Reputation: 241
I am facing some very weird rounding errors when compiling my code with intel 2018
when compared to gcc 7.2.0
. I'm simply looking into taking the absolutely value of extrememly small number:
#include <cfloat>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
int main() {
double numa = -1.3654159537789158e-08;
double numb = -7.0949094162313382e-08;
if (isnan(numa))
printf("numa is nan \n");
if (isnan(numb))
printf("numb is nan \n");
printf("abs(numa) %.17g \n", abs(numa));
printf("abs(numb) %.17g \n", abs(numb));
if ((isnan(numa) || (abs(numa) < DBL_EPSILON)) || (isnan(numb) || (abs(numb) < DBL_EPSILON))) {
printf("x %.17g y %.17g DBL_E %.17g \n", numa, numb, DBL_EPSILON);
}
return 0;
}
Here is the output when compiling the code with gcc 7.2.0
, which is expected:
$ ./a.out
abs(numa) 1.3654159537789158e-08
abs(numb) 7.0949094162313382e-08
But it is a different story for intel/2018
:
$ ./a.out
abs(numa) 2.0410903428666442e-314
abs(numb) 2.0410903428666442e-314
x -1.3654159537789158e-08 y -7.0949094162313382e-08 DBL_E 2.2204460492503131e-16
What could cause my version of Intel compilers to have such a huge difference?
Upvotes: 1
Views: 98
Reputation: 153547
Wrong function or wrong language
Output with "gcc 7.2.0" is as expected because OP compiled with C++
With "intel/2018" the output is consistent with a forced C compilation.
With C, the abs(numa)
converts numa
to an int
with the value of 0 and the below is undefined behavior (UB) as "%.17g"
expects a double
and not an int
.
// In C UB: vvvvv------vvvvvvvvv
printf("abs(numa) %.17g \n", abs(numa));
With the UB output of "abs(numa) 2.0410903428666442e-314"
, we can do some forensics.
Typical 2.0410903428666442e-314 in binary is
00000000 00000000 00000000 00000000 11110110 00111101 01001110 00101110
This is consistent with some C compilations that pass a 32-bit int 0
and then printf()
retrieved that along with some other following junk as the expected double
.
As UB, this result may vary from time-to-time, if output at all, yet is good indicator of the problem: Compile in C++ or change to fabs()
(@dmuir) to take the absolute value of a double
in both C++ and C.
Some kudos to OP for using "%g"
(or "%e"
) when debugging a floating point issues. Far more informative the "%f"
Upvotes: 1