domenic at domenicdenicola.com (2013-07-17T18:56:54.879Z)
On Fri, Jul 12, 2013 at 4:07 PM, Jeff Walden <jwalden+es at mit.edu> wrote:
> 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.
Mark's Nat() function *does* throw if the input isn't an
exactly-representable number.
On Fri, Jul 12, 2013 at 4:07 PM, Jeff Walden <jwalden+es at mit.edu> wrote: > 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. Mark's Nat() function *does* throw if the input isn't an exactly-representable number. ~TJ