2

I was trying to use the remainder operator (i.e.,'%') to get the remainder, but I ran into an error: n % 25 is not evaluated to 23 when the input is 9.73. Am I doing something wrong here? Or is it because of the C compiler?

Here's my code:

#include <stdio.h>

int main(void)
{
    float x;
    int i, n;

    scanf("%f", &x);

    n = x * 100;
    i = n / 25;
    n = n % 25;

    printf("%d %d\n", i, n);
}

Output:

jharvard@appliance(~/Dropbox/pset1): ./remainder
9.72
38 22
jharvard@appliance(~/Dropbox/pset1): ./remainder
9.73
38 22
jharvard@appliance(~/Dropbox/pset1): ./remainder
9.74
38 24

3 Answers 3

3

Why do you think n should be 23?

if x = 9.72
then n = 972
so 972 % 25 = 22

edit to add given that the original question is now edited

When you are dealing in floats, you run into imprecision, because a floating point number is only an approximation. 9.73 cannot be stored in binary exactly. It's more like 9.729999... so when you multiply by 100, you get 972.99999.... and when you then save that as an integer, you get 972. 972%25 = 22.

Here's a good video about floating point imprecision which will help explain it more fully: https://www.youtube.com/watch?v=PZRI1IfStY0

5
  • OP is surely referring to the second input, 9.73
    – Air
    Commented Jul 1, 2014 at 20:45
  • Interestingly, when I say n = round(x*100), its all correct. I want to know whats going on inside.! Any help is appreciated!
    – PranavM
    Commented Jul 1, 2014 at 20:48
  • @PranavM and AirThomas my fault! I didn't notice that there are more than one input and output in the screenshot when editing the question!
    – kzidane
    Commented Jul 1, 2014 at 21:06
  • @AirThomas, when I replied, there was only one example.
    – curiouskiwi
    Commented Jul 1, 2014 at 22:52
  • My apology, @curiouskiwi!
    – kzidane
    Commented Jul 1, 2014 at 22:53
2

The compiler is not doing anything wrong; this is a typical "gotcha" of floating-point arithmetic.

What's happening here is that your input values are not being stored exactly as 9.72, 9.73 and 9.74 but rather as floating-point approximations of those numbers. They are very, very close to the input values, but off by a tiny amount, and printf() won't show the more precise value unless forced to. Try running this program:

#include <stdio.h>

int main(void)
{
    float n1 = 9.72;
    float n2 = 9.73;
    float n3 = 9.74;
    printf("9.72 times 100 is %.15f \n", n1 * 100);
    printf("9.73 times 100 is %.15f \n", n2 * 100);
    printf("9.74 times 100 is %.15f \n", n3 * 100);
}

You should see this output:

9.72 times 100 is 972.000000000000000 
9.73 times 100 is 972.999938964843750 
9.74 times 100 is 974.000000000000000 

When you assign those values directly to n, because n only stores integer values, everything after the decimal point gets truncated - even if the number is very, very close to the next integer. So you should always be careful when casting numeric values to, or storing them in, other numeric types.

In this case you can solve your problem by making sure to round your float to the nearest integer before you store its value.

For more information about floating-point numbers, you can explore the web site What Every Programmer Should Know About Floating-Point Arithmetic.

1

Well, if a compilation error happened, you won't be able to run your program at all because it won't compile (the executable ./remainder in your case won't exist)!

So this has nothing to do with the compiler.

Let's walk through your code to see what's really happening typically

  1. You get a float value from the user and store it in f (e.g., 9.73).

  2. You multiply this value by 100 and store the result in n. Notice that because n is an int, all the digits after the decimal points are truncated. So

    n = 9.73 * 100 = 973
    
  3. You then you divide n by 25 and storing the result in i. So

    i = 973 / 25 = 38
    
  4. Finally, you're taking the remainder of dividing n by 25 and storing the result in n. So

    973 / 25 = 38
    38 * 25 = 950
    973 - 950 = 23
    

    and you're printing the value of i and n respectively which should be 38 and 23.

But what really happened?

The problem is that floats are NOT precise. Meanwhile, when you enter a value like 9.73, it isn't necessarily stored as 9.73.

In fact, it may be stored as 9.72999954(depends on many things). And since you're storing it in an int, you get 972 stored at the end (as the digits after the decimal points are truncated).

You then play with the 972 all the way down through your code! And that explains why you get 22 instead of 23.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .