gpt4 book ai didi

c - 通过删除 printf 语句得到不同的答案

转载 作者:太空狗 更新时间:2023-10-29 17:03:09 25 4
gpt4 key购买 nike

这是UVa online judge的题目链接。
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=29&page=show_problem&problem=1078

我的C代码是

#include <stdio.h>

double avg(double * arr,int students)
{

int i;
double average=0;

for(i=0;i<students;i++){
average=average+(*(arr+i));
}

average=average/students;

int temp=average*100;

average=temp/100.0;

return average;
}


double mon(double * arr,int students,double average)
{
int i;
double count=0;

for(i=0;i<students;i++){

if(*(arr+i)<average){
double temp=average-*(arr+i);

int a=temp*100;

temp=a/100.0;

count=count+temp;
}
}

return count;
}


int main(void)
{
// your code goes here
int students;

scanf("%d",&students);

while(students!=0){

double arr[students];
int i;

for(i=0;i<students;i++){
scanf("%lf",&arr[i]);

}

double average=avg(arr,students);

//printf("%lf\n",average);

double money=mon(arr,students,average);

printf("$%.2lf\n",money);

scanf("%d",&students);

}

return 0;
}

其中一个输入和输出是
输入
3
0.01
0.03
0.03
0

输出
0.01 美元

我的输出是
$0.00。

但是,如果我取消注释行 printf("%lf",average);

输出如下
0.02//这是平均值
0.01 美元

我在ideone.com上运行代码

请解释为什么会这样。

最佳答案

我相信我已经找到了罪魁祸首和合理的解释。

在 x86 处理器上,FPU 在内部以 扩展精度 运行,这是一种 80 位格式。所有浮点指令都以这种精度运行。如果确实需要 double,编译器将生成代码以将扩展精度值向下转换为 double 值。至关重要的是,注释掉的 printf 会强制进行这种转换,因为 FPU 寄存器必须在该函数调用中保存和恢复,并且它们将保存为 double(请注意avgmon 都是内联的,所以那里不会发生保存/恢复。

事实上,我们可以使用 static double dummy = average; 这行来代替 printf 来强制进行 double 转换,这还会导致错误消失:http://ideone.com/a1wadn

您的 average 值接近但不完全是 0.02,因为 float 不准确。当我使用 long double 显式地进行所有计算,并打印出 average 的值时,它如下所示:

long double: 0.01999999999999999999959342418532
double: 0.02000000000000000041633363423443

现在您可以看到问题所在了。当您添加 printf 时,average 被强制为 double,从而将其推至 0.02 以上。但是,如果没有 printfaverage 在其原生扩展精度格式中将略小于 0.02。

当您执行 int a=temp*100; 时,错误出现了。如果不进行转换,则 a = 1。通过转换,这使得 a = 2

要解决此问题,只需使用 int a=round(temp*100); - 所有奇怪的错误都会消失。


请注意,此错误对代码的更改极其敏感。任何导致寄存器被保存的东西(例如几乎任何地方的 printf)实际上都会导致错误消失。因此,这是一个极好的 heisenbug 示例:当您尝试调查它时,它就会消失。

关于c - 通过删除 printf 语句得到不同的答案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30820825/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com