Skip to content

Consider adding an overflow option on .toNumber() #46

@eemeli

Description

@eemeli

When casting an Amount to a Number, it's possible that the result would not have the same decimal string representation as the Amount's value. As in:

let a = new Amount('0.1')
let b = new Amount('0.10000000000000001')

String(a) === String(a.toNumber()) // '0.1' === '0.1'
String(b) !== String(b.toNumber()) // '0.10000000000000001' !== '0.1'

It's also possible (actually, pretty likely for non-integer values) that the 𝔽(x) finite Number value is different from the Amount's mathematical value:

let c = new Amount('0.25')
let d = new Amount('0.3')

String(c) === c.toNumber().toFixed(60).replace(/0+$/, '') // '0.25' === '0.25'
String(d) !== d.toNumber().toFixed(60).replace(/0+$/, '') // '0.3' !== '0.299999999999999988897769753748434595763683319091796875'

So we have at least the above two definitions by which calling .toNumber() can be observably lossy. Should we maybe add an option like Temporal's overflow: 'constrain' | 'restrict' to .toNumber()? This would make calling it throw a RangeError for one or both of the precision-loss cases:

new Amount('0.25').toNumber({ overflow: 'restrict' }) // ok, 0.25

new Amount('0.10000000000000001').toNumber() // ok, 0.1
new Amount('0.10000000000000001').toNumber({ overflow: 'restrict' }) // error

new Amount('0.3').toNumber({ overflow: 'restrict' }) // ok or error?

I'm not completely sure myself whether this is warranted, but it would address the use case presented in Lxxyx/proposal-number-is-safe-numeric#4.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions