java - 如何正确地将 Java 中的 double 值设置为两位数

标签 java math double floor

我正在尝试将 Java 应用程序中的底数(不是舍入!)加倍到两位数。为此,我使用 DecimalFormat,但注意到对于接近零的负值,这些值不是四舍五入到 -0.01,而是四舍五入到 -0.00

public class MyTest {

    void formatAndPrint(double value) {
        DecimalFormat df = new DecimalFormat("0.00");
        df.setRoundingMode(RoundingMode.FLOOR);

        System.out.println(value + " => " + df.format(value));
    }

    @Test
    public void testFloor() {
        formatAndPrint(2.3289);  //  2.32
        formatAndPrint(2.3);     //  2.30
        formatAndPrint(-1.172);  // -1.18
        formatAndPrint(0.001);   //  0.00
        formatAndPrint(0.0001);  //  0.00
        formatAndPrint(-0.001);  // -0.01
        formatAndPrint(-0.0001); // -0.00 WRONG, expected: -0.01
    }
}

Math.floor(value * 100.0)/100.0 等其他解决方案不存在此问题,但存在其他问题,例如将 2.3 错误地设置为 2.29.

是否有适用于所有情况的适用于 Java 的地板解决方案?

最佳答案

BigDecimal 实现工作正常。

BigDecimal value = new BigDecimal(-0.0001);
value = value.setScale(2, BigDecimal.ROUND_FLOOR);
System.out.println(value.toPlainString());

输出:-0.01

2.3 仍将降至 2.29。这不是地板的结果,而是将 2.3 写成 double 的结果。 2.3 最接近的 64 位 IEEE754 表示是 2.29999...

在实例化 BigDecimal 时,您可以改为提供类似 new BigDecimal("2.3") 的字符串,这样不会导致此类错误。


编辑:正如@Hulk 提到的,您可以/应该使用 BigDecimal.valueOf() 代替,这将调用 Double.toString() 进行实例化。 Double.toString() 不使用 double 的精确值,而是“舍入”到最接近的唯一值。

Double JavaDoc:

There must be at least one digit to represent the fractional part, and beyond that as many, but only as many, more digits as are needed to uniquely distinguish the argument value from adjacent values of type double.

这是一个长值的小表(与 Double.longBitsToDouble(long) 及其 BigDecimalDouble.toString() 一起使用)同行:

long value            Double.toString()    new BigDecimal()
4612361558371493473 - 2.2999999999999976 - 2.299999999999997601918266809661872684955596923828125
4612361558371493474 - 2.299999999999998  - 2.29999999999999804600747665972448885440826416015625
4612361558371493475 - 2.2999999999999985 - 2.299999999999998490096686509787105023860931396484375
4612361558371493476 - 2.299999999999999  - 2.2999999999999989341858963598497211933135986328125
4612361558371493477 - 2.2999999999999994 - 2.299999999999999378275106209912337362766265869140625
4612361558371493478 - 2.3                - 2.29999999999999982236431605997495353221893310546875
4612361558371493479 - 2.3000000000000003 - 2.300000000000000266453525910037569701671600341796875
4612361558371493480 - 2.3000000000000007 - 2.300000000000000710542735760100185871124267578125
4612361558371493481 - 2.300000000000001  - 2.300000000000001154631945610162802040576934814453125
4612361558371493482 - 2.3000000000000016 - 2.30000000000000159872115546022541821002960205078125

关于java - 如何正确地将 Java 中的 double 值设置为两位数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49555627/

相关文章:

java - 使用java实现“俄罗斯农民乘法

Ada 中的 double ?

java - 如何在不修改元素的情况下将数据关联到集合中的元素?

java - HashMap:在onClick事件(Frame)期间通过键获取Key-Value

java - 为什么通过 Maven copy-resources 插件进行复制操作后文件会变大?

c# - 如何通过输入和输出值估计数学函数?

java - 如何在网页(jsp)中显示java类的代码

javascript - Ellipse - 鼠标碰撞检测

java - 需要帮助将字符串转换为数字类型(20,3)

swift - 检查 double 值是否为整数 - Swift