java - 如何检查 double 是否最多有 n 位小数?

标签 java floating-point decimal

目前我有这个方法:

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 的数学计算。

那么如何才能正确完成这项检查呢?

我想获取 double 值的字符串表示形式,然后使用正则表达式对其进行检查 - 但感觉很奇怪。

编辑: 感谢所有的答案。在某些情况下,我真的得到了一个双倍,对于这些情况,我实现了以下操作:

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 值,但当我立即使用 DecimalFormat 格式化 double 时,我可以获得准确的表示:

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);

这也适用于无法以二进制格式准确表示的值。

最佳答案

测试失败,因为您已经达到了二进制浮点表示的精度,即 IEEE754 double precision 大约为 16 位数字。 .将 649632196443.4279 乘以 10000 将截断二进制表示形式,导致之后舍入和除法时出错,从而使您的函数结果完全无效。

有关详细信息,请参阅 http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

更好的方法是检查 n+1 小数位是否低于某个阈值。如果 d - round(d) 小于 epsilon (参见 limit ),d 的十进制表示没有有效的小数位。类似地,如果 (d - round(d)) * 10^n 小于 epsilon,d 最多可以有 n 有效位置。

使用Jon SkeetDoubleConverter检查 d 不够准确以保留您要查找的小数位的情况。

关于java - 如何检查 double 是否最多有 n 位小数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/264937/

相关文章:

c++ - C++中的整数到十六进制字符串

python - 19 位长整数的截断问题

java - 如何使用 IntelliJ 和 Maven 安装库 Deeplearning4j?

java - 使用 tomcat 在 ubuntu 10.10 中运行 Servlet

python - int() 和 float() 的行为不一致

c - 注意 : expected ‘float (*)[100]’ but argument is of type ‘float (*)[100][100]’

java - 如何在intellij上正确编译jnativehook?

java - 当你在java中调用pack()时,有没有办法阻止JFrame调整大小?

python - 浮点值作为字典键

java - 如何让java在除法时产生小数点