使用java在浮点值中丢失精度

时间:2012-08-06 09:35:05

标签: java floating-point

在下面给出测试代码及其输出。当我从数值获得浮点值时,精度会丢失..任何人都可以告诉我为什么这种行为以及如何处理这个问题?

public static void main(String[] args)
    {
        try
        {
            java.lang.Number numberVal = 676543.21;
            float floatVal = numberVal.floatValue();
            System.out.println("Number value    : " + numberVal);
            System.out.println("float value     : " + floatVal);
            System.out.println("Float.MAX_VALUE : " + Float.MAX_VALUE);
            System.out.println("Is floatVal > Float.MAX_VALUE ? " + ( floatVal > Float.MAX_VALUE));
        }catch(Exception e)
        {
            e.printStackTrace();
        }
    }

输出:

    Number value    : 676543.21
    float value     : 676543.2
    Float.MAX_VALUE : 3.4028235E38
    Is floatVal > Float.MAX_VALUE ? false

为什么浮点值小于Float.MAX_VALUE?

5 个答案:

答案 0 :(得分:21)

float通常最多可达6位有效数字。您的电话号码是676543.21,其中有8位有效数字。您看到超过6位数的错误,并且这些错误很容易传播到您执行的计算越多的有效数字。如果您重视您的理智(或精确度),请使用double s。浮标甚至不能准确计算超过1000万。

现在,您有2位有效数字,这表明您有可能想要代表货币 - 不要。使用您自己的类,使用定点算法在内部表示值。

现在,至于Float.MAX_VAL是3.4028235E38,意思是3.4028235 * 10 ^ 38,这比你的值大10 ^ 32倍。注意那里的'E'?那是指数。

答案 1 :(得分:8)

我喜欢这些。但我会快速而轻松地做到这一点。

浮点数和小数(也就是浮点数)也没有精确地保存在内存中。但我不想在这里考虑浮动精度与精度问题,我只想指出一个链接 - http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm

至于你的另一个问题,lemme就是这样说的,因为花车以科学记数法存储。

floatVal = 6.765432E6 = 6.7 * 10^6
MAX_VALUE = 3.4E38 = 3.4 * 10^38

MAX_VALUE比您的浮点数大32个数量级。请随意查看此处http://steve.hollasch.net/cgindex/coding/ieeefloat.html

几个月前我花了很多时间来比较和解决一些FP问题......

比较浮点数时尝试使用小的delta。 也许这个链接可以帮助您http://introcs.cs.princeton.edu/java/91float/

答案 2 :(得分:7)

所有数据类型都有表示限制,因此存在限制的事实不应该令人惊讶。

float使用24位作为其“尾数”,其中包含所有有效数字。这意味着它具有大约7位数的精度(因为2 ^^ 24大约是1600万)

double使用53位的“尾数”,因此它可以准确地保存大约16位。

答案 3 :(得分:2)

3.4028235E38大于676543.2。 Float.MAX_VALUE是可以表示的最大浮点数。

答案 4 :(得分:0)

您键入的十进制文字默认为double,而不是float。 java.lang.Number默认也使用双精度数。如果你用java.lang.Number numberVal = 676543.21f;替换它,我会期望两者的精度损失相同。或者,将float floatVal = numberVal.floatValue();替换为double doubleVal = numberVal.doubleValue();,以免失去精确度。

编辑,作为一个例子,尝试运行:

Number num = 676543.21;
System.out.println(num); //676543.21
System.out.println(num.doubleValue()); //676543.21
System.out.println(num.floatValue()); //676543.2 <= loses the precision

查看类型精度的差异

Float.MAX_VALUE返回浮点数可以容纳的最大值。任何更高的将溢出。如果仔细观察,你会在文字表示中看到“E”。这是标准索引形式,'E'表示“乘以10乘以E后的任何数字的幂”(或在java-speak * pow(10,numberAfterE))