英特尔编译器无法处理小数的绝对值

时间:2018-12-06 07:30:18

标签: gcc floating-point precision icc

intel 2018相比,使用gcc 7.2.0编译代码时,我面临一些非常奇怪的舍入错误。我只是在考虑极小的数字的绝对值:

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

以下是使用gcc 7.2.0编译代码时的输出,这是预期的:

$ ./a.out
abs(numa) 1.3654159537789158e-08
abs(numb) 7.0949094162313382e-08

但这与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

什么会导致我的Intel编译器版本有如此大的差异?

1 个答案:

答案 0 :(得分:1)

功能错误或语言错误

与“ gcc 7.2.0”一起输出是预期的,因为OP是使用C ++编译的

使用“ intel / 2018”,输出与强制C编译一致。

使用C,abs(numa)numa转换为值为0的int,以下是 undefined behavior (UB),其值为{{1 }}期望"%.17g"而不是double

int

使用UB输出// In C UB: vvvvv------vvvvvvvvv printf("abs(numa) %.17g \n", abs(numa)); ,我们可以进行一些取证。

binary中的典型2.0410903428666442e-314是

00000000 00000000 00000000 00000000 11110110 00111101 01001110 00101110

这与某些C编译通过32位"abs(numa) 2.0410903428666442e-314",然后int 0检索此代码以及随后的其他垃圾作为预期的printf()一致。

作为UB,此结果有时可能会有所不同(如果有输出的话),但仍然可以很好地说明问题:使用C ++编译或更改为double@dmuir) C ++和C中fabs()的绝对值。


在调试浮点问题时,使用double(或"%g")对OP很有帮助。 "%e"

内容更丰富