首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >IEEE-754浮点计算、相等和缩小

IEEE-754浮点计算、相等和缩小
EN

Stack Overflow用户
提问于 2012-05-23 11:51:05
回答 1查看 527关注 0票数 8

在下面的代码中,函数foo1、foo2和foo3应该是等效的。然而,当run foo3没有从循环中终止时,会出现这种情况吗?

代码语言:javascript
复制
template <typename T>
T foo1()
{
   T x = T(1);
   T y = T(0);
   for (;;)
   {
      if (x == y) break;
      y = x;
      ++x;
   }
   return x;
}

template <typename T>
T foo2()
{
   T x = T(0);
   for (;;)
   {
      T y = x + T(1);
      if (!(x != y)) break;
      ++x;
   }
   return x;
}

template <typename T>
T foo3()
{
   T x = T(0);
   while (x != (x + T(1))) ++x;
   return x;
}

int main()
{
   printf("1 float:  %20.5f\n", foo1<float>());
   printf("2 float:  %20.5f\n", foo2<float>());
   printf("3 float:  %20.5f\n", foo3<float>());
   return 0;
}

注意:这是在发布模式下使用带有/fp precise的VS2010编译的。不知道GCC等人会如何对待这段代码,任何信息都会很棒。这会不会是一个问题,在foo3中,x和x+1值以某种方式变成了NaN?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-05-23 14:38:17

发生的情况很可能如下所示。在x86 arch上,中间计算的精度可以达到80位(long double是对应的C/C++类型)。编译器将所有80位用于(+1)运算和(!=)运算,但在存储之前截断结果。

所以你的编译器真正要做的是:

代码语言:javascript
复制
while ((long double)(x) != ((long double)(x) + (long double)(1))) {
  x = (float)((long double)(x) + (long double)(1));
} 

这绝对不符合IEEE,并且会给每个人带来无尽的麻烦,但这是MSVC的默认设置。使用/fp:strict编译器标志禁用此行为。

这是我对大约10年前的问题的记忆,如果这不完全正确,请原谅我。See this for the official Microsoft documentation

编辑我非常惊讶地了解到,g++在默认情况下表现出完全相同的行为(在i386 linux上,但不是在-mfpmath=sse上)。

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10713195

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档