I bump into with strange behaviour. In this program I try check is floating point value equals to zero:
#include <cstdlib>
#include <cmath>
#include <iostream>
int main ()
{
float fa (0), fb (0);
double da (0), db (0);
long double la (0), lb (0);
cout << "Float: " << (FP_ZERO == fpclassify (fa - fb) ) << endl;
cout << "Double: " << (FP_ZERO == fpclassify (da - db) ) << endl;
cout << "Long double: " << (FP_ZERO == fpclassify (la - lb) ) << endl;
cout << "Float: " << (FP_ZERO == fpclassify (fa - 42) ) << endl;
cout << "Double: " << (FP_ZERO == fpclassify (da - 42) ) << endl;
cout << "Long double: " << (FP_ZERO == fpclassify (la - 42) ) << endl;
return EXIT_SUCCESS;
}
The result of the program is predictable:
$ ./llvlg
Float: 1
Double: 1
Long double: 1
Float: 0
Double: 0
Long double: 0
But if I launch the program via Valgrind the result will be wrong for long double zero:
$ valgrind ./llvlg
==7521== Memcheck, a memory error detector
==7521== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==7521== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==7521== Command: ./llvlg
==7521==
Float: 1
Double: 1
Long double: 0
Float: 0
Double: 0
Long double: 0
==7521==
==7521== HEAP SUMMARY:
==7521== in use at exit: 0 bytes in 0 blocks
==7521== total heap usage: 2 allocs, 2 frees, 73,728 bytes allocated
==7521==
==7521== All heap blocks were freed -- no leaks are possible
==7521==
==7521== For counts of detected and suppressed errors, rerun with: -v
==7521== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Is it a bug or expected behaviour?
UPD:
Source code of the program available here.
Build options: g++ main.cpp -O0 -o llvlg
.
My environment:
$ uname -a
Linux tiptop 4.8.0-53-generic #56-Ubuntu SMP Tue May 16 00:23:44 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
$ gcc --version
gcc (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005
$ valgrind --version
valgrind-3.12.0.SVN
$ cat /proc/cpuinfo
...
model name : Intel(R) Core(TM) i7-4700MQ CPU @ 2.40GHz
...
This is the expected behaviour with Valgrind - a known limitation. Internally long double is only represented with 64bit (double) precision.
See here.