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
Asked By: Michael Bianconi

||

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
Answered By: Jack Fleeting

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
Answered By: anka