Javascript 中的负数四舍五入
Rounding of negative numbers in Javascript
我们在 JavaScript 中遇到了 Math.round() 的问题。问题是此函数不能正确舍入负数。例如:
1.5 ~= 2
0.5 ~= 1
-0.5 ~= 0 // 错误
-1.5 ~= -1 // 错误
根据算术舍入,这是不正确的。 -0.5 的正确数字应该是 -1,-1.5 应该是 -2。
是否有任何标准方法可以正确舍入 Javascript 中的负数?
应用Math.round
after converting to a positive number and finally roll back the sign. Where you can use Math.sign
method to get the sign from the number and Math.abs
得到数字的绝对值。
console.log(
Math.sign(num) * Math.round(Math.sign(num) * num),
// or
Math.sign(num) * Math.round(Math.abs(num))
)
var nums = [-0.5, 1.5, 3, 3.6, -4.8, -1.3];
nums.forEach(function(num) {
console.log(
Math.sign(num) * Math.round(Math.sign(num) * num),
Math.sign(num) * Math.round(Math.abs(num))
)
});
您可以保存标志并稍后在 ES5 中应用;
function round(v) {
return (v >= 0 || -1) * Math.round(Math.abs(v));
}
console.log(round(1.5)); // 2
console.log(round(0.5)); // 1
console.log(round(-1.5)); // -2
console.log(round(-0.5)); // -1
var r = (Math.random() * 200) - 100;
在不使用数学库的情况下纯粹评估结果如何?例如,通过使用三元运算符,您可以优雅地检查负数,然后在 "rounding":
之后进行 floor
var n = r + (r < 0 ? -0.5 : 0.5) | 0;
| 0
只是 js 中的一个愚蠢的把戏 "overloads" 二元运算符(您可以使用任何二元运算符)以截断数字。
注意 这不是地板(像 Math.floor
),因为 Math.floor(-3.2)
,例如,实际上会产生 -4
。
甚至可以做类似于@Balan 的回答的事情(我喜欢那个和下面的那个,但我觉得这个或三元运算符会更快一点——不过我可能错了,因为Math
库已被证明非常快):
var n = (r + Math.sign(r) / 2) | 0;
可能是最快、最优雅的方式:
var n = Math.floor(r + 0.5);
示例:
var body = document.getElementById("myTable").children[1];
var i, iMax = 100, r, tr, td;
for (i = 0; i < iMax; i++) {
r = Math.random() * 200 - 100;
tr = document.createElement("tr");
td = document.createElement("td");
td.innerHTML = r;
tr.appendChild(td);
td = document.createElement("td");
td.innerHTML = (r + Math.sign(r) / 2) | 0;
tr.appendChild(td);
body.appendChild(tr);
}
#myTable {
min-width: 250px;
}
<table id="myTable">
<thead>
<tr>
<th>float</th>
<th>round</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
您可以尝试使用 Math.ceil(number) 对数字进行舍入,然后 - 如果 num 为负则为 1,例如
if (num < 0) {
num = Math.ceil(num) - 1;
} else {
num = Math.ceil(num);
}
精确舍入。
默认情况下舍入为 Int,或者如果提供了第二个参数,则舍入到小数点后的 n 位数字。
+“1”修复了 .0X5 数字的不正确舍入。
function round(num, digits=0) {
if (!(num % 1)) return num
return +Number(num + '1').toFixed(digits)
}
首先观察Math.round(v)
定义为Math.floor(v + 0.5)
:
Math.round(-1.7) === -2
Math.round(-1.3) === -1
Math.floor(-1.7 + 0.5) === -2
Math.floor(-1.3 + 0.5) === -1
然后意识到 parseInt(v)
类似于 Math.floor(v)
,但是,它处理负数的方式不同(正是您所期望的):
Math.floor(1.7) === 1
Math.floor(-1.7) === -2
parseInt(1.7) === 1
parseInt(-1.7) === -1
所以 parseInt(v)
行为是您想要的,但您想要舍入而不是地板。为了将其应用于任何数字,我们需要为正数添加 +0.5
,为负数添加 -0.5
。所以解决方案就是这个函数:
var parseIntRound = function(v)
{
return parseInt(v + Math.sign(v)/2);
};
// or with modern syntactic sugar:
// const parseIntRound = v => parseInt(v + Math.sign(v)/2);
parseIntRound( 1.5) === 2
parseIntRound( 0.5) === 1
parseIntRound(-0.5) === -1
parseIntRound(-1.3) === -1
parseIntRound(-1.5) === -2
parseIntRound(-1.7) === -2
其中 Math.sign(v)
returns 1 表示任何正数 (>0),-1 表示任何负数 (<0),0 表示正零(-0 表示负零) .
ES6 添加了一个名为 Math.trunc 的方法,使用它我们可以得到小数的整数部分
The Math.trunc() function returns the integer part of a number by
removing any fractional digits.
Math.trunc(42.84) -> Returns 42
Math.trunc(5.3) -> Returns 5
Math.trunc(-4.3) -> Returns -4
Math.trunc(-3.123) -> Returns -3
我们在 JavaScript 中遇到了 Math.round() 的问题。问题是此函数不能正确舍入负数。例如:
1.5 ~= 2
0.5 ~= 1
-0.5 ~= 0 // 错误
-1.5 ~= -1 // 错误
根据算术舍入,这是不正确的。 -0.5 的正确数字应该是 -1,-1.5 应该是 -2。
是否有任何标准方法可以正确舍入 Javascript 中的负数?
应用Math.round
after converting to a positive number and finally roll back the sign. Where you can use Math.sign
method to get the sign from the number and Math.abs
得到数字的绝对值。
console.log(
Math.sign(num) * Math.round(Math.sign(num) * num),
// or
Math.sign(num) * Math.round(Math.abs(num))
)
var nums = [-0.5, 1.5, 3, 3.6, -4.8, -1.3];
nums.forEach(function(num) {
console.log(
Math.sign(num) * Math.round(Math.sign(num) * num),
Math.sign(num) * Math.round(Math.abs(num))
)
});
您可以保存标志并稍后在 ES5 中应用;
function round(v) {
return (v >= 0 || -1) * Math.round(Math.abs(v));
}
console.log(round(1.5)); // 2
console.log(round(0.5)); // 1
console.log(round(-1.5)); // -2
console.log(round(-0.5)); // -1
var r = (Math.random() * 200) - 100;
在不使用数学库的情况下纯粹评估结果如何?例如,通过使用三元运算符,您可以优雅地检查负数,然后在 "rounding":
之后进行 floorvar n = r + (r < 0 ? -0.5 : 0.5) | 0;
| 0
只是 js 中的一个愚蠢的把戏 "overloads" 二元运算符(您可以使用任何二元运算符)以截断数字。
注意 这不是地板(像 Math.floor
),因为 Math.floor(-3.2)
,例如,实际上会产生 -4
。
甚至可以做类似于@Balan 的回答的事情(我喜欢那个和下面的那个,但我觉得这个或三元运算符会更快一点——不过我可能错了,因为Math
库已被证明非常快):
var n = (r + Math.sign(r) / 2) | 0;
可能是最快、最优雅的方式:
var n = Math.floor(r + 0.5);
示例:
var body = document.getElementById("myTable").children[1];
var i, iMax = 100, r, tr, td;
for (i = 0; i < iMax; i++) {
r = Math.random() * 200 - 100;
tr = document.createElement("tr");
td = document.createElement("td");
td.innerHTML = r;
tr.appendChild(td);
td = document.createElement("td");
td.innerHTML = (r + Math.sign(r) / 2) | 0;
tr.appendChild(td);
body.appendChild(tr);
}
#myTable {
min-width: 250px;
}
<table id="myTable">
<thead>
<tr>
<th>float</th>
<th>round</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
您可以尝试使用 Math.ceil(number) 对数字进行舍入,然后 - 如果 num 为负则为 1,例如
if (num < 0) {
num = Math.ceil(num) - 1;
} else {
num = Math.ceil(num);
}
精确舍入。
默认情况下舍入为 Int,或者如果提供了第二个参数,则舍入到小数点后的 n 位数字。
+“1”修复了 .0X5 数字的不正确舍入。
function round(num, digits=0) {
if (!(num % 1)) return num
return +Number(num + '1').toFixed(digits)
}
首先观察Math.round(v)
定义为Math.floor(v + 0.5)
:
Math.round(-1.7) === -2
Math.round(-1.3) === -1
Math.floor(-1.7 + 0.5) === -2
Math.floor(-1.3 + 0.5) === -1
然后意识到 parseInt(v)
类似于 Math.floor(v)
,但是,它处理负数的方式不同(正是您所期望的):
Math.floor(1.7) === 1
Math.floor(-1.7) === -2
parseInt(1.7) === 1
parseInt(-1.7) === -1
所以 parseInt(v)
行为是您想要的,但您想要舍入而不是地板。为了将其应用于任何数字,我们需要为正数添加 +0.5
,为负数添加 -0.5
。所以解决方案就是这个函数:
var parseIntRound = function(v)
{
return parseInt(v + Math.sign(v)/2);
};
// or with modern syntactic sugar:
// const parseIntRound = v => parseInt(v + Math.sign(v)/2);
parseIntRound( 1.5) === 2
parseIntRound( 0.5) === 1
parseIntRound(-0.5) === -1
parseIntRound(-1.3) === -1
parseIntRound(-1.5) === -2
parseIntRound(-1.7) === -2
其中 Math.sign(v)
returns 1 表示任何正数 (>0),-1 表示任何负数 (<0),0 表示正零(-0 表示负零) .
ES6 添加了一个名为 Math.trunc 的方法,使用它我们可以得到小数的整数部分
The Math.trunc() function returns the integer part of a number by removing any fractional digits.
Math.trunc(42.84) -> Returns 42
Math.trunc(5.3) -> Returns 5
Math.trunc(-4.3) -> Returns -4
Math.trunc(-3.123) -> Returns -3