从整数/整数/长整型/长整型转换时双等式布尔值的精度



如果将以下数据类型转换为Double.equals()测试)或double==测试),则相等性检验的准确性是多少?

  • Long
  • long
  • Integer
  • int

如果等式检验仅在可能的LonglongIntegerint值范围内准确,那么这个精度的精确范围是多少?

例如;

Long longTest = Long.MAX_VALUE;
Long longTest2 = Long.MAX_VALUE;
double doubleTest = (double) longTest;
double doubleTest2 = (double) longTest2;
if(doubleTest == doubleTest2) //Is this accurate? 
     return true;

可以这样想:

双倍和长整型都占用 64 位存储空间。对于浮点数和整数,它是 32。

由于在指数上花费了一些位,因此在将长整型转换为双精度或将整数转换为浮点数时,您将始终面临失去精度的危险。

唯一的保存是int ->双精度。

无论如何,对于您的示例:由于上述原因,双精度不能以绝对精度保存 Long.MAX_VALUE。这将是一个近似值。但是,近似值每次都应该相同,因此您的示例应返回 true。

尽管 Java 的创建者有可能为所有数值类型组合定义==重载,以便只有具有相同数值的东西才能比较相等[例如,这意味着没有float值比较等于 16777217],或者禁止在该运算符不会表现为等价关系的任何类型组合上使用==, 他们没有做这些事情。 相反,他们决定应该可以将操作数与基元类型的任何组合进行比较,无论这是否有意义,并且这种比较应该使用与任何其他上下文中相同的隐式转换(顺便说一句,我真的很不喜欢这个决定)。

因此,例如,longfloat之间的比较将通过执行近似转换为float并进行比较来执行,而不考虑转换中是否损失了任何精度。 floatdouble之间的比较将通过执行精确转换为double并进行比较来完成。 这导致 16777216.0f == 16777217,16777217 == 16777217.0,但 167772176.0f != 16777217.0。 有时人们可能想知道float是否是另一个值的最佳float表示形式,有时人们可能想知道它是否是确切的表示形式,但 Java 中的类型排名与==运算符回答的问题不一致。

几种情况...

如果两种类型都是包装器,则 equals 总是精确的 - 但请注意 equals 是类型敏感的(例如 Integer.equals(Long) 总是产生 false,无论值如何)。否则。。。

如果一种类型是包装器,而另一种是基元,则包装器将被取消装箱,并使用 == 语义进行比较,因为这两种类型从一开始就是原语。

基元 (==) 的相等性对于任何整数类型(字节、短整型、整型、长整型)都是精确的 - 较小的类型将被强制转换为较大的类型,然后进行比较。对于 char,其强制转换为较大的类型但未签名

与一个操作数相等 浮点类型(浮点型、双精度型)将另一种类型强制转换为浮点类型,在这种情况下可能会丢失精度。Float 可以精确表示具有 <= 24 个有效位的任何整数值,double 具有 53 位的相关精度(它由类型中的尾数位数决定,有关详细信息,请参阅IEEE754)。

所以基本上,float == (int) N 仅在(大约)abs(N) <= (1 <<23) 时才精确,而当 abs(N) <= (1 <<52) 时,double = (long) N 是精确的。如果整数类型中有更多有效位,则当类型转换为浮点数/或双精度时,最下面的位将丢失。由于 double 的尾数位多于 int 可以有重要的位,因此 double 和 int 之间的比较在这方面是精确的。

最新更新