我正在尝试将小数截断到指定的位数。类似这样:
5.467 -> 5.46
985.943 -> 985.94
toFixed(2)
可以实现四舍五入,但我不需要进行四舍五入。希望在JavaScript中有这种可能。
我正在尝试将小数截断到指定的位数。类似这样:
5.467 -> 5.46
985.943 -> 985.94
toFixed(2)
可以实现四舍五入,但我不需要进行四舍五入。希望在JavaScript中有这种可能。
狗伯特的回答不错,但是如果你的代码可能涉及负数,Math.floor
本身可能会产生意外的结果。
例如,Math.floor(4.3) = 4
,但是Math.floor(-4.3) = -5
使用这个辅助函数来获取一致的结果:
truncateDecimals = function (number) {
return Math[number < 0 ? 'ceil' : 'floor'](number);
};
// Applied to Dogbert's answer:
var a = 5.467;
var truncated = truncateDecimals(a * 100) / 100; // = 5.46
这是一个更方便的函数版本:
truncateDecimals = function (number, digits) {
var multiplier = Math.pow(10, digits),
adjustedNum = number * multiplier,
truncatedNum = Math[adjustedNum < 0 ? 'ceil' : 'floor'](adjustedNum);
return truncatedNum / multiplier;
};
// Usage:
var a = 5.467;
var truncated = truncateDecimals(a, 2); // = 5.46
// Negative digits:
var b = 4235.24;
var truncated = truncateDecimals(b, -2); // = 4200
如果不希望这种行为,可以在第一行插入对Math.abs
的调用:
var multiplier = Math.pow(10, Math.abs(digits)),
编辑: shendz 正确指出,使用此解决方案并将 a = 17.56
时会错误地产生 17.55
。想要了解更多原因,请阅读 《计算机科学家应该知道的浮点运算》。不幸的是,用javascript编写消除所有浮点误差的解决方案相当棘手。在另一种语言中,您可以使用整数或 Decimal 类型,但在 JavaScript 中...
这个解决方案应该是100%准确的,但也会更慢:
function truncateDecimals (num, digits) {
var numS = num.toString(),
decPos = numS.indexOf('.'),
substrLength = decPos == -1 ? numS.length : 1 + decPos + digits,
trimmedResult = numS.substr(0, substrLength),
finalResult = isNaN(trimmedResult) ? 0 : trimmedResult;
return parseFloat(finalResult);
}
对于那些需要速度但又想避免浮点数错误的人,可以尝试使用BigDecimal.js之类的东西。你可以在这个SO问题中找到其他JavaScript BigDecimal库:“有没有一个好的JavaScript BigDecimal库?”这里有一篇关于JavaScript数学库的好博客文章
if(isNAN(result)) result = 0;
这取决于你所需要的行为。 - Jeremy WitmerdecPos
是否为 -1 可以解决这个问题。像这样:result = decPos === -1 ? num : numS.substr(0, 1 + decPos + digits);
- Hari Pachuveetil更新:
所以,最后发现,无论你如何努力弥补它们,四舍五入的错误总会困扰着你。因此,该问题应该通过在十进制符号中精确表示数字来解决。
Number.prototype.toFixedDown = function(digits) {
var re = new RegExp("(\\d+\\.\\d{" + digits + "})(\\d)"),
m = this.toString().match(re);
return m ? parseFloat(m[1]) : this.valueOf();
};
[ 5.467.toFixedDown(2),
985.943.toFixedDown(2),
17.56.toFixedDown(2),
(0).toFixedDown(1),
1.11.toFixedDown(1) + 22];
// [5.46, 985.94, 17.56, 0, 23.1]
旧的、基于编译他人代码的容易出错的解决方案:
Number.prototype.toFixedDown = function(digits) {
var n = this - Math.pow(10, -digits)/2;
n += n / Math.pow(2, 53); // added 1360765523: 17.56.toFixedDown(2) === "17.56"
return n.toFixed(digits);
}
1.11.toFixedDown(1) + 22
的结果为 1.122
而不是 23.1
。另外 0.toFixedDown(1)
应该产生 0
,但实际上它产生了 -0.1
。 - Nick Knowlson(-10.2131).toFixedDown(2) // ==> 10.21
。 - rgajrawala(1e-7).toFixedDown(0) // ==> 1e-7
。对于 1e-(>=7)
(例如:1e-8
、1e-9
等),也是这样处理的。 - rgajrawalavar a = 5.467;
var truncated = Math.floor(a * 100) / 100; // = 5.46
truncate(-3.14)
并收到 -4
的返回值,我肯定会认为这是不可取的。 - Nick Knowlsonvar a = 65.1
var truncated = Math.floor(a * 100) / 100; // = 65.09
- Sanyam Jain您可以通过减去0.5来修正toFixed的四舍五入,例如:
(f - 0.005).toFixed(2)
简洁的一行解决方案:
function truncate (num, places) {
return Math.trunc(num * Math.pow(10, places)) / Math.pow(10, places);
}
然后使用以下方式调用:
truncate(3.5636232, 2); // returns 3.56
truncate(5.4332312, 3); // returns 5.433
truncate(25.463214, 4); // returns 25.4632
考虑利用双波浪号:~~
。
取数字。将小数点后的有效数字乘以一个倍数,这样你就可以使用~~
截断到零位。然后再除以该倍数。获利。
function truncator(numToTruncate, intDecimalPlaces) {
var numPower = Math.pow(10, intDecimalPlaces); // "numPowerConverter" might be better
return ~~(numToTruncate * numPower)/numPower;
}
我试图避免将~~
调用包含在括号中; 我相信操作顺序应该可以正确地工作。
alert(truncator(5.1231231, 1)); // 是5.1
alert(truncator(-5.73, 1)); // 是-5.7
alert(truncator(-5.73, 0)); // 是-5
编辑:回顾一下,我无意中还处理了小数点左侧的四舍五入。
alert(truncator(4343.123, -2)); // 得到4300。
这种用法的逻辑看起来有点奇怪,可能会受益于快速重构。但它仍然有效。比好运气更好。
Math
原型并在执行之前检查NaN,它将是完美的。 - Liglo Apptruncator((10 * 2.9) / 100, 2)
返回的结果是0.28而不是0.29... https://jsfiddle.net/25tgrzq1/ - Alex100012345678
比2147483647
要大得多。如果您确实有超过32位的数字(更确切地说,如果您需要那么多有效数字),那么这不是您要寻找的答案。对于可能只需要4-5个有效数字的快速且简单的答案,可以使用此方法。对于可能过度完美的解决方案,请尝试接受的答案。;^D - ruffin我想使用|
来回答问题,因为它既简单又有效。
truncate = function(number, places) {
var shift = Math.pow(10, places);
return ((number * shift) | 0) / shift;
};
~~
答案相同的操作,但只需进行一次位运算。尽管它也有与写入相同的限制:我们不能超过2 ^ 31。 - ruffintruncate((10 * 2.9) / 100);
时,返回的结果是0.28而不是0.29。https://jsfiddle.net/9pf0732d/ - Alex使用位运算符进行截断:
~~0.5 === 0
~~(-0.5) === 0
~~14.32794823 === 14
~~(-439.93) === -439
@Dogbert的回答可以通过Math.trunc
进行改进,它会截断而不是四舍五入。
舍入和截断是有区别的。显然,这个问题所寻求的是截断行为。如果我调用truncate(-3.14)并收到-4的返回值,我肯定会认为这是不可取的。 - @NickKnowlson
var a = 5.467;
var truncated = Math.trunc(a * 100) / 100; // = 5.46
var a = -5.467;
var truncated = Math.trunc(a * 100) / 100; // = -5.46
Math.trunc
的问题,而是9.28 * 100
得到的结果是927.9999
而不是928
。你可能需要阅读一下《浮点数的危险》(The Perils of Floating Point)的内容。 - zurfyx我用一种更简短的方法写了一个答案。以下是我得到的结果:
function truncate(value, precision) {
var step = Math.pow(10, precision || 0);
var temp = Math.trunc(step * value);
return temp / step;
}
truncate(132456.25456789, 5)); // Output: 132456.25456
truncate(132456.25456789, 3)); // Output: 132456.254
truncate(132456.25456789, 1)); // Output: 132456.2
truncate(132456.25456789)); // Output: 132456
function truncate(v, p) {
var s = Math.pow(10, p || 0);
return Math.trunc(s * v) / s;
}