2999999 + 1
3e+6 // => no error, as expected
2999999 g + 1 g
3 Mg [[round-off error]]
This result contains a round-off error which is hidden from the output. The unrounded result is:
3.0000000000000004 Mg
Why is this happening? How do we prevent such errors when making unit calculation?
These are... drum roll... round-off errors due to floating point calculations. You've asked a couple of questions in this regard last days, just look up the links to the documentation that I posted here and there for more information.
When using the expression parser, you can configure mathjs to use BigNumber or Fraction instead of number: Units do support all three numeric types. Or you can round the output to a limited precision using the math.format function to hide the round-off errors.
var math = require('mathjs');
math.config({number: 'BigNumber'});
console.log(math.multiply(4.523901, 10000000));
Output: 45239010.00000001
What am I doing wrong? I'm honestly losing my damn mind with this, its been 2 days and I still don't know how to work with big numbers in NodeJS. In PHP I just use the bcmath library and it's done.
Sorry for the confusion here @DanVeira . Unfortunately, the {number: 'BigNumber'} setting only applies to numbers created using the expression parser (see docs). mathjs does not change the type of inputs passed to individual functions.
See related discussion here: https://github.com/josdejong/mathjs/issues/864
@josdejong What would you do in my case? I receive decimal numbers up to 8 decimal places from a websocket and I need to work with them. It needs to be seriously fast too.
I'm at a point where I'm thinking of giving up on NodeJS and use something else because it's pathetic that I can't even get basic arithmetic operations to work.
Thank you.
@DanVeira you sound frustrated, keep breathing ;)
What sort of operations do you need to do?
If you just need to do some basic operations with bignumbers, you could simply us decimal.js directly, this library is used by mathjs under the hood. If you need dynamic expression parsing with bignumbers or need specific functions available in math.js, well, then math.js may be a good choice.
o, and if you need fast performance it will make a lot of difference if you could simply use regular numbers instead of BigNumbers. Calculations with BigNumbers are way slower than with simple numbers. But well that depends on your use case.
These are... drum roll... round-off errors due to floating point calculations.
The problem I mentioned is, the number part should stay intact whether you use units or not. For example, if:
math.eval('10 / 3'); // 5.888 (it's wrong, of course, but OK, I'll accept it)
I would expect:
math.eval('10 g / 3 g'); // 5.888 g
My point is, the problem here is not about the results (the number part), it's about inconsistencies between a simple calculation and a calculation with unit.
The problem here is ... inconsistencies between a simple calculation and a calculation with unit.
@ceremcem, math.js performs more calculations than are immediately apparent when handling units. In your first example at the top of this thread, 2999999 + 1 is evaluated using integer arithmetic which gives an exact answer. With 2999999 g + 1 g, however, math.js first converts each unit to an SI basis, kg, before evaluating. So internally, the actual calculation is performed like this:
2999999 g to 2999.999 kg1 g to 0.001 kg2999.999 + 0.001MgThe actual arithmetic performed is this:
(2999999 * 0.001 + 1 * 0.001) / 1000
If you type the above expression into your javascript console, you'll get 3.0000000000000004. Anything with a decimal point uses floating point arithmetic, which is not exact. That's why you get the round off error with units and not with normal integers.
That was a great explanation.
So I assume we have to use (and carry between operations) 2 distinct outputs: Result's human readable string and the actual result (the fraction); like this one: http://jsbin.com/heyegezezo/1/edit?html,output