单个浮点运算(如a+b, a-b, a*b或a/b)以更高的精度(80位)计算并立即截断(为32位)是否总是产生与原始类型精度(32位)计算相同的结果?
或者最不有效位在结果中会不同吗?为什么?
编辑:这篇博文中的部分例子
float tmp; // 32 bit precision temporary variable
push a; // converts 32 to 64 bit
push b; // converts 32 to 64 bit
multiply; // 64 bit computation
pop tmp; // converts result to 32 bits
这个例子的作者这样解释这段代码:
尽管乘法和加法指令使用64位内部精度,但结果会立即转换回32位格式,因此这不会影响结果。
所以我要问的是,这总是正确的吗?像这样的单次操作无论在什么平台上都会产生与最后一位相同的结果。
我正在用c#编程,在c#中我们无法控制精确浮点操作的完成。
来自c#规范:
浮点操作的精度可以高于操作的结果类型。例如,一些硬件体系结构支持"扩展"或"长双精度"浮点数打字比双字打字有更大的范围和精度隐式地执行所有浮点操作精密类型 .
并且我需要知道浮点数上的单个操作(如下面的c#示例)是否确定。
double a = 2.5d;
double b = 0.1d;
myClassInstance.someDoubleField = a*b; // value should be converted out of extended precision
那么这个someDoubleField
值在所有平台上都是相同的吗?
是的,这是在本文中建立的:
Samuel A. Figueroa,"什么时候双舍入是无害的?"ACM SIGNUM通讯,卷30第3期,1995年7月doi:10.1145/221332.221334
主要结果是,如果输入类型具有p位有效位,且计算类型的有效位位数至少为2p+2位,则截断后的初等运算+
, -
, *
, /
和sqrt
都能正确舍入。
IEEE754的binary32
数字(即典型的C float
类型)具有24位有效位,因此实际上使用具有53位有效位的binary64
(即典型的C double
)就足够了。事实上,这是JavaScript编译器在语言本身只有binary64
类型时使用binary32
操作的一个非常常见的技巧。