【问题标题】:Float and BigDecimal precision differenceFloat 和 BigDecimal 精度差异
【发布时间】:2012-07-18 11:03:07
【问题描述】:
public static void main(String[] args) {
    // TODO Auto-generated method stub
    BigDecimal foo,foo1;
    foo=BigDecimal.valueOf(3.1);
    foo1=BigDecimal.valueOf(3.1f);

    System.out.println(foo);
    System.out.println(foo1);

}

结果:
3.1
3.0999999046325684

为什么他们是不同的结果?我正在使用JDK1.7.0_03

【问题讨论】:

标签: java floating-point bigdecimal


【解决方案1】:

由于我想分享的菜鸟错误,我遇到了类似的问题:

BigDecimal bd = new BigDecimal(float); 

这给了我不想要的额外精度,并将其设置为 String 修复了它...

但是,我是这样做的:

BigDecimal bd = new BigDecimal(float);
bd.setScale(2, RoundingMode.HALF_UP);

新手错误。我应该这样做的。

bd = bd.setScale(2, RoundingMode.HALF_UP);

【讨论】:

    【解决方案2】:

    问题在于,对于浮点数和双精度数,您分别使用 32 位和 64 位来表示数字的整数部分和小数部分。当您尝试表示一个小数值时,问题就出现了,而该小数值实际上并没有以二进制位精确表示十进制。

    以 0.1 为例,没有办法以 2 为基数准确表示这一点,就像无法以 10 为基数准确表示 1/3 一样。

    所以java使用了一些技巧,所以当你说:

    float f = 3.1;
    System.out.println(f);
    

    它打印出正确的数字。但是,当您开始使用这些值进行算术运算时,最终会出现舍入错误。

    BigDecimal 是准确的,因为它使用不同的表示。它在内部存储一个 BigInteger(它使用一个 int[] 来表示巨大的数字)。然后它使用一个精度值来告诉它小数点后有多少个整数。

    例如,值 3.1 在 BigDecimal 中表示为 31,precision=1 出于这个原因,BigDecimal 不会遇到浮点数和双精度数的舍入问题。

    但是,当您使用浮点/双精度值初始化 BigDecimal 时,同样的舍入错误会导致它进入 BigDecimal 实例。这就是为什么建议使用 String 来构造值的原因。

    【讨论】:

      【解决方案3】:

      float 和double 是不同的类型,具有不同的精度。

      BigDecimal.valueOf(double) 可以纠正double 中的表示错误,但不能纠正float 中的表示错误

      恕我直言,不要使用float,除非您有非常理由这样做。

      【讨论】:

        【解决方案4】:

        3.1 定义了一个double,而3.1f 定义了一个float。您看到的是float 表示该值的问题(浮点使用“仅”32 位和双 64 位)。

        如果您想完全使用BigDecimal 定义3.1,请使用String 构造函数:

        BigDecimal foo = new BigDecimal("3.1");
        System.out.println(foo);
        

        输出:

        3.1
        

        【讨论】:

        • 那么,是float的问题还是Bug?我应该使用 double 来避免错误吗?
        • OP,这些不是错误。请阅读其他人在您的问题下方提出的建议。对这些问题的认识是 Programming 101。
        • 也就是说,最好的方法是使用String 而不是double 或 float。
        • 谢谢大家,所有的答案都对我很有帮助,但我只能选择1个最佳答案。我选择dacwe的答案,因为我只是一个简单的程序员,知道如何解决对我来说就足够了。
        猜你喜欢
        • 1970-01-01
        • 2016-05-27
        • 1970-01-01
        • 2012-06-24
        • 2013-03-05
        • 2015-08-31
        • 2020-07-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多