Jeff Walden (2013-07-12T23:07:04.000Z)
On 07/09/2013 06:49 PM, Mark S. Miller wrote:
> Because Nat includes 2**53, this code actually fails to enforce conservation of currency!!

The problem isn't that Nat includes 2**53.  It's that you're performing an operation that may compute an inexact value, then you're treating that inexact value *as if it were exact*.  You should be testing *before* performing any operation that might compute an inexact value.  Or, you should be rejecting values which might be rounded from an inexact value.  Which would mean your MAX_NAT test should instead be

  if (allegedNum >= MAX_NAT)      { throw new RangeError('too big'); }

But really, Nat seems like the wrong concept to me.  Even if you correct it as above, it's only correctly usable if it is applied after *every* floating point operation.  If you have |a + b|, you can correctly apply a corrected Nat to that.  But if you have |a + b + c| or |a + b - c| or any more floating-point operations than a single operation, Nat can't be correctly applied.  Corrected Nat as-is gives a false sense of security, by implying that you can apply it to a calculation and it'll do the right thing, when really it'll only do so if the value you're passing in is the result of no more than a single computation.

Jeff
domenic at domenicdenicola.com (2013-07-17T18:56:08.212Z)
On 07/09/2013 06:49 PM, Mark S. Miller wrote:
> Because Nat includes 2^53, this code actually fails to enforce conservation of currency!!

The problem isn't that Nat includes 2^53.  It's that you're performing an operation that may compute an inexact value, then you're treating that inexact value *as if it were exact*.  You should be testing *before* performing any operation that might compute an inexact value.  Or, you should be rejecting values which might be rounded from an inexact value.  Which would mean your MAX_NAT test should instead be

```js
if (allegedNum >= MAX_NAT)      { throw new RangeError('too big'); }
```

But really, Nat seems like the wrong concept to me.  Even if you correct it as above, it's only correctly usable if it is applied after *every* floating point operation.  If you have |a + b|, you can correctly apply a corrected Nat to that.  But if you have `a + b + c` or `a + b - c` or any more floating-point operations than a single operation, Nat can't be correctly applied.  Corrected Nat as-is gives a false sense of security, by implying that you can apply it to a calculation and it'll do the right thing, when really it'll only do so if the value you're passing in is the result of no more than a single computation.