So I'm trying to make a function that returns a stringified decimal in the most readable format. These are the requirements I have created for myself:
25000000000 -> 2.5E+9
, 0.0000000036 -> 3.6E-9
)103.400000 -> 103.4
, 0.000005600 -> 0.0000056
)Currently, I'm using some code that I modified from this answer, but I can't really see a way to get it to match my requirements exactly.
Currently, my solution is as follows:
def stringifyDecimal(d: Decimal):
# If d is within a reasonable range for printing as a normal number
a = abs(math.log10(abs(d)))
if a < 9:
r = d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()
else:
r = d.normalize()
return str(r)
This works great for larger numbers:
stringifyDecimal(D('1E5')) -> '10000'
stringifyDecimal(D('1E9')) -> '1E+9'
But for very small fractions, it will always be returned in scientific notation:
stringifyDecimal(D('1E-7')) -> '1E-7'
This is because of the ...else d.normalize()
part of the 5th line, which returns a Decimal that will stringify to scientific notation by default. Sadly, formatting options won't work for this as they require me to know the exact precision that I want to format to.
Is there a way that I can force the Decimal type to display a very small fraction as a decimal rather than in scientific notation?
Ok so the most effective method I've found is to use string formatting.
d = Decimal('152')
print(f"{d:f}") # Format as a standard decimal
print(f"{d:e}") # Format in scientific notation
from this, my solution is as follows:
def strDecimal_Sci(d: Decimal) -> str:
return f"{d.normalize():e}"
def strDecimal_Norm(d: Decimal) -> str:
return f"{d.normalize():f}"
def stringifyDecimal(d: Decimal) -> str:
if d == 0: return "0"
a = abs(math.log10(abs(d)))
if a < 9:
return strDecimal_Norm(d)
else:
return strDecimal_Sci(d)