繁体   English   中英

是否存在错误评估为略低于 5 或 0 的浮点数?

[英]Does a float exist that wrongly evaluates to slightly below .5 or .0?

我正在使用它来获得正确舍入的 integer 划分:

Math.round((float)dividend/(float)divisor)

除以 0 已在其他地方处理。 除此之外,这会失败吗?
我可以想象那个除法的结果是一个应该something.5的浮点数,但实际上计算为something.4999997左右。 这样的浮标存在吗?

为了自己检查这一点,我尝试打印出所有接近 5 的浮点数,如下所示:

for(int i=Integer.MIN_VALUE+1; i!=Integer.MIN_VALUE; i++){
   float f=Float.intBitsToFloat(i);
   if ((f>(int)f+0.4999999 && f<(int)f+0.5000001 && f!=(int)f+0.5)
     ||(f<(int)f-0.4999999 && f>(int)f-0.5000001 && f!=(int)f-0.5)){
      System.out.println(Float.toString(f));
   }
}

(手动检查Integer.MIN_VALUE 。)

那只打印:

-0.4999999
-0.49999994
-0.49999997
-0.50000006
0.4999999
0.49999994
0.49999997
0.50000006

由于-0.50.5肯定是浮点数,这意味着不存在这样的浮点数。 但也许我的范围太小并且有问题的数字超出了范围。 无论如何,我想要第二个意见,所以我在这里问,也许有人对 IEEE754 有先进的内部知识,并有证据证明为什么这绝对不会发生。

将范围扩大一个数字有这个结果,这些数字都没有回答这个问题。

相关问题: something.99999怎么样? 一个类似的测试这个结果 所有这些浮点数都与浮点数不同,因为它们的确切整数。

简短的回答:是的,它可能会失败。

更长的答案:您的问题完全取决于您正在考虑的 integer 和浮点格式 - 这不仅仅是关于 IEEE 754 的问题。

例如,如果您正在查看 IEEE 754 “双精度” binary64 类型(假设您的语言将其称为double ),并且仅考虑固定宽度的 32 位 integer (有符号或无符号),那么每个这样的 integer 都是完全可以表示为 binary64 浮点数,因此在这种情况下转换为double不会改变值,并且您确实可以依赖(double)x / (double)y根据当前舍入模式正确舍入(假设任何语言您正在使用保证根据当前舍入模式正确舍入除法,例如因为它保证遵循 IEEE 754 标准)。

另一方面,如果float是 IEEE 754 binary32“单精度”浮点类型,则有 32 位有符号整数xy的示例,使得x可以被y整除(因此商很小,完全可表示,整数),但(float)x / (float)y给出不同的值。 一个这样的例子是x = 296852655y = 59370531 那么x / y正好是5 ,但是最接近x的 binary32 浮点数是296852640.0 ,最接近y的 binary32 浮点数是59370532.0 ,最接近商296852640.0 / 59370532.05.0浮点数正好是4.999999523162841796875 ., 1 ulp

binary64 “双精度” IEEE 754 浮点和 64 位整数存在类似示例。 For example, with x = 2135497568948934666 and y = 305071081278419238 , both x and y fit into a signed 64-bit integer type, x / y is exactly 7 , but (double)x / (double)y is 6.99999999999999911182158029987476766109466552734375 , again 1 ulp away从确切的结果。

这里还有几个更接近您在标题中提出的问题的示例:再次假设 IEEE 754 单精度算术,采用x = 592534758y = 395023172 ,它们都可以表示为带符号的 32 位整数。 那么x / y正好是1.5 ,但(float)x / float(y)1.50000011920928955078125 对于舍入相反的示例,如果x = 1418199327y = 945466218 ,则x / y1.5并且(float)x / (float)y1.49999988079071044921875

然而,值得一提的是0.5不存在这样的例子:如果xy是 32 位有符号整数,使得x / y正好是0.5 ,那么 than 意味着y正好是x的两倍,意味着(float)y将恰好是(float)x因为如果(float)x是最接近x的可表示值,那么2.0 * (float)x必须是最接近2.0 * x的可表示值)。 因此,在这种情况下, (float)x / (float)y也保证为0.5

您在问什么并不完全清楚:“失败”是什么意思? 我想您想知道是否有可能在您的第一行中存在 integer 值作为除数和除数,并且由于舍入问题,结果不是您所期望的。

我认为这是可能的。 在下面的代码中 999,999,999/2,000,000,000 略小于 0.5,因此我们预计结果为 0.0。 但是在 Java 中,结果是 1.0。 如果你做 Math.round(dividend/divisor) 你做 integer 除法并得到正确的答案。

int dividend = 999999999;
int divisor = 2000000000;
float result = Math.round((float)dividend/(float)divisor);
System.out.println(result);  // 1.0

这是你的意思吗? 这里的问题不在于没有正确舍入的浮点数,而是在将 integer 转换为浮点数时,您会失去准确性。 float(dividend) 实际上是 1.0E9。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM