我正在编写一个带浮动的示例程序,但突然发生了一些奇怪的事情。我真的很感激,如果有人可以解释为什么我会在我的计划中面对这样的行为。
package Programs;
public class FloatTest {
/**
* @param args
*/
public static void main(String[] args) {
float f1 = (float) 3.2;
float f2 = (float) 6.5;
if (f1 == 3.2) {
System.out.println(f1 + " same");
} else {
System.out.println(f1 + " different");
}
if (f2 == 6.5) {
System.out.println(f2 + " same");
} else {
System.out.println(f2 + " different");
}
}
}
输出:
3.2 different
6.5 same
在做了一些改变f2值的测试后,我注意到f2>我得到了意想不到的结果。 3.5为什么?任何意见都非常感谢。
由于
答案 0 :(得分:5)
我将亲自尝试一下技术解释。由于这些值最终以二进制格式存储,因此在某些条件下精度将会丢失。
6.5
不应失去任何精度,因为它可以转换为二进制值110.1
。
3.2
不能像这样干净地转换,因为.2
的二进制表示变得不合理。这将是11.00110011..
的内容。这种情况最多只能在转换为另一种方式时四舍五入为3.2
。
如果有人能够验证我在说什么,那就太棒了 - 这是基于对Java如何处理这个问题的公认有限的知识。
答案 1 :(得分:3)
由于表示浮点变量的方式,并非所有数字都可以精确表示。事实上,很少有人可以。
写作时
float f1 = (float) 3.2;
并将其与3.2进行比较,您将f1
(一个float
)与3.2
进行比较(double
:3.2
作为文字输入是隐含的一个double
类型)。在您的语句f1 == 3.2
中,f1
被隐式转换为double
,但到那时,精度已经丢失。这是因为3.2
是无法准确表示的数字之一,double
比float
更能做到这一点。
巧合的是,6.5
是可以精确表达的数字之一(double
或float
),这是由于Java用来表示浮点的内部方案。这就是为什么,在您的情况下,f2 == 6.5
是true
。
答案 2 :(得分:2)
有很多方法可以解决这个问题,
出现此问题是因为无法表示小数值 准确地在二进制文件中。
- 具有公差值并检查差异是否小于公差值。
- 将它乘以10/100 / ...然后比较数字
- 查看BigDecimal。
醇>
答案 3 :(得分:2)
:)啊,IEEE754和JVM与浮点数的区别。简而言之,6.5与6.5的浮点值不同。 6.5 == 6.5f会起作用,但你更了解你在做什么!请阅读http://en.wikipedia.org/wiki/IEEE_floating_point,同时注意'strictfp'关键字,以强制跨平台强制IEEE754行为。这里有很多事情需要考虑,舍入行为,预测顺序,JVM差异等。不是整数或长期的东西都是出乎意料的棘手。
您正在操纵数字的二进制表示,该数字具有适用于许多类型的数学计算的精度,其中不需要无限精确的答案。对于许多工程和财务系统,特别是那些涉及乘法或分数的系统,这是不可接受的。您需要重新计算您的会计(使用理解金钱和小数的金融类),(例如以便士计算金钱),而对于工程,您可能需要使用BigDecimal或具有特定舍入行为,percision等的相关类。
再举一个例子,浮点值为1/3 + 1/3 + 1/3,可能也可能不等于1.因为组成数据的数字表示的1和0并不精确为1 / 3。在我的特定平台(JVM 1.6 Windows 64位)上,它是1.0,但它可能不在您的平台上。
答案 4 :(得分:2)
使用演员if (f1 == (float)3.2) {
然后它会起作用。
像3.2
这样的文字是double类型,你正在将float与double进行比较,这会导致这样的事情发生。
@JNL指出
出现此问题是因为无法在二进制文件中准确表示十进制值。
答案 5 :(得分:1)
虽然看起来似乎不正确,但是当你运行
时float f1 = (float) 3.2;
f1
并不等于3.2。如上所述,有几种方法可以解决这个问题。