c#: sum of two double numbers problem [duplicate]
Possible Duplicate:
Why is floating point arithmetic in C# imprecise?
Hi. I've got following pr开发者_StackOverflow中文版oblem:
43.65+61.11=104.75999999999999
for decimal is correct:
(decimal)43.65+(decimal)61.11=104.76
Why result for double is wrong?
This question and its answers are a wealth of info on this - Difference between decimal, float and double in .NET?
To quote:
For values which are "naturally exact decimals" it's good to use decimal. This is usually suitable for any concepts invented by humans: financial values are the most obvious example, but there are others too. Consider the score given to divers or ice skaters, for example.
For values which are more artefacts of nature which can't really be measured exactly anyway, float/double are more appropriate. For example, scientific data would usually be represented in this form. Here, the original values won't be "decimally accurate" to start with, so it's not important for the expected results to maintain the "decimal accuracy". Floating binary point types are much faster to work with than decimals.
Short answer: floating point representation (such as "double") is inherently inaccurate. So is fixed point (such as "decimal"), but the inaccuracy in fixed-point representation is of a different kind. Here's one short explanation: http://effbot.org/pyfaq/why-are-floating-point-calculations-so-inaccurate.htm
You can google for "floating point inaccuracy" or so for more.
It isn't exactly wrong. It's the closest decimal representation to the binary floating-point number that results from the sum.
The problem is that IEEE floats cannot represent 43.65 + 61.11 exactly, due to the use of a binary mantissa. Some systems (such as Python 2.7 and Visual C++'s standard I/O libraries) will round to the simplest decimal that resolves to the same binary, and will print the expected 104.76. But all these systems arrive at exactly the same answer internally.
Interestingly, decimal notation can finitely represent any finite binary fraction, whereas the opposite doesn't hold. If humans had two fingers and computers used ten-state memory, we wouldn't have this problem. :-)
Because double uses a fractional model. Any number < 1 is expressed in the form of x / y. Given that information, some numbers can only be approximated. Use decimal, not double for high precision calculations.
See here for some light reading :)
It comes down to the fact that floats are stored as binary floats, and like in base 10, there are some numbers which can't be stored without truncation. Take for example 1/3rd in base 10, that is .3 recurring. The numbers you are dealing with, when converted to binary are recurring.
I disagree that floats or doubles are more or less accurate than decimal representations. They are as accurate as you choose to have precision. They are a different representation however, and different numbers can be expressed wholey than in base 10.
Decimal stores numbers in base 10. That will probably give you the result you expect
Decimal arithmetic is well-suited for base-10 representations of numbers, as base-10 numbers can be exactly represented in decimal. (Which is why currency is always stored in currency appropriate classes, or stored in int
with a scaling factor to represent 'pennies' or 'pence' or other similar decimal currency.)
IEEE-754 Binary numbers cannot calculate with .1
or .01
accurately. So floating point formats approximate the inputs, and you get approximate outputs back, which is perfectly acceptable for what floating point was designed to handle -- physical simulations, scientific data, and fast numerical mathematical methods.
Note this simple program and output:
#include <stdio.h>
int main(int argc, char* argv[]) {
float f, g;
double d, e;
long double l, m;
f=0.1;
g=f*f;
d=0.1;
e=d*d;
l=0.1;
m=l*l;
printf("%40.40f, %40.40f, %40.40Lf\n", g, e, m);
return 0;
}
$ ./fp
0.0100000007078051567077636718750000000000,
0.0100000000000000019428902930940239457414,
0.0100000000000000011102569059430467124372
All three possibilities don't give the exact answer, 0.01
, but they do give numbers that are quite close to the answer.
But use decimal arithmetic for currency.
Really? The code below returned 104.76 as expected:
class Program
{
static void Main(string[] args)
{
double d1 = 43.65;
double d2 = 61.11;
double d3 = d1 + d2;
Console.WriteLine(d3);
Console.ReadLine();
}
}
whereas the below code returned 104.76000213623
class Program
{
static void Main(string[] args)
{
float d1 = 43.65f;
float d2 = 61.11f;
double d3 = d1 + d2;
Console.WriteLine(d3);
Console.ReadLine();
}
}
Check if you are converting from float to double which may have caused this issue.
精彩评论