[英]should ldexp round correctly
我对MSVC ldexp行为感到有点惊讶(它发生在Visual Studio 2013中,但是至少到2003年都会出现所有旧版本......)。
例如:
#include <math.h>
#include <stdio.h>
int main()
{
double g=ldexp(2.75,-1074);
double e=ldexp(3.0,-1074);
printf("g=%g e=%g \n",g,e);
return 0;
}
版画
g=9.88131e-324 e=1.4822e-323
第一个g奇怪地圆了......
它是2.75 * fmin_denormalized,所以我绝对期待第二个结果e。
如果我评估2.75*ldexp(1.0,-1074)
我正确得到与e相同的值。
我的期望是否太高,或者微软是否未能遵守某些标准?
虽然问题没有明确说明这一点,但我认为提问者预期的输出是:
g=1.4822e-323 e=1.4822e-323
这是我们对C / C ++编译器的期望,它承诺严格遵守IEEE-754。 这个问题被标记为C
和C++
,我将在这里解决C99
,因为这是我手头的标准。
在附件F中,它描述了IEC 60559浮点运算(其中IEC 60559基本上是IEEE-754的另一个名称), C99
标准规定:
定义
__STDC_IEC_559__
的实现应符合本附件中的规范。 [...]<math.h>
的scalbn
和scalbln
函数提供了IEC 60559附录中推荐的scalb函数。
在该附件中,F.9.3.6节规定:
在二元系统上,
ldexp(x, exp)
等同于scalbn(x, exp)
。
C99
标准引用的附录是1985年版IEEE-754的附录,其中我们发现scalb函数定义如下:
Scalb(y,N)返回y×2 N的积分值N而不计算2 N.
scalb定义为乘以2的幂,乘法必须根据标准根据当前的舍入模式正确舍入。 因此, 如果编译器定义__STDC_IEC_559__
,则使用符合C99
编译器的ldexp()
必须返回正确舍入的结果。 在没有库调用设置舍入模式的情况下,默认舍入模式“舍入到最接近或甚至”是有效的。
我无法访问MSVC 2013,因此我不知道它是否定义了该符号。 这甚至可能取决于编译器标志设置,例如/fp:strict
。
在追踪我的C ++ 11标准副本之后,我找不到任何对__STDC_IEC_559__
引用或任何有关IEEE-754绑定的语言。 根据这个问题的答案, 这是因为参考C99标准包含了这种支持。
发生这种情况是因为在ldexp
计算期间2.75被截断为2,这是因为在那个小的非规范化数字处,表示'.75'部分的位从可表示数字的末尾移开并消失。 无论这是一个错误还是设计行为都可以辩论。
当计算2.75*ldexp(1.0,-1074)
时,正常的舍入发生,而2.75变为3。
编辑:ldexp应正确舍入,这是一个错误。
OP结果不符合C规范,因为规范没有定义计算的准确性。
OP结果可能已经失败了IEEE 754,但它取决于当时使用的舍入模式,该模式未发布。 然而,OP的报告2.75*ldexp(1.0,-1074)
按预期工作,这意味着预期的舍入模式已经生效。
使用printf("%la",x)
有助于清楚地看到接近double
极限的情况。
我希望g
能够“舍入到最近 - 与偶数相关”,结果为0x1.8p-1073
- 这确实发生在Windows上的gcc。
理想情况下, g
的值为0x1.6p-1073
0x0.0p-1073 Zero
0x0.8p-1073 next higher double DBL_TRUE_MIN
0x1.0p-1073 next higher double
0x1.6p-1073 ideal `g` answer, but not available as a double
0x1.8p-1073 next higher double
公平地说,它可能是一个处理器错误 - 它以前发生过 。
参考
double g=ldexp(2.75,-1074);
printf("%la\n%la\n", 2.75,ldexp(2.75,-1074));
printf("%la\n%la\n", 3.0 ,ldexp(3.0 ,-1074));
double e=ldexp(3.0,-1074);
printf("%la\n%la\n", g,e);
printf("%la\n%la\n", 9.88131e-324, DBL_TRUE_MIN);
printf("g=%g e=%g \n",g,e);
0x1.6p+1
0x1.8p-1073
0x1.8p+1
0x1.8p-1073
0x1.8p-1073
0x1.8p-1073
0x1p-1073
0x1p-1074
g=1.4822e-323 e=1.4822e-323
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.