请确认我对 IEEE 浮点数的理解。
我相信如果我有两个数字:
a
= 2^ea × ma ← "数学 ×"b
= 2^eb × mb然后他们的乘积
a * b
与 ((a * p) * b) / p
完全相同,其中 p
是 2 的幂(警告:中间值不会溢出到无穷大或在指数=-308 附近失去精度;也就是说,这是一个满足p
的(a * p) / p = a
)。
根据我的理解,
a * b
(IEEE *
)被定义为“最接近数学值 2^(ea+eb) × ma × mb”(最接近,或者无论舍入模式做什么)。这涉及到尾数相乘,然后根据需要移动尾数(例如 1.11111×1.11111 = 11.something,因此最终结果将具有指数 ea+eb+1,并且尾数四舍五入为浮点数中的位数)。
所有这些基本上与 ea 和 eb 的值无关;我们可以随意增加/减少它们,然后再撤消它,并且不会影响最终产品。
推论:
int
添加提取的指数来完成此操作。然后我可以将双精度数缩小到范围±[1,2),最后将指数进行位调整(如果超出范围±1024,则会出现错误)。这将有助于像[1E300、1E300、1E-200、1E-200]这样的情况,在这些情况下,幼稚的产品会失败。而且 - 对于简单的产品能够工作的情况,稍微调整一下的版本会给出相同的结果。TLDR:你是对的
一些假设
然后,每个标准化浮点数都被编码为
1.x * 2^y
,带有二进制尾数 1.x
和整数指数 y
。因此,2 的整数幂被编码为 1.0 * 2^p
。如果我们忽略归一化的位移位,则乘法将实现为
(1.x * 2^y) * (1.u * 2^w) == (1.x * 1.u) * 2^(y+w)
相反,除法是
(1.x / 1.u) * 2^(y-w)
。按照这种模式,2 的幂的乘法包含乘法 1.x * 1.0
,它是恒等函数,不会引入结合性问题。指数的加法 y + p
是整数加法,具有结合律。因此,乘法和除以 2 的幂是结合律。
如果任何中间结果超出指数的整数范围,则情况不成立。然后对结果进行非规范化并对尾数位进行四舍五入。
这意味着对于 2 的幂,可以安全地将(相对昂贵的)除法替换为其逆乘法,而不会损失精度。对于编译时间常数,编译器会自动执行此操作。
标准化数字通常很有用。例如,在计算 L2 向量范数 (
sqrt(x^2 + y^2 + …)
) 时,确定缩放因子 s = max(abs({x, y, …}))
并计算 s * sqrt((x/s)^2 + (y/s)^2 + …)
以避免溢出中间和非常有用。
如果我们将
s
舍入到附近的 2 次幂,则不会引入舍入误差。标准数学函数 frexp
和 ldexp
可用于选择因子。
Goldberg 的 每个计算机科学家应该了解的浮点运算 包含相关的定理 7。它还包含简单的注释“按 2 的幂缩放是 无害,因为它只改变指数而不改变显着性。”这支持了我们的评估。