'Python, Convert Arbitrary List of Floats to Decimals with Most Precision without Rounding Errors

I'm writing code that has to take a bunch of floats in Python and convert them to decimals without any rounding errors but with as much precision as possible. I'm not sure what the best approach to solve this is. Just based on some empirical tests, this seems to work OK:

import math
from decimal import Decimal
numbers = [2400.2, 4800.3, 3000, 1.1 + 2.2, 0.000000000000006, -1.418686791445350, 1.418686791445356666666, 2400.418686791445350]

def orderOfMagnitude(number):
  return math.floor(math.log(abs(number), 10))

for num in numbers:
  places = 14 - orderOfMagnitude(num)
  dec = Decimal(num).quantize(Decimal(f'1.{"0"*places}'))
  print(dec)

output:

2400.20000000000
4800.30000000000
3000.00000000000
3.30000000000000
6.00000000000000E-15
-1.41868679144535
1.41868679144536
2400.41868679145

but of course there could be a counterexample where this doesn't work and there is an error. For example, if I use 15 instead of 14 in the formula for places I get:

2400.200000000000
4800.299999999999
3000.000000000000
3.300000000000000
6.000000000000000E-15
-1.418686791445350
1.418686791445357
2400.418686791445

and you can see the error for 4800.3.

What is the proper way to convert an arbitrary list of floats to decimals with as much precision as possible without rounding errors? Is this even possible?

Edit: I'm on Windows 10 and Python 3.8 if that makes a difference.



Solution 1:[1]

import math
from decimal import Decimal
numbers = [2400.2, 4800.3, 3000, 1.1 + 2.2, 0.000000000000006, -1.418686791445350, 1.418686791445356666666, 2400.418686791445350]

def orderOfMagnitude(number):
  return math.floor(math.log(abs(number), 10))

for num in numbers:
  places = 15 - orderOfMagnitude(num)
  dec = Decimal(num).quantize(Decimal(f'1.{"0"*places}'))
  print(dec)

works well

2400.200000000000
4800.300000000000
3000.000000000000
3.300000000000000
6.000000000000000E-15
-1.418686791445350
1.418686791445357
2400.418686791445

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ashkan Goleh Pour