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 double
s (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