da_*_*_zi 0 floating-point precision
由于精度,0.1 + 0.2不等于0.3大多数编程语言。然而,
var float a, float b
assert(a != 0 && b != 0)
if a / b == -1.0 {
// a, b are opposite numbers:
// abs(a) == abs(b) && (a > 0 && b < 0 || a < 0 && b > 0)
...
}
Run Code Online (Sandbox Code Playgroud)
如果非零并且是相反的数(它们的绝对值相同,但一个是正数,另一个是负数),它总是正确的吗?ab
或者我必须引入一个非常小的数字epsilon(例如1e-7)来消除错误:
if a / b >= -1.0 - epsilon && a / b <= -1.0 + epsilon
Run Code Online (Sandbox Code Playgroud)
a/b首先, = \xe2\x88\x921 \xe2\x87\x94 a= \xe2\x88\x92是不正确的b。正如问题中的示例代码所示,这不适用于a= 0, b= 0,因为a/b会产生 NaN。另一种情况是a= \xc2\xb1\xe2\x88\x9e, b= \xe2\x88\x93\xe2\x88\x9e,a/b也产生 NaN。
另一种情况发生在使用大于二的基数的格式中。考虑两位十进制格式。对于a= \xe2\x88\x921.0\xe2\x80\xa210 2和b= +9.9\xe2\x80\xa210 1,a/b是 \xe2\x88\x921.0101010\xe2\x80\xa6,并将其四舍五入 (四舍五入到两位数会产生 \xe2\x88\x921.0,a/b\xe2\x88\x921 也是如此。
在向上舍入或向零舍入的二进位格式中,取a= \xe2\x88\x921 和b= 大于 \xe2\x88\x921 的下一个可表示值,将为 生成 \xe2\x88\x921 a/b,如下所述。
排除这些情况(NaN 商、大于二的基数、在 \xe2\x88\x921 处向上舍入),确实 = \xe2 a/b\x88\x921 \xe2\x87\x94 a= \xe2\x88\x92 b。下面是一个证明。
考虑任何将有限数表示为 \xc2\xb1 d 0的浮点格式。d \xe2\x88\x921 d \xe2\x88\x922 \xe2\x80\xa6 d 1- p \xe2\x80\xa2 b e,其中b是固定底数,e是设定范围内的指数,p是精度(位数),数字d i是整数,且 0 \xe2\x89\xa4 d i < b。
\n对于不同大小的a和b,最接近的a/ b(注意是浮点运算a/b的计算结果,而/是除以 的实数商,没有浮点舍入)可以是 \xe2\x88\ x921 是如果和的大小是格式中的相邻数字,特别是如果, for , d i = b \ xe2\x88\x921, so = \xc2\xb1( b e +1 \xe2\x88\x92 be e + 1- p ),并且= \xe2\x88\x93 b e +1。然后/ = \xe2\x88\x921+ b - p )。在/ = \xe2\x88\x921+ b - p中,确切的结果 \xe2\x88\x921+ b - p是远离 \xe2\的完整 ULP(e = \xe2\x88\x921 指数区间) x88\x921,因此 的浮点结果将是 \xe2\x88\x921+ b - p。a/babababaabababa/b
然而,我们还必须考虑一种情况,其中a是 \xc2\xb1b e并且b是下一个较低值,但被取反, \xe2\x88\x93( b e \xe2\x88\x92 b e - p )。那么a/b就是 \xe2\x88\x92b e / ( b e \xe2\x88\x92 b e - p ) = \xe2\x88\x921 / (1\xe2\x88\x92 b \xe2\x88\x92 p ) 。这不是最接近 \xe2\x88\x921 而不是 \xe2\x88\x921 的商,但它使商的大小略大于 1,将其置于 ULP 较大的指数区间中。尽管e = \xe2\x88\x921 区间的 ULP 与 \xe2\x88\x921 相差超过 1 个 ULP ,但e = 0 区间中的 ULP却大b倍。来自 \xe2\x88\x921 的商略大于 1/ b ULP。如果b为 2,则商大于 \xe2\x88\x921 的 \xc2\xbd ULP,因此,通过舍入到最接近的值,它将舍入到下一个可表示的值。如果b是任何更大的整数,则商小于 \xe2\x88\x921 的 \xc2\xbd ULP,因此它将四舍五入到 \xe2\x88\x921。因此,a/b= \xe2\x88\x921 \xe2\x87\x94 a= \xe2\x88\x92b在非基数 2 格式中不成立,即使排除 NaN 商情况也是如此。它也不适用于某些非默认舍入模式(例如向零舍入)的二进位格式。
使用以 2 为基数的格式并朝最接近的方向舍入时,a/b= \xe2\x88\x921 意味着a= - b。只要a/b不为 NaN,则相反的情况成立。