当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何检查double是否最多有n个小数位?》经验,为你挑选了2个好方法。

目前我有这个方法:

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值的字符串表示,然后用regexp检查 - 但这感觉很奇怪.

编辑: 谢谢你的所有答案.在某些情况下,我真的得到了一个双倍,在这些情况下,我实现了以下内容:

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的数字单元格的值,我可以得到一个精确的表示时,我立即格式化doubleDecimalFormat:

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

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



1> Ken Gentle..:

如果您的目标是在小数点右侧表示一个具有正确n个有效数字的数字,则BigDecimal是要使用的类.

不可变的,任意精度的带符号十进制数.BigDecimal由任意精度整数非标度值和32位整数标度组成.如果为零或正数,则比例是小数点右侧的位数.如果是负数,则将数字的未缩放值乘以10来表示比例的否定.因此,BigDecimal表示的数字的值是(unscaledValue×10-scale).

scale可以通过setScale(int)设置



2> David Schmit..:

测试失败,因为您已达到二进制浮点表示的精度,大约是16位数,具有IEEE754双精度.乘以649632196443.4279乘以10000会截断二进制表示,导致后续舍入和除法时出错,从而使函数的结果完全失效.

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

更好的方法是检查n+1小数位是否低于某个阈值.如果d - round(d)小于epsilon(见限制),则十进制表示d没有显着的小数位.同样,如果(d - round(d)) * 10^n小于epsilon,则d可以具有最多n显着位置.

使用乔恩斯基特的DoubleConverter检查,其中情况d不够准确抱着你正在寻找的小数位.

推荐阅读
勤奋的瞌睡猪_715
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有