我在编写测试程序时发现了这一点。我想知道这个问题在哪里。是在C库(printf),clang编译器还是Mac处理器中?我在Mac上使用clang编译了该程序。这是简短的程序:
#include <stdio.h>
int main(void) {
int num = 12;
double temp = 0.0;
temp = num/10.0;
printf("%lf\n", temp);
temp = temp - 1.0;
printf("%lf\n", temp);
temp = temp * 10.0;
printf("%lf\n", temp);
int new_num = temp;
printf("%d\n", new_num);
int cast_num =(int)temp;
printf("%d\n", cast_num);
return 0;
}
该程序适用于所有数字,除非num以12结尾。当num以12结尾时,new_num和cast num分别为1而不是2。如果将num设置为22,则应将new_num和cast_num = 2设置为2。如果num = 11,10,13,14等,即使按预期方式工作也是如此……当num以12结尾时,它不起作用。因此设置num = 212,并用temp = temp-21替换第10行。并且发生错误的结果。将num更改为213,即可正常使用。
有人知道这个问题的性质吗?奇怪的是,它只显示一个以12结尾的数字。
有什么想法吗?
Apple LLVM版本10.0.0(clang-1000.10.44.4) 目标:x86_64-apple-darwin18.2.0 线程模型:posix
答案 0 :(得分:0)
这是由于四舍五入问题。 2.000000并不总是2!
尝试以下操作:
temp = temp * 10.0;
printf("%.20lf\n", temp);
您可能会观察到,温度略微低于2。因此将其强制转换为int会将其四舍五入为1。
问题是,已经1.2
(12/10.0
)不能精确地表示为浮点数,因此第一除法已经不是精确的1.2,而是要少一些。该错误会传播到您的演员表。要解决此问题,例如在将其强制转换为int之前,以数学上正确的方法round()
进行舍入。