mathjs: Why does 1cm + 1mm give rounding error, but 1mm + 1cm does not?
When using eval
with units, first unit in string is set as the “ground” unit for the calculation. For example:
const m = require('mathjs')
m.eval('1cm + 1mm').toString() // '1.0999999999999999 cm'
m.eval('1mm + 1cm').toString() // '11 mm'
The result is a funny difference in the output format. Of course one could force output format:
m.eval('1cm + 1mm').format(2) // '1.1 cm'
m.eval('1mm + 1cm').format(2) // '11 mm'
I guess this is because first calculation is done with decimal (1 mm as 0.1 cm, which is not precise in binary) and second calculation in integers. As I see it, a sensible heuristic could be:
- “Sort” inputs by SI-prefix, smallest SI-prefix first.
- Convert all inputs to this SI-prefix.
- Do calculation.
Does this heuristic make sense for mathjs, or should the user of mathjs implement similar heuristics himself?
BTW, see that Math Notepad does what I expected:
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 1
- Comments: 23 (7 by maintainers)
Ok here we go 😃
So far no rounding errors.
When calling
.toString()
, the unit is transformed back to eithermm
orcm
. The heuristics of the current implementation in mathjs will select the prefix of the first unit of the two added units.So in this case
0.011 * 100
introduces a floating point rounding error, whilst0.011 * 1000
doesn’t.All good, my bad. Did not aply the fix in all my code. Works now!