This one is weird, because I got it running in this fiddle but it is not working in the main fiddle. I believe the code is the same.
Here is the main function:
window.setInterval(function(){
for(var i=0; i < companies.length; i++) {
var randomVal = (Math.random()*(10 - (-10) + 1)) + (-10);
randomVal = randomVal / 100;
randomVal = Number(randomVal.toFixed(2));
companies[i].price += randomVal;
//companies[i].price = companies[i].price.toFixed(2);
$('#price'+i).html(companies[i].price);
}
}, 1000);
A value like 34.569999999999986
isnt been cut down to 34.56
.
Any idea what is wrong?
This one is weird, because I got it running in this fiddle but it is not working in the main fiddle. I believe the code is the same.
Here is the main function:
window.setInterval(function(){
for(var i=0; i < companies.length; i++) {
var randomVal = (Math.random()*(10 - (-10) + 1)) + (-10);
randomVal = randomVal / 100;
randomVal = Number(randomVal.toFixed(2));
companies[i].price += randomVal;
//companies[i].price = companies[i].price.toFixed(2);
$('#price'+i).html(companies[i].price);
}
}, 1000);
A value like 34.569999999999986
isnt been cut down to 34.56
.
Any idea what is wrong?
5 Answers
Reset to default 13This has to do with a common problem that occurs when converting between binary floating point values and decimal representations. See this fiddle, which is like your "working" one, but I altered the price
value so that it also breaks.
Here's an even simpler demo that gets right to the heart of the problem: http://jsfiddle.net/2NHSM/4/
As you can see, the output of 1.23 - 1
is 0.22999999999999998
. That's obviously off by a little bit, but it has to do with the way computers represent numbers.
Computers hold numbers as binary digits. 1.23
is actually a "repeating decimal" in binary (just like 1/7 is repeating in decimal), so there's no 100% accurate way to store it. As a result, when you subtract 1.23 - 1
you get an answer that is slightly off because 1.23
was never accurate to begin with.
The same thing is happening in your case. To fix it, just use toFixed
right before you display the value, not before you add something else to it.
Update
Here's a working fiddle: http://jsfiddle.net/2NHSM/6/
Update 2
Also note that toFixed
can have unexpected rounding behavior. Try the following in the console:
1.35.toFixed(1);
// => 1.4
1.45.toFixed(1);
// => 1.4
You might want to use Math.round
instead.
Math.round(1.35 * 10) / 10
// => 1.4
Math.round(1.45 * 10) / 10
// => 1.5
Floating points are approximations so when you add, they don't always end up clean numbers. Just call toFixed when you display it:
companies[i].price += randomVal;
$('#price'+i).html(companies[i].price.toFixed(2));
Demo
This is why your //companies[i].price = companies[i].price.toFixed(2);
didn't work:
toFixed()
returns a string, so after the first call, companies[i].price
is a string. When you do companies[i].price += randomVal;
, it is doing string concatenation instead of numeric addition. It'll produce something like:
577.05
577.050.05
577.050.050.1
So you can't call toFixed on it anymore because:
- It's a string
- It's not even a valid number
So, how would you fix that? Convert it to a number by multiplying by 1 (or Number()
);
companies[i].price += randomVal;
companies[i].price = companies[i].price.toFixed(2)*1;
$('#price'+i).html(companies[i].price);
Demo
With either of these solutions, the first call to toFixed()
is unnecessary.
That's because after applying .toFixed()
you're adding the value to another variable, which then causes the precision to go haywire again.
Instead use this for displaying:
$('#price'+i).html(companies[i].price.toFixed(2));
The reason it works in your first example is because you are resetting the value of price to 577 on each pass.
Try this, it calls .toFixed(2) on the price after the sum has been calculated and also returns it back to your variable.
You can probably ditch the first .toFixed thats called on randomVal.
window.setInterval(function(){
for(var i=0; i < companies.length; i++) {
var randomVal = (Math.random()*(10 - (-10) + 1)) + (-10);
randomVal = randomVal / 100;
randomVal = Number(randomVal.toFixed(2));
companies[i].price += randomVal;
companies[i].price = Number(companies[i].price.toFixed(2));
$('#price'+i).html(companies[i].price);
}
}, 1000);
your conversion data is response[25] and follow the below steps.
var i = parseFloat(response[25]).toFixed(2)
console.log(i)//-6527.34