Today I faced a strange problem in C#. I have an ASP.NET page where user can ent开发者_如何学Pythoner certain price, quantity etc. I get the price value, convert it to double, then multiply it with 100 and then typecast it to an integer. When the price is "33.30", after converting it to double it remains 33.3 (obviously...), but after multiplying it with 100, it becomes 3329.9999999999995, and when I cast it to integer by applying simple cast operator "(int) (price * 100) ", it becomes 3329.
Right now I have no idea why this is happening. So I thought may be you guys can help :) .
This happens because of the way doubles are stored. You should use decimal
when working with money to avoid rounding errors.
don't cast it, round it using Math.Round. and its better to use a decimal type for currency
This is happening due to floating point rounding errors. Floating point numbers cannot be accurately represented in binary, so rounding errors such as the one you are experiencing happen. See this wikipedia article for more detail.
To overcome this, you should round to the closest integer - this is best achieved by using Math.Round
.
When dealing with currencies however, best practice it to use the decimal
type instead of double
.
If you want to cast to the closest integer there is a Math.Round
method for this.
What you are doing by default is flooring
- which is exactly what you observe. (and is consistent with C)
The error is because doubles are stored in binary form. While every binary fraction has an exact decimal expansion, most decimals don't have an exact binary expansion. The decimal 33.3 has an inexact binary expansion. This approximation is then multiplied by 100, and converted to its exact decimal expansion, which is 3329.9999999999995. (Actually, this may not be the exact expansion, due to display truncation, but the gist of it is the same.)
Floating Point arithmetic in computing is almost always an approximation of the "Real" value
精彩评论