🔥
[javascript] "Math.round()" or "Number.prototype.toFixed()"
- note: updated at 7/26
I noticed that, when debugging, we shouldn't format the number or string.
I wrote more details in the "Bug Fix" part in this post.
Intro.
When I rounded a negative number by "Math.round()" or "Number.prototype.toFixed()", I noticed a little difference.
"Math.round()" converted -12.5 into -12.0 and -12.6 into -13.0 .
- -12.5 -> -12.0
- -12.6 -> -13.0
"toFixed()" converted -12.4 into -12.0 and -12.5 into -13.0 .
- -12.4 -> -12.0
- -12.5 -> -13.0
I feel that "Math.round()" seems correct mathematically.
List
Here is the list of rounding numbers(12 ~ 13 and -13 ~ -12)
- using "Math.round()"
positive number | negative number |
---|---|
Math.round() before: 13 => after: 13 | Math.round() before: -12 => after: -12 |
Math.round() before: 12.9 => after: 13 | Math.round() before: -12.1 => after: -12 |
Math.round() before: 12.8 => after: 13 | Math.round() before: -12.2 => after: -12 |
Math.round() before: 12.7 => after: 13 | Math.round() before: -12.3 => after: -12 |
Math.round() before: 12.6 => after: 13 | Math.round() before: -12.4 => after: -12 |
Math.round() before: 12.5 => after: 13 | Math.round() before: -12.5 => after: -12 |
Math.round() before: 12.4 => after: 12 | Math.round() before: -12.6 => after: -13 |
Math.round() before: 12.3 => after: 12 | Math.round() before: -12.7 => after: -13 |
Math.round() before: 12.2 => after: 12 | Math.round() before: -12.8 => after: -13 |
Math.round() before: 12.1 => after: 12 | Math.round() before: -12.9 => after: -13 |
Math.round() before: 12 => after: 12 | Math.round() before: -13 => after: -13 |
- using ".toFixed()"
positive number | negative number |
---|---|
.toFixed() before: 13 => after: 13 | .toFixed() before: -12 => after: -12 |
.toFixed() before: 12.9 => after: 13 | .toFixed() before: -12.1 => after: -12 |
.toFixed() before: 12.8 => after: 13 | .toFixed() before: -12.2 => after: -12 |
.toFixed() before: 12.7 => after: 13 | .toFixed() before: -12.3 => after: -12 |
.toFixed() before: 12.6 => after: 13 | .toFixed() before: -12.4 => after: -12 |
.toFixed() before: 12.5 => after: 13 | .toFixed() before: -12.5 => after: -13 |
.toFixed() before: 12.4 => after: 12 | .toFixed() before: -12.6 => after: -13 |
.toFixed() before: 12.3 => after: 12 | .toFixed() before: -12.7 => after: -13 |
.toFixed() before: 12.2 => after: 12 | .toFixed() before: -12.8 => after: -13 |
.toFixed() before: 12.1 => after: 12 | .toFixed() before: -12.9 => after: -13 |
.toFixed() before: 12 => after: 12 | .toFixed() before: -13 => after: -13 |
Code
Here is the code that I used to create the List of rounding numbers.
type ChangeFunction = (n: number) => number;
const calcNum = (tag: string, num: number, func: ChangeFunction) => {
const afterNum = func(num);
console.log(`${tag} before: ${num} => after: ${afterNum}`);
// I noticed that, when debugging, we shouldn't format the number or string.
// const beforeVal = new Intl.NumberFormat('ja-JP', { style: 'decimal', 'minimumFractionDigits': 1} ).format(num);
// const afterVal = new Intl.NumberFormat('ja-JP', { style: 'decimal', 'minimumFractionDigits': 1} ).format(afterNum);
// console.log(`${tag} before: ${beforeVal} => after: ${afterVal}`);
}
for (let i=0; i < 11;i++) {
calcNum('Math.round()', 13 - i * 0.1, (n: number) => {return Math.round(n)})
}
for (let i=0; i < 11;i++) {
calcNum('Math.round()', -12 - i * 0.1, (n: number) => {return Math.round(n)})
}
for (let i=0; i < 11;i++) {
calcNum('.toFixed()', 13 - i * 0.1, (n: number) => {return parseFloat((n).toFixed(0))})
}
for (let i=0; i < 11;i++) {
calcNum('.toFixed()', -12 - i * 0.1, (n: number) => {return parseFloat((n).toFixed(0))})
}
Bug Fix
I found this.
When we calculate "6.4 - 5 * 0.01", we get "6.3500000000000005".
console.log(`calc: ${6.4 - 5 * 0.01}`);
// -> calc: 6.3500000000000005
Here is another example.
for (let i=0; i < 11;i++) {
let val = 6.4 - i * 0.01;
console.log(`(test) val: ${val}`);
}
// Result
(test) val: 6.4
(test) val: 6.390000000000001
(test) val: 6.380000000000001
(test) val: 6.37
(test) val: 6.36
(test) val: 6.3500000000000005
(test) val: 6.340000000000001
(test) val: 6.33
(test) val: 6.32
(test) val: 6.3100000000000005
(test) val: 6.300000000000001
So I noticed that, when debugging, we shouldn't format the number or string.
Then I changed my code to remove the formatting by "Intl.NumberFormat", so that we could detect the real number.
...
const calcNum = (tag: string, num: number, func: ChangeFunction) => {
const afterNum = func(num);
console.log(`${tag} before: ${num} => after: ${afterNum}`);
// I noticed that, when debugging, we shouldn't format the number or string.
// const beforeVal = new Intl.NumberFormat('ja-JP', { style: 'decimal', 'minimumFractionDigits': 1} ).format(num);
// const afterVal = new Intl.NumberFormat('ja-JP', { style: 'decimal', 'minimumFractionDigits': 1} ).format(afterNum);
// console.log(`${tag} before: ${beforeVal} => after: ${afterVal}`);
}
...
Discussion