How to increment number by 0.01 in javascript using a loop?

22,774

Solution 1

You are doing this fine. The problem is with the inaccuracy of floating point numbers.

Why are floating point numbers so inaccurate?

If you wish to display this number then use:

heights[i].toFixed(2);

Note that toFixed() returns a string and you will have to convert back to a float (parseFloat()) if you want to perform more numerical operations.

Solution 2

This is just because of how math works in JavaScript, you can find lots of answers explaining about it - like this one. The easiest solution is to just do everything times 100, and then divide when adding to the array e.g.

var heights = [], i, l;
for (i = 120; i < 250; i += 1){    
    heights.push(i / 100);    
}

You could use toFixed but that will give you a String as the result.

Solution 3

This is due to how floating point numbers are stored internally, it's not JavaScript specific. You can use .toFixed() to store a string representation of the number with the desired accuracy, so:

heights.push(i.toFixed(2));

If you want to avoid storing strings and then converting them back into an actual number, you can multiply the step so that it becomes a whole number and then store a division instead:

for (var i = 120; i <= 250; ++i) {
    heights.push(i / 100);
}

The difference besides the fact that you now have numbers is that multiple of 0.1 are represented in single accuracy, e.g. 2.4 instead of "2.40".

Solution 4

This is because machines use base 2, and you are using base 10 numbers that cannot be accurately represented in base 2 with a floating point number.

You can use this library to format it: https://github.com/dtrebbien/BigDecimal.js

Solution 5

As it has been mentioned, toFixed() returns String, and parseFloat() converts String to Float. parseFloat() also removes trailing zeros, which makes sense, but was not working for my use case.

Here is an example of iteration using Float and retaining trailing zeroes.

var i = 0.9,
  floats = [];

while (i < 2) {
  i = (i + 0.1).toFixed(1);
  floats.push(i);
  i = parseFloat(i);
}
console.log(floats);


[ '1.0',
  '1.1',
  '1.2',
  '1.3',
  '1.4',
  '1.5',
  '1.6',
  '1.7',
  '1.8',
  '1.9',
  '2.0' ]

If trailing zeroes are not needed, the loop can be simplified as:

while (i < 2) {
  floats.push(i);
  i = parseFloat((i + 0.1).toFixed(1));
}
Share:
22,774
hitautodestruct
Author by

hitautodestruct

I'm a freelance front end developer. Mainly interested in the HTML/CSS/JS stack and related technologies. I also dabble in NodeJS, PHP, MySQL, VueJS, AngularJS and other technologies that help with building web related stuff.

Updated on September 01, 2021

Comments

  • hitautodestruct
    hitautodestruct over 2 years

    Problem

    I was trying to build out a list of heights in the console by meteres starting from 1.20m and ending up at 2.50m.

    I used this code:

    var heights = [];
    for ( var i=1.20, l=2.5; i<l; i+=0.01 ){
    
        heights.push(i);
    
    }
    
    heights = heights.join('\n');
    

    If I console.log( heights ) I get:

    1.2
    1.21
    1.22
    1.23
    ...
    

    But then at 1.37 I start getting:

    1.37
    1.3800000000000001
    1.3900000000000001
    1.4000000000000001
    1.4100000000000001
    1.4200000000000002
    1.4300000000000002
    

    Questions

    • What's going on?
    • How do I fix it?

    Demo

    var heights = [];
    for ( var i=1.20, l=2.5; i<l; i+=0.01 ){
    
        heights.push(i);
    
    }
    
    var heights = heights.join('\n');
    
    document.querySelector('#output').innerText = heights;
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset=utf-8 />
    <title>JS Bin</title>
    </head>
    <body>
      <div id="output"></div>
    </body>
    </html>