ericmj / decimal

Arbitrary precision decimal arithmetic

Home Page:https://hexdocs.pm/decimal/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

to_string(:normal) should omit trailing 0s after decimal point

lukaszsamson opened this issue · comments

Is:

iex(19)> Decimal.new("1.2340000E-1")|>Decimal.to_string(:normal)
"0.12340000"
iex(20)> Decimal.new("1.2340000")|>Decimal.to_string(:normal)   
"1.2340000"
iex(21)> Decimal.new("1656577575.2340000")|>Decimal.to_string(:normal)
"1656577575.2340000"
iex(22)> Decimal.new("1656577864874875876578587575.2340000")|>Decimal.to_string(:normal)
"1656577864874875876578587575.2340000"

Should be:

iex(19)> Decimal.new("1.2340000E-1")|>Decimal.to_string(:normal)
"0.1234"
iex(20)> Decimal.new("1.2340000")|>Decimal.to_string(:normal)   
"1.234"
iex(21)> Decimal.new("1656577575.2340000")|>Decimal.to_string(:normal)
"1656577575.234"
iex(22)> Decimal.new("1656577864874875876578587575.2340000")|>Decimal.to_string(:normal)
"1656577864874875876578587575.234"

I think we print as many zeros as the coefficient has precision according to: http://speleotrove.com/decimal/daconvs.html#reftonum.

If you call Decimal.reduce/1 before it should remove the extra zeros.

Shouldn't Decimal.to_string(:normal) call Decimal.reduce/1 before printing then?

No, because sometimes you want to print with the full precision. For example when printing money amounts: "$8.00".

@ericmj but you don't have real control over how many digits are printed. You can always round but it's rather cumbersome.

iex(27)> Decimal.new("1.230")|>Decimal.round(2)|>Decimal.to_string(:normal)
"1.23"
iex(28)> Decimal.new("1.230")|>Decimal.round(0)|>Decimal.to_string(:normal)
"1"
iex(29)> Decimal.new("1.230")|>Decimal.round(-1)|>Decimal.to_string(:normal)
"00"

Especially, there is no way to print value in format 01.23

To print money amounts a separate format api is needed like JS toFixed

Anyway, I noticed some some inconstancies in trailing 0s handling, e.g.

iex(11)> Decimal.div(Decimal.new("122.0"), Decimal.new("1.0"))|>Decimal.to_string(:normal)
"122"
iex(12)> Decimal.mult(Decimal.new("122.0"), Decimal.new("1.0"))|>Decimal.to_string(:normal)
"122.00"

It's not about controlling how many digits are printed, although we can add a mechanism for that, it's about printing the full precision of the coefficient.

If the results of operations div and mult prints a number with an unexpected precision it's probably due to bugs in their implementation where they don't keep the correct precision but I would suggest reading their specification first.

OK, I'm convinced that it need to stay like that to be spec-compliant. Anyway, better formatting tools would be helpful.