Decimal Math, Floating Point Precision, and Exponents in RatioMath #7967
Replies: 1 comment 2 replies
-
The design of Amounts is to use an integer quantity so that the are never ambiguities of precision. The "decimalPlaces" of the brand specifies how many of the countable unit there are in the human-scale unit (ee.g. 6 decimal places) but all the math is done ignoring that scaling parameter. It's just an integer. Specifically a bigint so that it can be arbitrarily large and not subject to overflow problems. (It also wraps access in RatioMath is for working with ratios of Amounts.
I'm not sure I understand the question. If you mean can a ratio multiplicand support repeated multiplication by the same multipler, yes. There is no possibility of overflow with ratios because they use bigint. Now, the numerator and denominator could get very large. But you can always quantize down to the precision you need: agoric-sdk/packages/zoe/src/contractSupport/ratio.js Lines 332 to 348 in b05c226
Not in Amounts or Ratios, no. They are designed to have fixed precision to prevent a class of bugs.
If your precision is the decimal places of an Amount, use a bare amount. If you need more precision, make a ratio. Quantize it to the precious you need. You may find Inter Protocol's interest module helpful. |
Beta Was this translation helpful? Give feedback.
-
Around 49:50 in yesterday’s office hours, @dckc started talking about BigInts, RatioMath, and floating point precision. Some chatter ensued in Discord, and I’d like to start a discussion here as I was unable to find any for the “exponent”, “logarithm”, or “decimal” keywords.
I am aware that floating point precision is a complex topic and am by no means an expert. But as a consumer of this software, some topics I am interested in learning about are:
1. Can RatioMath support exponents? (i.e.,
exponentiateRatios(baseRatio, expRatio)
)RatioMath has been a pleasure to use, but I ran into a blocker when trying to introduce exponents.
In this snippet here, I am attempting to calculate continuous interest (Pe^rt) with ratios using a fictitious
exponentiateRatios()
function. Is this something that could be supported, or would overflows be too much of a concern? Perhaps there could also beexponentiateRatioBy(baseRatio, exp)
andexponentiateByRatio(base, expRatio)
signatures.2. Will the agoric-sdk ever support arbitrary precision decimals as part of the official sdk (something like BigDecimal)?
This is maybe something that would need to come from the ES community, but I am curious to get thoughts nonetheless. From a DX perspective it seems like BigInt/RatioMath is enough to get you where you need, but it’d be great to have something to reach to when decimals or irrational numbers are needed!
3. What is the recommended way (best practice) for working with decimals in a smart contract?
makeRatio()
allows us to express rational numbers and approximations of irrational numbers with precision and seemingly handles a majority of use cases, but has limitations with exponents and trig.We also have the JS-native Math object (minus
.rand()
) and number primitive, but I imagine something like this is not recommended for use in a production contract due to loss of precision. (0.1 + 0.2 !== 0.3
)I believe @dckc was exploring libraries like exactnumber and MikeMcl’s family of libraries - big.js, bignumber.js, decimal.js, and decimal.js-light during some weekend skunk works time, so perhaps he may have some more thoughts to share in due course.
Beta Was this translation helpful? Give feedback.
All reactions