python How to Remove Invalid 0 and Invalid '.' Sign at Tail of Floating Point Numbers

  • 2021-10-11 18:55:21
  • OfStack

Method 1:


a = 12.12300 # The result requirements are 12.123  
b = 12.00 # The result is 12
c = 200.12000 # The result is 200.12
d = 200.0 # The result is 200
 
print 'a==>' ,[ str (a), int (a)][ int (a) = = a]
print 'b==>' ,[ str (b), int (b)][ int (b) = = b]
print 'c==>' ,[ str (c), int (c)][ int (c) = = c]
print 'd==>' ,[ str (d), int (d)][ int (d) = = d]

Method 2:


for i in [ 12.12300 , 12.00 , 200.12000 , 200.0 ]:
 print ( '{:g}' . format (i))

Add: Only 1% of Python programmers have understood the floating-point trap

It has a slight taste of clickbait title, but the content is pure dry goods. Let's start with an example


>>> 0.1+0.2==0.3
False

You may be surprised when you see this result for the first time. It turns out that there is such a big bug. Let's see what the expression 0.1 +0.2 is equal to.


>>> 0.1+0.2
0.30000000000000004

It's completely beyond our imagination. So what happened to this operation in the computer?

Let's go back to binary.

First of all, we need to be clear about one point. In computers, integers, floating-point numbers, or strings are ultimately represented in binary.

Binary representation of integers

The integer 9 is represented by binary system in computer: 1001. How did you get it?

Divide a decimal integer integer by 2 to get the quotient and remainder, which is the lowest bit of a binary number, and then continue to divide the quotient integer by 2 to get the new quotient and remainder, and so on until the quotient equals 0, and all the remainders are inverted to form the binary representation of the integer. In code, it is:


>>> n = 9
>>> while n >0:
  n,e = divmod(n, 2) # divmod Return n Divide by 2 Quotient and remainder of 
  print(e)
1 #  Low position 
0
0
1 #  High position 

Convert binary to decimal integers

We know that the decimal system can be expressed by scientific calculation as:


123 = 1*10^2 + 2*10^1 + 3*10^0 
= 100 + 20 + 3 
= 123

By the same token, if it is a binary number, it can mean:


1001 = 1*2^3 + 0*2^2 +0*2^1 + 1*2^0
= 8+0+0+1 
= 9

Let's look at floating point numbers again

Binary Representation of Floating Point Numbers

There is no difference between binary decimal and binary integer. They are all composed of 0 and 1, but there is only one more point. For example, 101.11 is a binary decimal, and the corresponding decimal number is:


101.11 = 1*2^2 + 0*2^1 + 1*2^0 + 1*2^-1 + 1* 2^-2
= 4 + 0 + 1 + 1/2 + 1/4
= 5 + 0.5 + 0.25
= 5.75

The left side of the decimal point is represented by 2 ^ n, and the value to the right side of the decimal point is represented by 2 ^-n.

Converting floating-point numbers to binary decimals

To convert a decimal floating-point number into a binary decimal number:

The integer part before the decimal point is operated in the way of decimal to binary

Multiply the decimal part by 2, take the integer 0 or 1, and continue multiplying the remaining decimal part by 21 until the decimal part is 0 or reaches the specified precision

For example, 2.25 is converted to binary decimal, integer 2 is converted to binary is 10, and decimal part 0.25 is converted to binary:


0.25 * 2 = 0.5  Integer is 0 Where the decimal number is 0.5
0.5 * 2 = 1.0   Integer is 1 Where the decimal number is 0

So 2.25 for binary decimal is 10.01, but not every floating-point number is so lucky that it ends up multiplied by 2 and the decimal is 0. For example, 0.2 for binary is:


0.2*2 = 0.4  Integer is 0 Where the decimal number is 0.4
0.4*2 = 0.8  Integer is 0 Where the decimal number is 0.8
0.8*2 = 1.6  Integer is 1 Where the decimal number is 0.6
0.6*2 = 1.2  Integer is 1 Where the decimal number is 0.2
0.2*2 = 0.4  Integer is 0 Where the decimal number is 0.4
0.4*2 = 0.8  Integer is 0 Where the decimal number is 0.8
0.8*2 = 1.6  Integer is 1 Where the decimal number is 0.6
0.6*2 = 1.2  Integer is 1 Where the decimal number is 0.2

1 Repeat straight....

0.2 in binary is 0.001100110011 …, and you will find that 0.2 can't be accurately expressed in binary at all. Just as 1/3 can't be accurately expressed as 1 by decimal, only 1 approximation can be taken.

If you convert this binary decimal number 0.001100110011 back to decimal, it is:


for i in [ 12.12300 , 12.00 , 200.12000 , 200.0 ]:
 print ( '{:g}' . format (i))
0

This is only a number close to 0.2. The higher the precision, the closer it is to 0.2, but it can never be equal to 0.2. So how are floating-point numbers stored inside the computer?

According to the international standard IEEE 754, a binary floating-point number V is divided into three parts, which can be expressed by the following formula:

s represents a sign bit, and when s=0, V is a positive number;

When s=1, V is negative

M represents a significant number, 1 < =M < 2

E represents exponential bits

For example, 1.25 in decimal is 1.01 in binary, which is equivalent to 1.01 × 2 0 in this formula. It can be concluded that s=0, M=1. 01 and E=0.

IEEE 754

1. For a 32-bit floating-point number, the highest bit is the sign bit s, the next 8 bits are the exponent E, and the remaining 23 bits are the significant number M.

2. For 64-bit floating-point numbers, the highest 1 bit is the sign bit S, the next 11 bits are the exponent E, and the remaining 52 bits are the significant number M

3. The first digit of M is always 1, which will be discarded. For example, when saving 1.01, only the 01 part after the decimal point is actually saved

4. The true value of E must be subtracted by an intermediate number. For 8-bit E, this intermediate number is 127; For an 11-bit E, the median number is 1023.

Based on the above rules, we can verify floating-point numbers, and we can use the following function to see the actual stored value of a floating-point number in the computer:


for i in [ 12.12300 , 12.00 , 200.12000 , 200.0 ]:
 print ( '{:g}' . format (i))
1

The actual stored value of floating-point number 0.2 is 1045220557, and the corresponding binary system is 111110010011001100110011001101. When converted into a 32-bit integer, two zeros must be filled in front of it, and finally it becomes:


for i in [ 12.12300 , 12.00 , 200.12000 , 200.0 ]:
 print ( '{:g}' . format (i))
2

The highest bit is 0, so it represents a positive number. Next, 8 bits 01111100 are exponential bits E, corresponding to an integer of 124. According to IEEE 754, the true value of E should be subtracted by 127, so E=-3. Finally, 23 is the value of M, because one bit is omitted before, so the true value of M is:


1.10011001100110011001101

Finally, the value of V is:


for i in [ 12.12300 , 12.00 , 200.12000 , 200.0 ]:
 print ( '{:g}' . format (i))
4

Its actual value is 1 point larger than 0.2, so I saw the first act.


Related articles: