对变量和常量的操作在c中给出不同的结果

Opeartion on a variable and constant giving different result in c

简单计算:3^20%15。
根据计算器,答案是 6。

以下代码生成答案 7。

#include <stdio.h>
#include <math.h>
int main() {
        int i = 20;
        printf("%d\n", ((int)pow(3,20)%15));
        return 0;
}

如果我用变量 i 替换 printf 语句中的 20,它会给出 -8 作为输出。

假设计算器正确(或不正确?),程序中有什么问题?

谢谢。

pow(3,20) 的结果不适合您平台(或我的平台)上的 int。因此,您会遇到意想不到的结果。

更改为更大的整数类型,例如 long long 即可。

此外,pow 处理在内存中未准确表示的浮点数(查找)。在转换为整数期间,这可能会导致某些错误。例如,对于 printf("%fl\n", (pow(3,20))); 我得到 3486784401.000000l 这不是一个精确的整数值。

这里可能发生的事情是:

  • 在您的 C 实现中,int 是 32 位,最小值为 −2,147,483,648,最大值为 2,147,483,647。
  • pow(3, 20)的结果是3486784401。(见下面注释1。)
  • 3486784401 对于 int 来说太大了,所以会溢出。在整数溢出的情况下,C 标准允许实现做任何事情。
  • (int) pow(3, 20) 中,到 int 的转换可能是在编译时通过生成最大值 2,147,483,647 计算出来的。然后除以 15 的余数是 7.
  • (int) pow(3, i) 中,到 int 的转换可能是在 运行 时通过产生最小值 −2,147,483,648 计算出来的。 (一些处理器为整数溢出产生这样的结果。)然后除以 15 的余数是 −8。

总结:

  • 您的代码溢出,因此 C 标准未定义该行为。
  • 编译器对 pow(3, 20)pow(3, i) 的行为可能不同,因为它在编译时评估前者,在执行时评估后者。

备注

  1. pow return 的良好实施 pow(3, 20) 正好是 3486784401。不幸的是,糟糕的实施可能 return 不准确的值,例如 3486784401.000000476837158203125 或 3486784400.999999523162841796875.