Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

143
Views
Different Answers by removing a printf statement

This is the link to the 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 is

#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;
}

One of the input and outputs are
Input
3
0.01
0.03
0.03
0

Output
$0.01

My output is
$0.00.

However if I uncomment the line printf("%lf",average);

The Output is as follows
0.02 //This is the average
$0.01

I am running the code on ideone.com

Please explain why is this happening.

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

I believe I've found the culprit and a reasonable explanation.

On x86 processors, the FPU operates internally with extended precision, which is an 80-bit format. All of the floating point instructions operate with this precision. If a double is actually required, the compiler will generate code to convert the extended precision value down to a double precision value. Crucially, the commented-out printf forces such a conversion because the FPU registers must be saved and restored across that function call, and they will be saved as doubles (note that avg and mon are both inlined so no save/restore happens there).

In fact, instead of printf we can use the line static double dummy = average; to force the double conversion to occur, which also causes the bug to disappear: http://ideone.com/a1wadn

Your value of average is close to but not exactly 0.02 because of floating-point inaccuracies. When I do all the calculations explicitly with long double, and I print out the value of average, it is the following:

long double: 0.01999999999999999999959342418532
double: 0.02000000000000000041633363423443

Now you can see the problem. When you add the printf, average is forced to a double which pushes it above 0.02. But, without the printf, average will be a little less than 0.02 in its native extended precision format.

When you do int a=temp*100; the bug appears. Without the conversion, this makes a = 1. With the conversion, this makes a = 2.

To fix this, simply use int a=round(temp*100); - all your weird errors should vanish.


Of note, this bug is extremely sensitive to changes in the code. Anything that causes the registers to be saved (such as a printf pretty much anywhere) will actually cause the bug to vanish. Hence, this is an extremely good example of a heisenbug: a bug that vanishes when you try to investigate it.

over 4 years ago · Santiago Trujillo Report

0

@nneonneo well answered most of the issue: Slightly variant compilations result in slightly different floating-point code that result in nearly the same double answer, except one answer is just below 2.0 and the the other at or just about 2.0.

Like to add about the importance on not using conversion to int for floating point rounding.

Code like double temp; ... int a=temp*100; accentuate this difference resulting in a with a value of 1 or 2 as conversion to int is effective "truncate toward zero" - drop the fraction.

Rather than round to near 0.01 with code like:

double temp;
...
int a = temp*100;  // Problem is here
temp = a/100.0;

Do not use int at all. Use

double temp;
...
temp = round(temp*100.0)/100.0;

Not only does this provide more consistent answers (as temp is unlikely to have values near a half-cent), it also allows temp values outside the int range. temp = 1e13; int a = temp/100; certainly results in undefined behavior.

Do not use conversion to int to round floating-point numbers: use round()

roundf(), roundl(), floor(), ceil(), etc. may also be useful. @jeff

over 4 years ago · Santiago Trujillo Report

0

You're dividing a double by an integer, which is integer division. In this case it will give a value of 0.

If you cast student to a double it should give you proper output.

average=average/(double)students;

There might be other locations this is needed depending on your arithmetic.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!