目前我有这个方法:
static boolean checkDecimalPlaces(double d, int decimalPlaces){
if (d==0) return true;
double multiplier = Math.pow(10, decimalPlaces);
double check = d * multiplier;
check = Math.round(check);
check = check/multiplier;
return (d==check);
}
但这种方法失败了checkDecmialPlaces(649632196443.4279, 4)
可能是因为我对以 2 为底的数字进行以 10 为底的数学运算。
那么如何才能正确地进行这项检查呢?
我想获取双精度值的字符串表示形式,然后使用正则表达式进行检查 - 但这感觉很奇怪。
EDIT:感谢所有的答案。在某些情况下,我确实得到了双倍,对于这些情况,我实施了以下操作:
private static boolean checkDecimalPlaces(double d, int decimalPlaces) {
if (d == 0) return true;
final double epsilon = Math.pow(10.0, ((decimalPlaces + 1) * -1));
double multiplier = Math.pow(10, decimalPlaces);
double check = d * multiplier;
long checkLong = (long) Math.abs(check);
check = checkLong / multiplier;
double e = Math.abs(d - check);
return e < epsilon;
}
我改变了round
到截断。看来计算是在round
过多地增加了不准确性。至少在失败的测试用例中是这样。
正如你们中的一些人指出的,如果我可以得到我应该使用的“真实”字符串输入BigDecimal
检查,所以我已经做了:
BigDecimal decimal = new BigDecimal(value);
BigDecimal checkDecimal = decimal.movePointRight(decimalPlaces);
return checkDecimal.scale() == 0;
The double
我得到的值来自读取 Excel 文件的 Apache POI API。我做了一些测试,发现虽然API返回double
当我立即格式化数字单元格的值时,我可以获得准确的表示double
与DecimalFormat
:
DecimalFormat decimalFormat = new DecimalFormat();
decimalFormat.setMaximumIntegerDigits(Integer.MAX_VALUE);
// don't use grouping for numeric-type cells
decimalFormat.setGroupingUsed(false);
decimalFormat.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.US));
value = decimalFormat.format(numericValue);
这也适用于无法以二进制格式精确表示的值。