views:

260

answers:

9

I came across this following arithmetic problem.

But the result is different from normal maths operation, Why is it so?

double d1 = 1.000001;

double d2 = 0.000001;

Console.WriteLine((d1-d2)==1.0);
+2  A: 

It is because computers do maths in base 2, and hence many decimal floating point numbers can not be represented exactly with a limited number of digits.

norheim.se
+1  A: 

this may be due to floating point precision problems as it could be that your outcome is not exactly 1.0 but maybe something like 1.000000000001

Joachim Kerschbaumer
+10  A: 

I presume you found the question on Jon Skeet's Brainteasers page? The answers are listed and explained here on the same website.

For a matter of reference, here's the answer copied from that page.


3) Silly arithmetic

Computers are meant to be good at arithmetic, aren't they? Why does this print "False"?

double d1 = 1.000001; double d2 =
0.000001; Console.WriteLine((d1-d2)==1.0);

Answer: All the values here are stored as binary floating point. While 1.0 can be stored exactly, 1.000001 is actually stored as 1.0000009999999999177333620536956004798412322998046875, and 0.000001 is actually stored as 0.000000999999999999999954748111825886258685613938723690807819366455078125. The difference between them isn't exactly 1.0, and in fact the difference can't be stored exactly either.


Noldorin
+1  A: 

This happens because floating point types store numbers using a base two and not a base ten representation. This has the consequence that double is unable to store values like 0.1 exactly. For example 0.1 is represented by the single value 0.100000001490116119384765625.

You have to use Decimal to get rid of the error.

Daniel Brückner
+2  A: 

Because you are using floating point numbers.

http://docs.sun.com/source/806-3568/ncg_goldberg.html

idstam
A: 

See what python docs has to saym the problem is the same for both:

http://docs.python.org/tutorial/floatingpoint.html

John Nolan
+1  A: 

This is due to the way that floating point numbers work in the CPU, it's not C# specific. See this Wikipedia entry and the paper here for more info.

The short answer is that floating point numbers aren't stored as an exact representation, so doing a comparison using "==" doesn't work in the way you are trying to use it.

Matt Warren
+2  A: 

From the MSDN entry for Double.Equals:

Precision in Comparisons

The Equals method should be used with caution, because two apparently equivalent values can be unequal due to the differing precision of the two values. The following example reports that the Double value .3333 and the Double returned by dividing 1 by 3 are unequal.

...

Rather than comparing for equality, one recommended technique involves defining an acceptable margin of difference between two values (such as .01% of one of the values). If the absolute value of the difference between the two values is less than or equal to that margin, the difference is likely to be due to differences in precision and, therefore, the values are likely to be equal. The following example uses this technique to compare .33333 and 1/3, the two Double values that the previous code example found to be unequal.

If you need to do a lot of "equality" comparisons it might be a good idea to write a little helper function or extension method in .NET 3.5 for comparing:

public static bool AlmostEquals(this double double1, double double2, double precision)
{
    return (Math.Abs(double1 - double2) <= precision);
}

This could be used the following way:

double d1 = 1.000001;

double d2 = 0.000001;

bool equals = (d1 - d2).AlmostEquals(1.0, 0.0000001);

See this very similar question: C#.NET: Is it safe to check floating point values for equality to 0?

0xA3
why the downcast and no comment? +1 to undo the -1. The answer might not be exactly what the user is asking, but it does offer a way to check for these kinds of calculations.
Davy Landman
+2  A: 

If you are doing such arithmetic in your application, the decimal type should be used

decimal d1 = 1.000001M;

decimal d2 = 0.000001M;

Console.WriteLine((d1 - d2) == 1.0M); // evaluates as true
Richard Ev
Be careful! decimal also has limited precision. Example: decimal d1 = 1.0M / 3.0M; decimal d2 = 3.0M; (d1 * d2) == 1.0M; // <-- this gives false!
0xA3