为什么在float中存储的相同值与Java中的double之间存在差异?

Ana*_*abu 5 java math floating-point precision

我期望以下代码生成:" Both are equal",但我得到了" Both are NOT equal":

float a=1.3f;
double b=1.3;
if(a==b)
{
 System.out.println("Both are equal");
}
else{
 System.out.println("Both are NOT equal");
}
Run Code Online (Sandbox Code Playgroud)

这是什么原因?

Jon*_*eet 26

这是因为1.3的最接近的浮点值与1.3的最接近的double值不同.这两个值都不是精确的 1.3 - 无法在非循环二进制表示中精确表示.

为了对发生这种情况的原因有不同的理解,假设我们有两个十进制浮点类型 - decimal5并且decimal10,其中数字表示有效数字的数量.现在假设我们试图将"三分之一"的值分配给它们.你最终会

decimal5 oneThird = 0.33333
decimal10 oneThird = 0.3333333333
Run Code Online (Sandbox Code Playgroud)

显然,这些价值观并不平等.这里完全相同,只是涉及不同的基础.

但是,如果将值限制为不太精确的类型,在这种特定情况下您会发现它们相等:

double d = 1.3d;
float f = 1.3f;
System.out.println((float) d == f); // Prints true
Run Code Online (Sandbox Code Playgroud)

但是,并不能保证这种情况.有时,从十进制文字到双重表示的近似,然后将该值近似到浮点表示,最终不如直线小数浮点近似精确.这个例子就是1.0000001788139343(感谢stephentyrone找到这个例子).

有些更安全,你可以在双打之间进行比较,但float在原始作业中使用文字:

double d = 1.3f;
float f = 1.3f;
System.out.println(d == f); // Prints true
Run Code Online (Sandbox Code Playgroud)

在后一种情况下,有点像说:

decimal10 oneThird = 0.3333300000
Run Code Online (Sandbox Code Playgroud)

但是,正如评论中指出的那样,您几乎肯定应该将浮点值与==进行比较.这几乎从来都不是正确的事,因为正是这样的事情.通常,如果你想比较两个值,你需要进行某种"模糊"的相等比较,检查这两个数字是否"足够接近"以达到你的目的.有关更多信息,请参阅Java Traps:double页面.

如果您确实需要检查绝对相等性,那通常表明您应该首先使用不同的数字格式 - 例如,您可能应该使用的财务数据BigDecimal.


bob*_*mcr 11

float是单精度浮点数.double是双精度浮点数.更多细节:http://www.concentric.net/~Ttwang/tech/javafloat.htm

注意:检查浮点数的精确相等是个坏主意.大多数情况下,您希望根据增量或公差值进行比较.

例如:

float a = 1.3f;
double b = 1.3;
float delta = 0.000001f;
if (Math.abs(a - b) < delta)
{
    System.out.println("Close enough!");
}
else
{
    System.out.println("Not very close!");
}
Run Code Online (Sandbox Code Playgroud)

某些数字不能完全以浮点表示(例如0.01),因此在比较相等性时可能会得到意外结果.