# ๐ Change floating-point to 2 decimal places?

Before I go down this rabbit hole further. If you could share your wisdom/experience.

Iโm assuming with certain large floating-point numbers is a known problem and CAN NOT be converted to 2 decimal places. As these large numbers appear to be an error, it is the way things work with my current findings as we discuss below.

## StackOverflow

Tearing through page after page related to big floating-point numbers devs are trying to find ways of converting. Iโd be another duplicate that is why we are discussing on discourse.threejs.org have you come across these big floating-point numbers? What did you do to convert to 2 decimal places?

Dev(s) speak of many ways in trying to do the same thing and yet these numbers refuse to change = typeof number: 0.9299999999999999

Reference: Round to at most 2 decimal places (only if necessary) = none of these worked for my situation

What is really strange is when I convert 0.93 from a string back into 0.93 the computer wants to convert to 0.9299999999999999

``````ry += Number(((parseFloat(rotateY, 10)).toFixed(2)));

ry += Math.round((rotateY * 100 ))/100;
``````

The 2 pieces of code that fit into line 10 are trying to do the same thing, this is more commonly what youโll see devs doing because you need to have an understanding that toFixed(2) will produce a string.

``````ry += Math.round((rotateY * 100 ))/100;
``````

Devs do go on to discuss using:

## Input

``````01 var trigger = setInterval(function() {
02   cnt++;
03
05
06   if (cnt < 4) {
07     var works = (ry + parseFloat(rotateY, 10)).toFixed(2);
08     console.log('WORKING AS STRING:', works);
09     console.log(typeof works);
10     ry += Math.round((rotateY * 100 ).toFixed(2))/100;
11     console.log('FIXED AS NUMBER:', ry);
12     console.log(typeof ry);
13   }
14   if (cnt === 11) {
15     clearInterval(trigger);
16   }
17
18   mesh.rotation.y = ry;
19
20   render();
21
22 }, 1000);
``````

## Output

``````THREE.WebGLRenderer 92

WORKING AS STRING: 0.31
string
FIXED AS NUMBER: 0.31
number
WORKING AS STRING: 0.62
string
FIXED AS NUMBER: 0.62
number
WORKING AS STRING: 0.93
string
FIXED AS NUMBER: 0.9299999999999999
number
``````

In depth talk on Mantissa/Significand:
Everything you never wanted to know about JavaScript numbers

Bartek Szopka: Only says these numbers exist, no fix, quite interesting in knowing what is happening under the hood

Reminds me of a problem I was banging my head against earlier this year:

`(0.1 + 0.2 === 0.3)` is false, so I had to use 2 comparisons as a dirty fix: `x > 2.9 && x < 3.1`

2 Likes

Awesome for this tip, yes I could check if that number kicks in to manually load a rounded floating point.
The ah-ha moment just kicked in! Is it ideal no, for now the condition will get the job done!

I know of the culprit problem as well (0.1 + 0.2 === 0.3) is false
Wondering if we could create a compiled list of these Javascript Gotcha(s) for the community!

Thanks for sharing @marquizzo!

When I was answering this SO question, I bumped into something similar. So I solved it with the conception of โtoleranceโ:

``````THREE.Vector3.prototype.equals = function(v, tolerance) {
if (tolerance === undefined) {
return ((v.x === this.x) && (v.y === this.y) && (v.z === this.z));
} else {
return ((Math.abs(v.x - this.x) < tolerance) && (Math.abs(v.y - this.y) < tolerance) && (Math.abs(v.z - this.z) < tolerance));
}
}
``````
2 Likes

Another great response thanks @prisoner849!

When calculating with floating points, inaccuracies are inevitable which makes comparison operations via `===` not robust. Using a โtoleranceโ or โepsilonโ value like mentioned by @prisoner849 is the right approach. But there is one obvious problem: What value should you use for `tolerance`? You often see hard coded values like `Number.EPSILON` or something like `0.00001`. The problem is that these values might be inappropriate for data sets with very large or very small values. Because of this, you normally scale the `tolerance` value based on all input data you are going to process. For instance the `QuickHull` implementation of `three.js` which computes the convex hull for a given set of points uses this approach.

2 Likes

Another great response thanks @Mugen87!
Have some more playing around to do

It seems like Math.round() is a better solution, but it is not! In some cases it will NOT round correctly. Also, toFixed() will NOT round correctly in some cases.

To correct the rounding problem with the previous Math.round() and toFixed(), you can define a custom JavaScript round function that performs a โnearly equalโ test to determine whether a fractional value is sufficiently close to a midpoint value to be subject to midpoint rounding. The following function return the value of the given number rounded to the nearest integer accurately.

``````Number.prototype.roundTo = function(decimal) {
return +(Math.round(this + "e+" + decimal)  + "e-" + decimal);
}

var num = 9.7654;
console.log( num.roundTo(2)); //output 9.77
``````