目前我有这个方法:
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 为基数的数学运算。
那么如何才能正确完成这项检查呢?
我想得到一个双精度值的字符串表示,然后用正则表达式检查它——但这感觉很奇怪。
编辑: 感谢所有的答案。在某些情况下,我真的得到了双倍的回报,对于这些情况,我实施了以下措施:
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;
我得到的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);
这也适用于无法以二进制格式精确表示的值。