Truncate f-string float without rounding
Question:
I want to print a very very close-to-one float, truncating it to 2 decimal places without rounding, preferably with the least amount of code possible.
a = 0.99999999999
print(f'{a:0.2f}')
Expected: 0.99
Actual: 1.00
Answers:
I don’t think you need f-strings or math functions, if I understand you correctly. Plain old string manipulation should get you there:
a = 0.987654321
print(str(a)[:4])
output:
0.98
Not skilled enough in python yet certainly the floating point math is close enough to C here – which I am versed in.
Python’s float
, like C’s double
is base 2, so values like 0.xx
, aside from 0.00, 0.25, 0.50, 0.75
cannot be exactly encoded.
Let us try a=0.87
. The closest representable python float
value is:
# 1234567890123456789012
0.8699999999999999955591...
so the true value is less than 0.87.
Printing that with less than 18 digits (which str()
apparently does) results in a rounded up output.
# 12345678901234567
0.87000000000000000
And textually truncating that leads to "0.87"
, and does not meet “truncating it to 2 decimal places without rounding” as the original value was 0.8699999999999999955591…
To solve, code needs to either change the rounding mode of float
math before calling str()
to round toward 0 rather than round to nearest or convert to a string with extra precision. I suspect python can do this – I am not aware.
Even with additional precision (still using round to nearest), in the general case, there still may exist cases where the true value is xxx.xx(many 9’s)… that round up and thwart our textual truncation.
You could also try this approach by simply cutting of the decimals by cast the number to an integer and back to a float again:
num_decimals = 2
a = 0.99999999999
a = int(a * 10 ** num_decimals)/10 ** num_decimals
print(a) # => prints 0.99
I want to print a very very close-to-one float, truncating it to 2 decimal places without rounding, preferably with the least amount of code possible.
a = 0.99999999999
print(f'{a:0.2f}')
Expected: 0.99
Actual: 1.00
I don’t think you need f-strings or math functions, if I understand you correctly. Plain old string manipulation should get you there:
a = 0.987654321
print(str(a)[:4])
output:
0.98
Not skilled enough in python yet certainly the floating point math is close enough to C here – which I am versed in.
Python’s float
, like C’s double
is base 2, so values like 0.xx
, aside from 0.00, 0.25, 0.50, 0.75
cannot be exactly encoded.
Let us try a=0.87
. The closest representable python float
value is:
# 1234567890123456789012
0.8699999999999999955591...
so the true value is less than 0.87.
Printing that with less than 18 digits (which str()
apparently does) results in a rounded up output.
# 12345678901234567
0.87000000000000000
And textually truncating that leads to "0.87"
, and does not meet “truncating it to 2 decimal places without rounding” as the original value was 0.8699999999999999955591…
To solve, code needs to either change the rounding mode of float
math before calling str()
to round toward 0 rather than round to nearest or convert to a string with extra precision. I suspect python can do this – I am not aware.
Even with additional precision (still using round to nearest), in the general case, there still may exist cases where the true value is xxx.xx(many 9’s)… that round up and thwart our textual truncation.
You could also try this approach by simply cutting of the decimals by cast the number to an integer and back to a float again:
num_decimals = 2
a = 0.99999999999
a = int(a * 10 ** num_decimals)/10 ** num_decimals
print(a) # => prints 0.99