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

Popular posts from this blog

facebook - android ACTION_SEND to share with specific application only -

python - Creating a new virtualenv gives a permissions error -

javascript - cocos2d-js draw circle not instantly -