🔥

[javascript] "Math.round()" or "Number.prototype.toFixed()"

2024/07/26に公開
• 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}`);
}
...
``````