I know how to keep only two decimal places after the decimal point. For example (there are other methods):
>>> print(f'{10000.01908223295211791992:.2f}')
10000.02
But I want to keep the first two digits other than zero after the decimal point:
10000.01908223295211791992 will give: 10000.019
0.0000456576578765 will give: 0.000046
Is there an built-in method that I'm missing? Or is the only solution to code a test for (almost) every case?
The following should be able to match the string and then round the value by applying a magnitude transformation.
import math
import re
TWO_DIGITS_AFTER_ZERO = re.compile(r'(\d+\.(?:(?:[1-9]*)?|0+)0[1-9]{2})')
def truncate(n: float) -> float:
if result := TWO_DIGITS_AFTER_ZERO.match(format(n, 'f')):
value = result.group(0)
magnitude = 10**len(value.split('.')[1])
return round(float(value) * magnitude) / magnitude
else:
return n
if __name__ == '__main__':
assert math.isclose(truncate(10000.01908223295211791992), 10000.019)
assert math.isclose(truncate(0.0000456576578765), 0.000046)
Here is an example utilizing the ndigits
keyword argument of the round()
function:
from math import floor, isclose, log10, modf
from typing import Callable
f: Callable[[float],float] = lambda n: round(n, -int(floor(log10(abs(modf(n)[0]))))+1)
if __name__ == '__main__':
assert isclose(f(10000.01908223295211791992), 10000.019)
assert isclose(f(0.0000456576578765), 0.000046)