PSR*_*PSR 40 java floating-point
class Test{
public static void main(String[] args){
float f1=3.2f;
float f2=6.5f;
if(f1==3.2){
System.out.println("same");
}else{
System.out.println("different");
}
if(f2==6.5){
System.out.println("same");
}else{
System.out.println("different");
}
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
different
same
Run Code Online (Sandbox Code Playgroud)
为什么输出是这样的?我期望same在第一种情况下得到结果.
Abi*_*san 40
区别在于6.5可以在float和double中精确表示,而3.2在两种类型中都不能完全表示.两个最接近的近似值是不同的.
float和double之间的相等比较首先将float转换为double,然后比较两者.所以数据丢失了.
你不应该比较浮动或双打的平等; 因为你不能真正保证你指定给float或double的数字是准确的.
该舍入误差是浮点计算的特征.
将无限多个实数压缩成有限数量的比特需要近似表示.尽管存在无限多个整数,但在大多数程序中,整数计算的结果可以以32位存储.
相反,给定任何固定数量的位,大多数具有实数的计算将产生无法使用那么多位精确表示的量.因此,浮点计算的结果通常必须舍入,以便适应其有限表示.该舍入误差是浮点计算的特征.
sig*_*ned 25
它们都是IEEE浮点标准的不同部分的实现.A float是4字节宽,而a double是8字节宽.
根据经验,您可能更愿意double在大多数情况下使用,并且仅float在您有充分理由时使用.(与a float相反使用的一个很好的理由的例子double是"我知道我不需要那么精确,我需要在内存中存储一百万个.")还值得一提的是,很难证明你没有不需要double精确度.
此外,在比较浮点值是否相等时,您通常希望使用类似于Math.abs(a-b) < EPSILONwhere的内容a并且b是要比较的浮点值,并且EPSILON是一个小的浮点值1e-5.这样做的原因是浮点值很少编码它们"应该"的确切值 - 相反,它们通常编码的值非常接近 - 因此当您确定两个值是否相同时,您必须"斜视".
编辑:每个人都应该阅读以下链接@Kugathasan Abimaran:每个计算机科学家应该知道的关于浮点运算的更多信息!
要查看您正在处理的内容,可以使用Float和Double的toHexString方法:
class Test {
public static void main(String[] args) {
System.out.println("3.2F is: "+Float.toHexString(3.2F));
System.out.println("3.2 is: "+Double.toHexString(3.2));
System.out.println("6.5F is: "+Float.toHexString(6.5F));
System.out.println("6.5 is: "+Double.toHexString(6.5));
}
}
$ java Test
3.2F is: 0x1.99999ap1
3.2 is: 0x1.999999999999ap1
6.5F is: 0x1.ap2
6.5 is: 0x1.ap2
Run Code Online (Sandbox Code Playgroud)
通常,如果数字等于A*2 ^ B,则数字具有精确表示,其中A和B是整数,其允许值由语言规范设置(并且double具有更多允许值).
在这种情况下,
6.5 = 13/2
=(1 + 10/16 )*4 =(1 + a/16)*2 ^ 2 == 0x1.ap2,而3.2 = 16/5 =(1 + 9/16 + 9/16 ^ 2 + 9/16 ^ 3 + ...)*2 ^ 1 == 0x1.999...P1.
但Java只能保存有限数量的数字,所以它会削减.999...在某个时候关闭.(你可能记得从数学上看0.999 ... = 1.那是在基数10中.在基数16中,它将是0.fff ... = 1.)