Agoric / nat

Ensures that a number is within the natural numbers (0, 1, 2...) or throws a RangeError
Apache License 2.0
5 stars 4 forks source link

Multiplication and Division with a Nat #60

Closed katelynsills closed 5 years ago

katelynsills commented 5 years ago

Should the Nat npm package describe how rounding with a nat works, especially as the result of division? It seems like an essential part of using Nat for financial purposes, and it would be nice to have a set standard for it.

erights commented 5 years ago

Nat does not round. It rejects numbers with a fractional part. To divide and have the result pass Nat, you'd have to do the rounding yourself.

Nat(Math.ceil(x/y))
Nat(Math.floor(x/y))
Nat(Math.round(x/y))
katelynsills commented 5 years ago

Yes, I would agree that the Nat test doesn't currently coerce and that it shouldn't. I'm suggesting that instead of making the user do the rounding and possibly getting it wrong (as far as I know, financial rounding has different rules than any of the Math methods), the Nat library also provides a financial rounding function and maybe even multiplication and division. This is is needed in something like uniswap.

erights commented 5 years ago

There is no one right way to do rounding or financial rounding. uniswap should round in a manner that clearly preserves its invariants (that the product stay above the limit) rather than encoding some financial rounding convention. See https://github.com/Agoric/ERTP/blob/uniswap/demo/contractHost/uniSwap.js#L61

Historical note: The IEEE decimal floating point standard does not canonicalize representations of the same number. "10.0" is different than "1.0e2". They use this representational difference to encode an approximation of financial rounding conventions that evolved during the practice of doing arithmetic with pen and paper. IIRC, some of these conventions have even been encoded in accounting standards. However, they do not correspond to any mathematically characterizable theory of preserving significance. Once we understood how incoherent it is, TC39 rejected IEEE decimal from JavaScript.

katelynsills commented 5 years ago

There is no one right way to do rounding or financial rounding

I found this article helpful. It implies that rounding rules are determined by the currency, so perhaps our strategies should have a round function.

I don't think I'm saying that there's one way to do rounding, but rather, that there are a few standard ways that are often used in financial programming. Once such standard would be banker's rounding. Others would be down, up, and half. I think leaving the users on their own to just use Math is probably a recipe for them to do it wrong or inconsistently. My understanding is that rounding in your own favor when doing financial programming is sometimes frowned-upon when audited. It would be nice to give users a few, well-written choices so that they deliberately choose their rounding algorithm. Maybe the rounding choices are a separate library than Nat, but I think it's necessary to provide somehow to allow users to use ERTP easily.

erights commented 5 years ago

Separate library would be good.