ldexp应该正确四舍五入 [英] should ldexp round correctly

查看:46
本文介绍了ldexp应该正确四舍五入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对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. [...] The scalbn and scalbln 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆