1

I'm making a math library because 0.1 + 0.2 DOES NOT = 0.30000000000004. But I ran into a really weird problem

I have an array:

var array = [1,2,3,".",4,5,6];

I want to split it into two parts so I...

var part1 = array;
var part2 = array;

And then...

for (var i = 4; i < 7; i++) {
  part1[i] = 0;
};

So now part1 =

[1,2,3,".",0,0,0]

As it should but then I arrive at this problem. After I...

for (i = 2; i > -1; i--) {
  part2[i] = 0;
};

Part1, part2 and array now =

[0,0,0,".",0,0,0]

This shouldn't happen, part2 should =

[0,0,0,".",4,5,6]

But it doesn't

???

Indiana Kernick
  • 5,041
  • 2
  • 20
  • 50
  • 2
    you only copy the reference to the array. You can copy the array in a new variable with `var newAr = array.slice(0)` – devqon Dec 24 '14 at 11:58

3 Answers3

2

This happens because both part1 and part2 (and obviously array too) variables are pointing to the same memory address, which stores the same information, therefore if you edit any of the three arrays the changes will be visible in all of them, because you're modifying the same value represented by three different variables.

To avoid this you should "copy" the array using slice() or something else, like a for loop, but slice is my favourite method, and also the fastest to type, so your code will become:

var part1 = array.slice();
var part2 = array.slice();

Now you can do whatever you want and the arrays will be treated as different variables.

Quick example:

a = [1,2]
> [1, 2]
b = a.slice()
> [1, 2]
b[0] = 2
2
b
> [2, 2]
a
> [1, 2]

Fastest method to copy an array:

If you're looking for the fastet method (since that there are several different methods to copy an array) then you should check this benchmark test, and run a test. The best solution isn't always the same one, so in the future it may change, depending on the JS implementation and your current browser version, although slice(), slice(0) and concat() are usually way faster than other methods.

Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
1

You have to copy the array:

var part1 = array.concat();// it is possible to use array.slice() too.
var part2 = array.concat();

If not, you are always modifying the same object, since part1 and part2 will have a reference to the array variable.

On the other hand, I would not recomend you to build your own math library just to resolve floating point issues in JS. Have you read similar questions?

Community
  • 1
  • 1
rvignacio
  • 1,710
  • 1
  • 18
  • 33
  • The real reason I wanted to do it is because I wanted to prove to myself that a can do it and I'm making a scientific calculator chrome app and I didn't want to use someone else's code to make it accurate. – Indiana Kernick Dec 24 '14 at 13:20
  • @Kerndog73, that's a good reason, just be aware that the results might not be always what you expect :) and using the standard Math.round() function could be better (in a production environment) than using arrays and positions. – rvignacio Dec 24 '14 at 13:31
0

What is going wrong in your code is that you don't create a clone of the array: array, part1, and part2 all point to the very same array. You can create a copy like part1 = array.slice(0).

Instead of writing your own math library to solve floating point round-off errors, you can use for example BigNumbers in math.js:

// configure math.js to use BigNumbers by default
math.config({
  number: 'bignumber', // Default type of number: 'number' (default) or 'bignumber'
  precision: 64        // Number of significant digits for BigNumbers
});

// evaluate an expression
math.eval('0.1 + 0.2'); // BigNumber, 0.3

See docs on BigNumbers: http://mathjs.org/docs/datatypes/bignumbers.html

Jos de Jong
  • 6,602
  • 3
  • 38
  • 58
  • I was going to but that library needs `eval()` to work so I didn't. `math.add(0.1, 0.2) == 0.1 + 0.2` but `math.eval('0.1 + 0.2') == 0.3` – Indiana Kernick Feb 18 '15 at 02:37
  • I'm not sure what you mean. You don't have to use `eval()`, you can also create bignumbers explicitly and call add, like `math.add(math.bignumber(0.1), math.bignumber(0.2))` – Jos de Jong Feb 18 '15 at 11:33
  • OMG really? I didn't know about that method! MathJS looks like the perfect version of my math library. It works the same way. I might as use that then. – Indiana Kernick Feb 18 '15 at 11:36