Quang Thinh Ha
Quang Thinh Ha

Reputation: 241

Intel compilers cannot handle absolute value of small number

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

Answers (1)

chux
chux

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

Related Questions