tags:

views:

844

answers:

6

Consider this:

double x,y;
x =120.0;
y = 0.05;

double z= x % y;

I tried this and expected the result to be 0, but it came out 0.04933333.

However,

x =120.0;
y = 0.5;
double z= x % y;

did indeed gave the correct result of 0.

What is happening here?

I tried Math.IEEERemainder(double, double) but it's not returning 0 either. What is going on here?

Also, as an aside, what is the most appropriate way to find remainder in C#?

+8  A: 

doubles are never exact values. 120 is probably stored lossless, but 0.05 not. 0.5 is 1/2, so it could be stored lossless and you don't get a rounding error.

To have exact (decimal) numbers, use decimal instead.

decimal x,y;
x =120.0M;
y = 0.05M;

decimal z = x % y;  // z is 0
Stefan Steinegger
A: 

http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems can help you understand why you get these "strange" results. There's a particular precision that floating point numbers can have. Just try these queries and have a look at the results:

0.5 in base 2

0.05 in base

Flo
A: 

Modulus is defined in msdn as:

x - (x / y) * y

If you do it this way manually it seems to get the correct result.

Cookey
why should this return the correct result? If y is an inexact value, this produces the same error.
Stefan Steinegger
You have to include floor for floating point numbers - this works only with '/' performing an integer division.
Daniel Brückner
Not sure why this "should" work, but it does with the 2 doubles provided in the example.
Cookey
+1  A: 

You could do something like:

double a, b, r;

a = 120;
b = .05;

r = a - Math.floor(a / b) * b;

This should help ;)

Kevin D.
Simple solution :-)
Stefan Steinegger
A: 

Modulus should only be used with integer. The remainder come from an euclidean division. With double, you can have unexpected results.

See this article

rockeye
you could safely use modulus with decimals.
Stefan Steinegger
A: 

I believe if you tried the same with decimal it would work properly.

configurator