in odps-sdk/odps-sdk-core/src/main/java/com/aliyun/odps/tunnel/hasher/DefaultHashFactory.java [407:486]
private BigInteger castBigDecimal2BigInteger(String input, int resultPrecision, int resultScale)
throws IllegalArgumentException {
// trim
input = input.trim();
int len = input.length();
int ptr = 0;
// check negative
boolean isNegative = false;
if (len > 0) {
if (input.charAt(ptr) == '-') {
isNegative = true;
ptr++;
len--;
} else if (input.charAt(ptr) == '+') {
ptr++;
len--;
}
}
// ignore leading zeros
while (len > 0 && input.charAt(ptr) == '0') {
ptr++;
len--;
}
// check decimal format and analyze precison and scale
int valueScale = 0;
boolean foundDot = false;
boolean foundExponent = false;
for (int i = 0; i < len; i++) {
char c = input.charAt(ptr + i);
if (Character.isDigit(c)) {
if (foundDot) {
valueScale++;
}
} else if (c == '.' && !foundDot) {
foundDot = true;
} else if ((c == 'e' || c == 'E') && i + 1 < len) {
foundExponent = true;
int exponent = Integer.parseInt(input.substring(ptr + i + 1));
valueScale -= exponent;
len = ptr + i;
break;
} else {
throw new IllegalArgumentException("Invalid decimal format: " + input);
}
}
// get result value
String
numberWithoutExponent =
foundExponent ? input.substring(ptr, len) : input.substring(ptr);
if (foundDot) {
numberWithoutExponent = numberWithoutExponent.replace(".", "");
}
if (numberWithoutExponent.isEmpty()) {
return BigInteger.ZERO;
}
BigInteger tmpResult = new BigInteger(numberWithoutExponent);
if (valueScale > resultScale) {
tmpResult = tmpResult.divide(BigInteger.TEN.pow(valueScale - resultScale));
if (numberWithoutExponent.charAt(
numberWithoutExponent.length() - (valueScale - resultScale)) >= '5') {
tmpResult = tmpResult.add(BigInteger.ONE);
}
} else if (valueScale < resultScale) {
tmpResult = tmpResult.multiply(BigInteger.TEN.pow(resultScale - valueScale));
}
if (isNegative) {
tmpResult = tmpResult.negate();
}
// TODO: check overflow
// if (tmpResult.toString().length() - (isNegative ? 1 : 0) > resultPrecision) {
// throw new IllegalArgumentException("Result precision overflow.");
// }
return tmpResult;
}