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 + -
显示快捷键?