在 Java 中使用 == 比较浮点数有什么问题?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1088216/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What's wrong with using == to compare floats in Java?
提问by user128807
According to this java.sun page==
is the equality comparison operator for floating point numbers in Java.
根据这个 java.sun 页面==
是 Java 中浮点数的相等比较运算符。
However, when I type this code:
但是,当我键入此代码时:
if(sectionID == currentSectionID)
into my editor and run static analysis, I get: "JAVA0078 Floating point values compared with =="
进入我的编辑器并运行静态分析,我得到:“JAVA0078 与 == 相比的浮点值”
What is wrong with using ==
to compare floating point values? What is the correct way to do it?
什么是错的使用==
比较浮点值?正确的做法是什么?
回答by Paul Sonier
Floating point values can be off by a little bit, so they may not report as exactly equal. For example, setting a float to "6.1" and then printing it out again, you may get a reported value of something like "6.099999904632568359375". This is fundamental to the way floats work; therefore, you don't want to compare them using equality, but rather comparison within a range, that is, if the diff of the float to the number you want to compare it to is less than a certain absolute value.
浮点值可能会偏离一点点,因此它们可能不会报告为完全相等。例如,将浮点数设置为“6.1”然后再次打印出来,您可能会得到类似“6.099999904632568359375”的报告值。这是浮动工作方式的基础;因此,您不想使用相等来比较它们,而是在一个范围内进行比较,也就是说,如果浮点数与要比较的数字的差异小于某个绝对值。
Thisarticle on the Register gives a good overview of why this is the case; useful and interesting reading.
登记册上的这篇文章很好地概述了为什么会这样;有用和有趣的阅读。
回答by omerkudat
First of all, are they float or Float? If one of them is a Float, you should use the equals() method. Also, probably best to use the static Float.compare method.
首先,它们是浮动的还是浮动的?如果其中之一是 Float,则应使用 equals() 方法。此外,最好使用静态 Float.compare 方法。
回答by Eric Wilson
Foating point values are not reliable, due to roundoff error.
由于舍入误差,泡沫点值不可靠。
As such they should probably not be used for as key values, such as sectionID. Use integers instead, or long
if int
doesn't contain enough possible values.
因此,它们可能不应该用作键值,例如 sectionID。改用整数,或者long
如果int
不包含足够的可能值。
回答by Eric
The correct way would be
正确的方法是
java.lang.Float.compare(float1, float2)
回答by Victor
the correct way to test floats for 'equality' is:
测试浮点数是否“相等”的正确方法是:
if(Math.abs(sectionID - currentSectionID) < epsilon)
where epsilon is a very small number like 0.00000001, depending on the desired precision.
其中 epsilon 是一个非常小的数字,如 0.00000001,具体取决于所需的精度。
回答by KM.
you may want it to be ==, but 123.4444444444443 != 123.4444444444442
你可能希望它是 ==,但 123.4444444444443 != 123.44444444444442
回答by Tom Hawtin - tackline
In addition to previous answers, you should be aware that there are strange behaviours associated with -0.0f
and +0.0f
(they are ==
but not equals
) and Float.NaN
(it is equals
but not ==
) (hope I've got that right - argh, don't do it!).
除了之前的答案之外,您还应该意识到还有与-0.0f
和+0.0f
(它们是==
但不是equals
)和Float.NaN
(是equals
但不是==
)相关的奇怪行为(希望我说对了 - 啊,不要这样做!)。
Edit: Let's check!
编辑:让我们检查一下!
import static java.lang.Float.NaN;
public class Fl {
public static void main(String[] args) {
System.err.println( -0.0f == 0.0f); // true
System.err.println(new Float(-0.0f).equals(new Float(0.0f))); // false
System.err.println( NaN == NaN); // false
System.err.println(new Float( NaN).equals(new Float( NaN))); // true
}
}
Welcome to IEEE/754.
欢迎使用 IEEE/754。
回答by Adam Goode
Here is a very long (but hopefully useful) discussion about this and many other floating point issues you may encounter: What Every Computer Scientist Should Know About Floating-Point Arithmetic
这里有一个很长(但希望有用)的讨论,关于这个问题以及您可能遇到的许多其他浮点问题:What Every Computer Scientist should Know About Floating-Point Arithmetic
回答by Bill K
Just to give the reason behind what everyone else is saying.
只是为了给出其他人所说的背后的原因。
The binary representation of a float is kind of annoying.
浮点数的二进制表示有点烦人。
In binary, most programmers know the correlation between 1b=1d, 10b=2d, 100b=4d, 1000b=8d
在二进制中,大多数程序员都知道 1b=1d、10b=2d、100b=4d、1000b=8d 之间的相关性
Well it works the other way too.
好吧,它也适用于其他方式。
.1b=.5d, .01b=.25d, .001b=.125, ...
.1b=.5d, .01b=.25d, .001b=.125, ...
The problem is that there is no exact way to represent most decimal numbers like .1, .2, .3, etc. All you can do is approximate in binary. The system does a little fudge-rounding when the numbers print so that it displays .1 instead of .10000000000001 or .999999999999 (which are probably just as close to the stored representation as .1 is)
问题是没有确切的方法来表示大多数十进制数,如 .1、.2、.3 等。你所能做的只是用二进制近似。系统在打印数字时会进行一些模糊处理,以便显示 0.1 而不是 .10000000000001 或 .999999999999(这可能与存储的表示形式一样接近 .1)
Edit from comment: The reason this is a problem is our expectations. We fully expect 2/3 to be fudged at some point when we convert it to decimal, either .7 or .67 or .666667.. But we don't automatically expect .1 to be rounded in the same way as 2/3--and that's exactly what's happening.
评论编辑:这是一个问题的原因是我们的期望。当我们将 2/3 转换为十进制时,我们完全希望 2/3 会在某个时候被篡改,无论是 .7 或 .67 还是 .666667。但我们不会自动期望 .1 以与 2/3 相同的方式四舍五入——这正是正在发生的事情。
By the way, if you are curious the number it stores internally is a pure binary representation using a binary "Scientific Notation". So if you told it to store the decimal number 10.75d, it would store 1010b for the 10, and .11b for the decimal. So it would store .101011 then it saves a few bits at the end to say: Move the decimal point four places right.
顺便说一句,如果您好奇它内部存储的数字是使用二进制“科学记数法”的纯二进制表示。因此,如果您告诉它存储十进制数 10.75d,它将存储 1010b 表示 10,而 .11b 表示十进制数。所以它会存储 .101011 然后它在最后保存几位说:将小数点向右移动四位。
(Although technically it's no longer a decimal point, it's now a binary point, but that terminology wouldn't have made things more understandable for most people who would find this answer of any use.)
(虽然从技术上讲它不再是小数点,它现在是一个二进制小数点,但是对于大多数会找到任何用处的答案的人来说,该术语不会使事情更容易理解。)
回答by AakashM
What is wrong with using == to compare floating point values?
使用 == 比较浮点值有什么问题?
Because it's not true that 0.1 + 0.2 == 0.3
因为这不是真的 0.1 + 0.2 == 0.3