简体   繁体   中英

IEEE-754 floating point computations, equality and narrowing

In the following code, the functions foo1,foo2 and foo3 are intended to be equivalent. However when run foo3 does not terminate from the loop, is there a reason why this is the case?

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;
}

Note: This was compiled using VS2010 with /fp precise in release mode. Not sure how GCC etc would treat this code, any information would be great. Could this be an issue where in foo3, the x and x+1 values become NaN somehow?

What happens is most likely the following. On the x86 arch, intermediate calculations can be done with 80 bits of precision (long double is the corresponding C/C++ type). The compiler uses all 80 bits for the (+1) operation and for the (!=) operation, but truncates the results before storage.

So what your compiler really does is this:

while ((long double)(x) != ((long double)(x) + (long double)(1))) {
  x = (float)((long double)(x) + (long double)(1));
} 

This is absolutely non-IEEE-conforming and causes endless headaches for everyone, but this is the default for MSVC. Use /fp:strict compiler flag to disable this behaviour.

This is my recollection of the problem from about 10 years ago so please forgive me if this is somehow not entirely correct. See this for the official Microsoft documentation .

EDIT I was very surprised to learn that g++ by default exhibits exactly the same behaviour (on i386 linux, but not with eg -mfpmath=sse).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM