考虑两种计算方式:
- 双精度数据
-> 应用具有双精度临时函数的函数
-> 返回结果 - 双精度数据
-> 转换为 long double
-> 应用具有长双精度临时函数的函数
-> 转换为 double
-> 返回结果
与第一个解决方案相比,第二种解决方案能否给出不太准确的结果?如果是,在什么情况下?
考虑两种计算方式:
与第一个解决方案相比,第二种解决方案能否给出不太准确的结果?如果是,在什么情况下?
是的。证明:令 c = 0x1p-53 + 0x1p-64。以双精度和长双精度计算 1+cc-1(常见的 Intel 格式,具有 64 位有效位)。在 double 中,结果为 0,这是数学上精确的答案。在 long double 中,结果是 -0x1p-64,这是错误的(并且在转换为 double 时仍然是错误的)。
在 double 中,1+c 将 1 的 ULP(最小精度单位)的一半添加到 1,因此它产生 1 加上一个 ULP。减去 c 会减去 ULP 的一半多一点,因此与结果最接近的可表示数字(双精度数)是 1,因此产生 1。然后减去 1 得到 0。
In long double, 1+c adds 0x1p-53 plus half an ULP of 1. (In long double, the ULP of 1 is 0x1p-63.) Since the result is exactly the same distance from the two nearest representable numbers (in long double), the one with the low bit zero is returned, 1+0x1p-53. Then the exact result of subtracting c is 1 - 0x1p-64. This is exactly representable, so it is returned. Finally, subtracting 1 yields -0x1p-64.
关于long double
草案说:
3.9.1 基本类型
8浮点类型共有三种:float、double 和 long double。double 类型提供的精度至少与 float 一样,long double 类型提供的精度至少与 double 一样。float 类型的值集是 double 类型的值集的子集;double 类型的值集是 long double 类型的值集的子集。浮点类型的值表示是实现定义的。整数和浮点类型统称为算术类型。标准模板 std::numeric_limits (18.3) 的特化应指定实现的每种算术类型的最大值和最小值。
至于下一个最有趣的促销活动:
4.6 浮点推广
1 float 类型的纯右值可以转换为 double 类型的纯右值。值不变。
2这种转换称为浮点提升。
请注意,没有什么要说double
的long double
。不过,我会冒这个险。
long double
接下来关于转换,当您从到时,我们感兴趣的是double
:
4.8 浮点数转换
1浮点类型的纯右值可以转换为另一种浮点类型的纯右值。如果源值可以在目标类型中精确表示,则转换的结果就是该精确表示。如果源值介于两个相邻的目标值之间,则转换的结果是实现定义的选择这些值中的任何一个。否则,行为未定义。
2允许作为浮点提升的转换不包括在浮点转换集中。
现在,让我们看看缩小的效果:
6 . 缩小转换是隐式转换
[...]
- 从long double到double或者float,或者从double到float,除非源是常量表达式并且转换后的实际值在可以表示的值范围内(即使不能准确表示)
所有这些标准语都有两个要点:
long double
a double
(高或低)无法准确表示的范围内,则这些结果可以累积以返回不同的最终结果,您希望将其作为double
.至于哪个更准确,我认为这完全取决于您的应用程序。