ericmj / decimal

Arbitrary precision decimal arithmetic

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

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Context precision limit

giddie opened this issue · comments

I have a question about default precision (related to #201).

Elixir/BEAM has arbitrary-precision integers that "just work" at any precision, as far as I'm aware. So I was a bit taken aback to discover that Decimal has this 28-digit precision limit by default. I'm wondering if there is some possible path toward lifting the precision limit (ideally by default)?

We cannot have infinite precision real numbers, if we did we couldn't represent irrational numbers such as Pi or the result of operations such as 1/3.

OK, interesting. So to put this in context, the issue we're facing here is that Ecto uses Decimal to represent numeric columns in PostgreSQL. Numerics are how arbitrary-precision integers are generally represented in Postgres. We store some large numbers, and later want to do simple arithmetic. But we run into issues doing a simple add.

An illustration, just for a bit of colour:

a = Decimal.new(11111111111111111111111111111)

Decimal.add(a, a)
|> Decimal.to_integer()

22222222222222222222222222220

I can see the rationale for why this is happening - the precision is applied uniformly for all operations. But following the principle of least surprise, I wonder if the precision should be ignored for operations that can be performed safely as integer arithmetic? Because the precision is really only needed if the result may be a non-integer, right?

Otherwise, given that Postgres does have some physical boundary on the precision of its numeric type, could it be sensible to encode a precision into the %Decimal{} struct itself, to avoid relying on a global default precision? That way Ecto could specify a reasonable precision when casting the column.

Just for reference, according to the docs, Postgres numeric precision is "up to 131072 digits before the decimal point; up to 16383 digits after the decimal point".