c - Different Answers by removing a printf statement -
this link question on uva online judge.
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&itemid=8&category=29&page=show_problem&problem=1078
my c code
#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) { // 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; } one of input , outputs are
input
3
0.01
0.03
0.03
0
output
$0.01
my output
$0.00.
if uncomment line printf("%lf",average);
output follows
0.02 //this average
$0.01
i running code on ideone.com
please explain why happening.
i believe i've found culprit , reasonable explanation.
on x86 processors, fpu operates internally extended precision, 80-bit format. of floating point instructions operate precision. if double required, compiler generate code convert extended precision value down double precision value. crucially, commented-out printf forces such conversion because fpu registers must saved , restored across function call, , saved doubles (note avg , mon both inlined no save/restore happens there).
in fact, instead of printf can use line static double dummy = average; force double conversion occur, causes bug disappear: http://ideone.com/a1wadn
your value of average close not 0.02 because of floating-point inaccuracies. when calculations explicitly long double, , print out value of average, following:
long double: 0.01999999999999999999959342418532 double: 0.02000000000000000041633363423443 now can see problem. when add printf, average forced double pushes above 0.02. but, without printf, average little less 0.02 in native extended precision format.
when int a=temp*100; bug appears. without conversion, makes a = 1. conversion, makes a = 2.
to fix this, use int a=round(temp*100); - weird errors should vanish.
of note, bug extremely sensitive changes in code. causes registers saved (such printf pretty anywhere) cause bug vanish. hence, extremely example of heisenbug: bug vanishes when try investigate it.
Comments
Post a Comment