I want to print floating point numbers which contain variable precision.
I have multiple numbers such as:
0.634564644534135499
0.0005462007746487777
0.028820785252590582
0.0018751147995774936
0.0075146048125540816
0.00046670455
I want to get the same numbers as output using print. I know that the number of decimal places can be fixed using print("{:.19f}".format(0.0005462007746487777)) but I don't want to make the number of decimal places fixed. Since different numbers will have different decimal places
Code
#!/usr/bin/env python3
number_1=0.634564644534135499
number_2=0.0005462007746487777
number_3=0.028820785252590582
number_4=0.0018751147995774936
number_5=0.0075146048125540816
number_6=0.00046670455
print("Number 1: ",number_1)
print("Number 2: ",number_2)
print("Number 3: ",number_3)
print("Number 4: ",number_4)
print("Number 5: ",number_5)
print("Number 6: ",number_6)
Actual Output:
Number 1: 0.6345646445341355
Number 2: 0.0005462007746487777
Number 3: 0.028820785252590582
Number 4: 0.0018751147995774936
Number 5: 0.0075146048125540816
Number 6: 0.00046670455
Required Output:
Number 1: 0.634564644534135499
Number 2: 0.0005462007746487777
Number 3: 0.028820785252590582
Number 4: 0.0018751147995774936
Number 5: 0.0075146048125540816
Number 6: 0.00046670455
What I don't understand is why Number 2(which has higher precision) is being printed correctly but Number 1 losses its precision?
Fundamentally what you require is not possible with float objects, which are basically wrappers around C-doubles, so 64-bit floating point numbers.
There are several things going on here. There is the fundamental problem with mapping a decimal literal input in your source code:
0.634564644534135499
To an actual machine representation, which is not decimal, but binary.
Due to the inherent constraints of the 64-bit floating point format, multiple decimal inputs will be mapped to the same underlying representation:
>>> 0.634564644534135499 == 0.6345646445341355
True
Which is actually neither of those, the exact decimal is actually:
>>> import decimal
>>> decimal.Decimal(0.6345646445341355)
Decimal('0.6345646445341355246227976749651134014129638671875')
>>> decimal.Decimal(0.634564644534135499)
Decimal('0.6345646445341355246227976749651134014129638671875')
What is actually printed when you naively print(some_float) is going to be a representation which is guaranteed to map back to the same float that produced it if you enter it as a float decimal literal. In fact, since Python 3.1 CPython uses David Gray's algorithm for finding the shortest such representation that preserves the value.
So, as is often the case when encountering troubles due to the inherent limitation of float, try using decimal.Decimal. Remember, the input should be a string. The following script:
import decimal
number_1 = decimal.Decimal('0.634564644534135499')
number_2 = decimal.Decimal('0.0005462007746487777')
number_3 = decimal.Decimal('0.028820785252590582')
number_4 = decimal.Decimal('0.0018751147995774936')
number_5 = decimal.Decimal('0.0075146048125540816')
number_6 = decimal.Decimal('0.00046670455')
print("Number 1: ",number_1)
print("Number 2: ",number_2)
print("Number 3: ",number_3)
print("Number 4: ",number_4)
print("Number 5: ",number_5)
print("Number 6: ",number_6)
Prints:
Number 1: 0.634564644534135499
Number 2: 0.0005462007746487777
Number 3: 0.028820785252590582
Number 4: 0.0018751147995774936
Number 5: 0.0075146048125540816
Number 6: 0.00046670455
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With