shopspring / decimal

Arbitrary-precision fixed-point decimal numbers in Go
Other
6.41k stars 623 forks source link

Behaviour of `Pow` changed in v1.4 #380

Open EVODelavega opened 3 months ago

EVODelavega commented 3 months ago

As part of v1.4.0, the PowPrecisionNegativeExponent was added, which limits the default precision of Pow() when using negative exponents to 16. When using this package to express amounts of crypto assets, 18 decimal places is extremely common. Storing balances/transfer amounts in the smallest possible decimal (e.g. in case of ETH, storing the amounts in wei) is standard practice. Converting these amounts to and from a more human-readable format (or the corresponding amount in ETH), I rely on a fair amount of code that looks somewhat like this:

    asset := app.GetAsset(assetID)
    // 10e-18
    factor := decimal.DecimalFromFloat(10).Pow(decimal.NewFromInt(-asset.Decimals))
    inAsset := someAmount.Mul(factor)

This worked fine before updating the dependency version, where there was no cap on the negative exponent when calling Pow. For my use-case, setting this value to at least a sensible default makes more sense, but truthfully, I believe a negative exponent ought not to be capped. Using 10^-N is an expression of precision in and of itself.

As part of the linked PR, I've also increased the default division precision to 18 for the same reason as above (crypto assets having 18 decimal places). I've kept it as a separate commit, which I can revert if needed.

PR: https://github.com/shopspring/decimal/pull/379