开发者

.Net and multiplication of singles

Can anyone explain this weirdness:

Dim result as single = 0
result = CType("8.01", Single) * 100 ' result=801.0 as expected
result = CType("8.02", Single) * 100 ' re开发者_高级运维sult=802.000061 --- not expected

Further to the above

result = 8.02 * 100 ' result = 802.0 as expected


Single (or float) only has seven significant digits, so everything that might be printed beyond those is pretty much bogus anyway. This is a normal artifact of floating-point arithmetic. You can only rely on up to 4 digits after the decimal point with your number (as three significant digits are already before the decimal point).

Further elaborated, the numbers 8.01 and 8.02 can't be represented exactly using binary storage (as neither 0.01 nor 0.02 can be represented exactly with sums of fractions of the form 1/2n). The details may vary from number to number but you may see extraneous digits outside the normal precision range when using such numbers.

This doesn't affect the fact that 801 and 802 can be represented exactly but you have no exact number to start with in this case.

ETA: In fact, what you see when you include the calculation directly is just this: The compiler will evaluate the calculation for you and simply write 802 into the program. You can use Reflector to verify that. Also floating point literals in the source code are likely Double by default so you have much greater precision to begin with here. If result is a Single this will be downcasted to Single and the error in the 16th digit after the decimal point is simply thrown away since it can't fit into Single anyway.


This is due to a limitation in the way floating point numbers are represented in memory. Have a read through the wikipedia page for the full lowdown - it's not an error, or something specific to .net.

EDIT: these two articles are worth a look too (the latter is math heavy).

  • http://www.techradar.com/news/computing/why-computers-suck-at-maths-644771
  • http://docs.sun.com/source/806-3568/ncg_goldberg.html


If what you need is to compare floating point values, see here: Comparing floating point values


Single and Double in .NET are represented as floating point numbers and unfortunately storing these kinds of numbers is not precise. You will get small discrepancies when working with 'Single' and 'Double' numbers.

However there is an alternative - .NET has a Decimal type which is much better at dealing with these numbers. It's still not perfect (see http://www.yoda.arachsys.com/csharp/decimal.html - in particular the last paragraph) but will be much better at representing quantities like money.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜