我想知道如何解释我今天观察到的浮点差异.这是一个错误,还是触发了一些未定义的行为?以下是代码.我希望理解这种行为,这样我就可以使它在编译器、处理器和平台上保持一致.

#include <stdio.h>
#include <math.h>

#define BUG_ON_GCC
#ifdef BUG_ON_GCC
__attribute__((noinline))
#else
inline __attribute__((always_inline))
#endif
double safe_pow(
  double x,
  double y)
{
  printf("x = %llx\n", *((unsigned long long *)&x));
  printf("y = %llx\n", *((unsigned long long *)&y));
  double result = pow(x, y);
  printf("r = %llx\n", *((unsigned long long *)&result));
  return result;
}

int main() {
  printf("%ld\n", sizeof(pow(15.034465284692086, 3.466120406090667)));
  printf("%.24f\n", pow(15.034465284692086, 3.466120406090667));
  printf("%ld\n", sizeof(safe_pow(15.034465284692086, 3.466120406090667)));
  printf("%.24f\n", safe_pow(15.034465284692086, 3.466120406090667));
  return 0;
}

以及我在Linux VM中使用Clang所看到的结果:

8
12020.670425990641888347454369
8
x = 402e11a56f0d331e
y = 400bba9d55e142e0
r = 40c77a55d084d419
12020.670425990641888347454369

在同一个VM中使用GCC:

8
12020.670425990643707336857915
8
x = 402e11a56f0d331e
y = 400bba9d55e142e0
r = 40c77a55d084d419
12020.670425990641888347454369

在同一台计算机上使用MacOS上的Clang:

8
12020.670425990643707336857915
8
x = 402e11a56f0d331e
y = 400bba9d55e142e0
r = 40c77a55d084d41a
12020.670425990643707336857915

推荐答案

Exhibit A.

正如您所看到的,没有人呼叫pow,无论是内联还是其他.gccclang都在编译时计算它,但它们的计算方式不同.不同之处在于最低有效位.

您的两个操作数都不能完全表示为IEEE双精度值.一个无限精度的计算器建议GCC使用精确的操作数并以高于double的精度计算结果,然后将结果转换为double,而Clang将操作数转换为double并失go 一定的精度,然后进行计算.没有对或错的行为,两者都是根据标准正确的.

C++相关问答推荐

为什么静态说明符为内联函数生成外部定义?

为什么可以通过指向常量int的指针间接地改变整数的值?

ZED for SDL上的C语言服务器

LONG_DOUBLE_T是否存在(标准C:C23)

C lang:当我try 将3个或更多元素写入数组时,出现总线错误

Make Node函数.S有什么问题吗?

CC2538裸机项目编译但不起作用

在创建动态泛型数组时,通过realloc对故障进行分段

为什么双精度d=flt_max+flt_max;在c语言中得到inf的结果

在libwget中启用Cookie会导致分段故障

如何使用唯一数字对整型进行分区

在C中创建任意类型的只读指针参数

在C++中允许使用字符作为宏参数

错误...的多个定义(&Q)首先在这里定义&

宏观;S C调深度

在C中打印指针本身

如何在C中计算包含递增和递减运算符的逻辑表达式?

C struct 中的冒泡排序

通过修改c中的合并排序对数组的偶数索引进行排序

使用复合文字数组初始化的指针数组