ldexp应该正确四舍五入 [英] should ldexp round correctly
问题描述
我对MSVC ldexp的行为感到有些惊讶(它发生在Visual Studio 2013中,但至少在2003年之前的所有旧版本中都发生了这种情况.)
I'm a bit surprised with MSVC ldexp behavior (it happens in Visual Studio 2013, but also with all older versions at least down to 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相同的值.
The first one g is strangely rounded...
It is 2.75 * fmin_denormalized, so i definitely expect the second result e.
If I evaluate 2.75*ldexp(1.0,-1074)
I correctly get same value as e.
我的期望是否过高,还是Microsoft未能遵守某些标准?
Are my expectations too high, or does Microsoft fail to comply with some standard?
推荐答案
虽然该问题未明确说明,但我假设询问者期望的输出为:
While the question does not explicitly state this, I assume that the output expected by the asker is:
g=1.4822e-323 e=1.4822e-323
这是我们期望从C/C ++编译器获得的结果,该编译器承诺严格遵守IEEE-754.这个问题被标记为 C
和 C ++
,我将在此处解决 C99
,因为这是我手头的标准.
This is what we would expect from a C/C++ compiler that promises strict adherence to IEEE-754. The question is tagged both C
and C++
, I will address C99
here as that is the standard I have in hand.
在附件F中,它描述了IEC 60559浮点算法(其中IEC 60559基本上是IEEE-754的另一个名称), C99
标准指定:
In Annex F, which describes IEC 60559 floating-point arithmetic (where IEC 60559 is basically another name for IEEE-754) the C99
standard specifies:
定义
__ STDC_IEC_559 __
的实现应符合本附件中的规格.[...]scalbn
和scalbln
< math.h>
中的函数提供了在IEC 60559的附录.
An implementation that defines
__STDC_IEC_559__
shall conform to the specifications in this annex. [...] Thescalbn
andscalbln
functions in<math.h>
provide the scalb function recommended in the Appendix to IEC 60559.
该附件中的F.9.3.6节进一步规定:
Further down in that annex, section F.9.3.6 specifies:
在二进制系统上,
ldexp(x,exp)
等同于scalbn(x,exp)
.
C99
标准引用的附录是1985年版的IEEE-754的附录,在其中我们找到了定义如下的scalb函数:
The appendix referenced by the C99
standard is the appendix of the 1985 version of IEEE-754, where we find the scalb function defined as follows:
Scalb(y,N)对于整数值N返回y×2 N ,而无需计算2 N .
scalb被定义为具有2的幂的乘法,并且乘法必须根据当前的舍入模式根据标准正确舍入.因此,使用合格的 C99
编译器 ldexp()
必须返回正确的舍入结果,如果编译器定义了 __ STDC_IEC_559 __
.在没有库调用设置舍入模式的情况下,默认的舍入模式舍入到最接近或什至"有效.
scalb is defined as a multiplication with a power of two, and multiplications must be rounded correctly based on the current rounding mode according to the standard. Therefore, with a conforming C99
compiler ldexp()
must return a correctly rounded result if the compiler defines __STDC_IEC_559__
. In the absence of a library call setting the rounding mode, the default rounding mode "round to nearest or even" is in effect.
我无权访问MSVC 2013,所以我不知道它是否定义了该符号.这甚至可能取决于编译器标志设置,例如/fp:strict
.
I do not have access to MSVC 2013, so I do not know whether it defines that symbol or not. This could even depend on a compiler flag setting, such as /fp:strict
.
在跟踪我的C ++ 11标准副本之后,我找不到对 __ STDC_IEC_559 __
的任何引用,也找不到关于IEEE-754绑定的任何语言.根据这个问题的答案是因为引用了C99标准就包含了对该支持的支持.
After tracking down my copy of the C++11 standard, I cannot find any reference to __STDC_IEC_559__
or any language about IEEE-754 bindings. According to the answer to this question this is because that support is included by referring to the C99 standard.
这篇关于ldexp应该正确四舍五入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!