简体   繁体   中英

Why do simple math operations on floating point return unexpected (inaccurate) results in VB.Net and Python?

x = 4.2 - 0.1  

vb.net gives 4.1000000000000005
python gives 4.1000000000000005

Excel gives 4.1
Google calc gives 4.1

What is the reason this happens?

Float/double precision.

You must remember that in binary, 4.1 = 4 + 1/10. 1/10 is an infinitely repeating sum in binary, much like 1/9 is an infinite sum in decimal.

>>> x = 4.2 - 0.1 
>>> x
4.1000000000000005

>>>>print(x)
4.1

This happens because of how numbers are stored internally .

Computers represent numbers in binary, instead of decimal, as us humans are used to. With floating point numbers, computers have to make an approximation to the closest binary floating point value.

Almost all machines today (November 2000) use IEEE-754 floating point arithmetic, and almost all platforms map Python floats to IEEE-754 “double precision”. 754 doubles contain 53 bits of precision, so on input the computer strives to convert 0.1 to the closest fraction it can of the form J/2***N* where J is an integer containing exactly 53 bits.

If you print the number, it will show the approximation , truncated to a normal value. For example, the real value of 0.1 is 0.1000000000000000055511151231257827021181583404541015625 .

If you really need a base 10 based number (if you don't know the answer to this question, you don't ), you could use (in Python) decimal.Decimal :

>>> from decimal import Decimal
>>> Decimal("4.2") - Decimal("0.1")
Decimal("4.1")

Binary floating-point arithmetic holds many surprises like this. The problem with “0.1” is explained in precise detail below, in the “ Representation Error ” section. See The Perils of Floating Point for a more complete account of other common surprises.

As that says near the end, “there are no easy answers.” Still, don't be unduly wary of floating-point! The errors in Python float operations are inherited from the floating-point hardware, and on most machines are on the order of no more than 1 part in 2**53 per operation. That's more than adequate for most tasks, but you do need to keep in mind that it's not decimal arithmetic, and that every float operation can suffer a new rounding error.

While pathological cases do exist, for most casual use of floating-point arithmetic you'll see the result you expect in the end if you simply round the display of your final results to the number of decimal digits you expect. str() usually suffices, and for finer control see the str.format() method's format specifiers in Format String Syntax .

There is no problem, really. It is just the way floats work (their internal binary representation). Anyway:

>>> from decimal import Decimal
>>> Decimal('4.2')-Decimal('0.1')
Decimal('4.1')

In vb.net, you can avoid this problem by using Decimal type instead:

Dim x As Decimal = 4.2D - 0.1D

The result is 4.1 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM