funutil.java

来自「数据仓库展示程序」· Java 代码 · 共 1,808 行 · 第 1/5 页

JAVA
1,808
字号
        }

    }

    /**
     * Handles TopSum, TopPercent, BottomSum, BottomPercent by
     * evaluating members, sorting appropriately, and returning a
     * truncated list of members
     */
    static Object topOrBottom(Evaluator evaluator,
                              List members,
                              ExpBase exp,
                              boolean isTop,
                              boolean isPercent,
                              double target) {
        Map mapMemberToValue = evaluateMembers(evaluator, exp, members, false);
        Comparator comparator = new BreakMemberComparator(mapMemberToValue, isTop);
        Collections.sort(members, comparator);
        if (isPercent) {
            toPercent(members, mapMemberToValue);
        }
        double runningTotal = 0;
        int numMembers = members.size();
        int nullCount = 0;
        for (int i = 0; i < numMembers; i++) {
            if (runningTotal >= target) {
                members = members.subList(0, i);
                break;
            }
            Object o = mapMemberToValue.get(members.get(i));
            if (o instanceof Number) {
                runningTotal += ((Number) o).doubleValue();
            } else if (o instanceof Exception) {
                // ignore the error
            } else if (o instanceof Util.NullCellValue) {
                nullCount++;
            } else {
                throw Util.newInternal("got " + o + " when expecting Number");
            }
        }

        // MSAS exhibits the following behavior. If the value of all members is
        // null, then the first (or last) member of the set is returned for percent
        // operations.
        if ((numMembers > 0) && isPercent && (nullCount == numMembers)) {
            return (isTop)
                ? members.subList(0, 1)
                : members.subList(numMembers - 1, numMembers);
        }
        return members;
    }

    /**
     * Decodes the syntactic type of an operator.
     *
     * @param flags A encoded string which represents an operator signature,
     *   as used by the <code>flags</code> parameter used to construct a
     *   {@link FunDefBase}.
     *
     * @return A {@link Syntax}
     */
    public static Syntax decodeSyntacticType(String flags) {
        char c = flags.charAt(0);
        switch (c) {
        case 'p':
            return Syntax.Property;
        case 'f':
            return Syntax.Function;
        case 'm':
            return Syntax.Method;
        case 'i':
            return Syntax.Infix;
        case 'P':
            return Syntax.Prefix;
        case 'I':
            return Syntax.Internal;
        default:
            throw newInternal(
                    "unknown syntax code '" + c + "' in string '" + flags + "'");
        }
    }

    /**
     * Decodes the signature of a function into a category code which describes
     * the return type of the operator.
     *
     * <p>For example, <code>decodeReturnType("fnx")</code> returns
     * <code>{@link Category#Numeric}</code>, indicating this function has a
     * numeric return value.
     *
     * @param flags The signature of an operator,
     *   as used by the <code>flags</code> parameter used to construct a
     *   {@link FunDefBase}.
     *
     * @return An array {@link Category} codes.
     */
    public static int decodeReturnType(String flags) {
        final int returnType = decodeType(flags, 1);
        if ((returnType & Category.Mask) != returnType) {
            throw newInternal("bad return code flag in flags '" + flags + "'");
        }
        return returnType;
    }

    /**
     * Decodes the <code>offset</code>th character of an encoded method
     * signature into a type category.
     *
     * <p>The codes are:
     * <table border="1">
     *
     * <tr><td>a</td><td>{@link Category#Array}</td></tr>
     *
     * <tr><td>d</td><td>{@link Category#Dimension}</td></tr>
     *
     * <tr><td>h</td><td>{@link Category#Hierarchy}</td></tr>
     *
     * <tr><td>l</td><td>{@link Category#Level}</td></tr>
     *
     * <tr><td>b</td><td>{@link Category#Logical}</td></tr>
     *
     * <tr><td>m</td><td>{@link Category#Member}</td></tr>
     *
     * <tr><td>N</td><td>Constant {@link Category#Numeric}</td></tr>
     *
     * <tr><td>n</td><td>{@link Category#Numeric}</td></tr>
     *
     * <tr><td>x</td><td>{@link Category#Set}</td></tr>
     *
     * <tr><td>#</td><td>Constant {@link Category#String}</td></tr>
     *
     * <tr><td>S</td><td>{@link Category#String}</td></tr>
     *
     * <tr><td>t</td><td>{@link Category#Tuple}</td></tr>
     *
     * <tr><td>v</td><td>{@link Category#Value}</td></tr>
     *
     * <tr><td>y</td><td>{@link Category#Symbol}</td></tr>
     *
     * </table>
     *
     * @param flags Encoded signature string
     * @param offset 0-based offset of character within string
     * @return A {@link Category}
     */
    public static int decodeType(String flags, int offset) {
        char c = flags.charAt(offset);
        switch (c) {
        case 'a':
            return Category.Array;
        case 'd':
            return Category.Dimension;
        case 'h':
            return Category.Hierarchy;
        case 'l':
            return Category.Level;
        case 'b':
            return Category.Logical;
        case 'm':
            return Category.Member;
        case 'N':
            return Category.Numeric | Category.Constant;
        case 'n':
            return Category.Numeric;
        case 'I':
            return Category.Numeric | Category.Integer | Category.Constant;
        case 'i':
            return Category.Numeric | Category.Integer;
        case 'x':
            return Category.Set;
        case '#':
            return Category.String | Category.Constant;
        case 'S':
            return Category.String;
        case 't':
            return Category.Tuple;
        case 'v':
            return Category.Value;
        case 'y':
            return Category.Symbol;
        default:
            throw newInternal(
                    "unknown type code '" + c + "' in string '" + flags + "'");
        }
    }

    /**
     * Decodes a string of parameter types into an array of type codes.
     *
     * <p>Each character is decoded using {@link #decodeType(String, int)}.
     * For example, <code>decodeParameterTypes("nx")</code> returns
     * <code>{{@link Category#Numeric}, {@link Category#Set}}</code>.
     *
     * @param flags The signature of an operator,
     *   as used by the <code>flags</code> parameter used to construct a
     *   {@link FunDefBase}.
     *
     * @return An array {@link Category} codes.
     */
    public static int[] decodeParameterTypes(String flags) {
        int[] parameterTypes = new int[flags.length() - 2];
        for (int i = 0; i < parameterTypes.length; i++) {
            parameterTypes[i] = decodeType(flags, i + 2);
        }
        return parameterTypes;
    }

    /**
     * Sorts an array of values.
     */
    public static void sortValuesDesc(Object[] values) {
        Arrays.sort(values, DescendingValueComparator.instance);
    }

    /**
     * Binary searches an array of values.
     */
    public static int searchValuesDesc(Object[] values, Object value) {
        return Arrays.binarySearch(
                values, value, DescendingValueComparator.instance);
    }

    /**
     * @param evaluator
     * @param members
     * @param exp
     * @return
     */
    static Object median(Evaluator evaluator, List members, ExpBase exp) {
        SetWrapper sw = evaluateSet(evaluator, members, exp);
        if (sw.errorCount > 0) {
            return new Double(Double.NaN);
        } else if (sw.v.size() == 0) {
            return Util.nullValue;
        }
        double[] asArray = new double[sw.v.size()];
        for (int i = 0; i < asArray.length; i++) {
            asArray[i] = ((Double) sw.v.get(i)).doubleValue();
        }
        Arrays.sort(asArray);

        /*
         * The median is defined as the value that has exactly the same
         * number of entries before it in the sorted list as after.
         * So, if the number of entries in the list is odd, the
         * median is the entry at (length-1)/2 (using zero-based indexes).
         * If the number of entries is even, the median is defined as the
         * arithmetic mean of the two numbers in the middle of the list, or
         * (entries[length/2 - 1] + entries[length/2]) / 2.
         */
        int length = asArray.length;
        Double result = ((length & 1) == 1)
            // The length is odd. Note that length/2 is an integer expression,
            // and it's positive so we save ourselves a divide...
            ? new Double(asArray[length >> 1])
            : new Double((asArray[(length >> 1) - 1] + asArray[length >> 1]) / 2.0);

        return result;
    }

    /**
     * Returns the member which lies upon a particular quartile according to a
     * given expression.
     *
     * @param evaluator Evaluator
     * @param members List of members
     * @param exp Expression to rank members
     * @param range Quartile (1, 2 or 3)
     *
     * @pre range >= 1 && range <= 3
     */
    static Object quartile(Evaluator evaluator,
                           List members,
                           ExpBase exp,
                           int range) {
        Util.assertPrecondition(range >= 1 && range <= 3, "range >= 1 && range <= 3");

        SetWrapper sw = evaluateSet(evaluator, members, exp);
        if (sw.errorCount > 0) {
            return new Double(Double.NaN);
        } else if (sw.v.size() == 0) {
            return Util.nullValue;
        }

        double[] asArray = new double[sw.v.size()];
        for (int i = 0; i < asArray.length; i++) {
            asArray[i] = ((Double) sw.v.get(i)).doubleValue();
        }

        Arrays.sort(asArray);
        // get a quartile, median is a second q
        double dm = (asArray.length * range) / 4;
        int median = (int) Math.floor(dm);
        return ((dm == median) && (median < asArray.length - 1))
            //have more elements
            ? new Double((asArray[median] + asArray[median+1])/2)
            : new Double(asArray[median]);
    }

    public static Object min(Evaluator evaluator, List members, Exp exp) {
        SetWrapper sw = evaluateSet(evaluator, members, (ExpBase) exp);
        if (sw.errorCount > 0) {
            return new Double(Double.NaN);
        } else if (sw.v.size() == 0) {
            return Util.nullValue;
        } else {
            double min = Double.MAX_VALUE;
            for (int i = 0; i < sw.v.size(); i++) {
                double iValue = ((Double) sw.v.get(i)).doubleValue();
                if (iValue < min) {
                    min = iValue;
                }
            }
            return new Double(min);
        }
    }

    public static Object max(Evaluator evaluator, List members, Exp exp) {
        SetWrapper sw = evaluateSet(evaluator, members, (ExpBase) exp);
        if (sw.errorCount > 0) {
            return new Double(Double.NaN);
        } else if (sw.v.size() == 0) {
            return Util.nullValue;
        } else {
            double max = Double.MIN_VALUE;
            for (int i = 0; i < sw.v.size(); i++) {
                double iValue = ((Double) sw.v.get(i)).doubleValue();
                if (iValue > max) {
                    max = iValue;
                }
            }
            return new Double(max);
        }
    }

    static Object var(Evaluator evaluator,
                      List members,
                      ExpBase exp,
                      boolean biased) {
        SetWrapper sw = evaluateSet(evaluator, members, exp);
        return _var(sw, biased);
    }

    private static Object _var(SetWrapper sw, boolean biased) {
        if (sw.errorCount > 0) {
            return new Double(Double.NaN);
        } else if (sw.v.size() == 0) {
            return Util.nullValue;
        } else {
            double stdev = 0.0;
            double avg = _avg(sw);
            for (int i = 0; i < sw.v.size(); i++) {
                stdev += Math.pow((((Double) sw.v.get(i)).doubleValue() - avg),2);
            }
            int n = sw.v.size();
            if (!biased) {
                n--;
            }
            return new Double(stdev / (double) n);
        }
    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?