Javascript 在javascript中截断(不四舍五入)十进制数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4912788/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Truncate (not round off) decimal numbers in javascript
提问by kcssm
I am trying to truncate decimal numbers to decimal places. Something like this:
我正在尝试将十进制数截断为小数位。像这样的东西:
5.467 -> 5.46
985.943 -> 985.94
toFixed(2)
does just about the right thing but it rounds off the value. I don't need the value rounded off. Hope this is possible in javascript.
toFixed(2)
做了几乎正确的事情,但它使价值四舍五入。我不需要四舍五入的值。希望这在javascript中是可能的。
采纳答案by kirilloid
upd:
更新:
So, after all it turned out, rounding bugs will always haunt you, no matter how hard you try to compensate them. Hence the problem should be attacked by representing numbers exactly in decimal notation.
所以,毕竟事实证明,舍入错误总是困扰着你,无论你如何努力补偿它们。因此,应该通过精确地用十进制表示法来表示数字来解决这个问题。
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]
Old error-prone solution based on compilation of others':
基于其他人的编译的旧的容易出错的解决方案:
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);
}
回答by Nick Knowlson
Dogbert's answer is good, but if your code might have to deal with negative numbers, Math.floor
by itself may give unexpected results.
Dogbert 的回答很好,但如果您的代码可能必须处理负数,则Math.floor
其本身可能会产生意想不到的结果。
E.g. Math.floor(4.3) = 4
, but Math.floor(-4.3) = -5
例如Math.floor(4.3) = 4
,但是Math.floor(-4.3) = -5
Use a helper function like this one instead to get consistent results:
使用类似这样的辅助函数来获得一致的结果:
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
Here's a more convenient version of this function:
这是这个函数的一个更方便的版本:
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
If that isn't desired behaviour, insert a call to Math.abs
on the first line:
如果这不是我们想要的行为,请Math.abs
在第一行插入一个调用:
var multiplier = Math.pow(10, Math.abs(digits)),
EDIT:shendz correctly points out that using this solution with a = 17.56
will incorrectly produce 17.55
. For more about why this happens, read What Every Computer Scientist Should Know About Floating-Point Arithmetic. Unfortunately, writing a solution that eliminates all sources of floating-point error is pretty tricky with javascript. In another language you'd use integers or maybe a Decimal type, but with javascript...
编辑:shendz 正确地指出,使用此解决方案 witha = 17.56
将错误地生成17.55
. 有关为什么会发生这种情况的更多信息,请阅读每个计算机科学家应该知道的关于浮点运算的知识。不幸的是,使用 javascript 编写一个消除所有浮点错误来源的解决方案非常棘手。在另一种语言中,您将使用整数或十进制类型,但使用 javascript ......
This solution should be100% accurate, but it will also be slower:
这个解决方案应该是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);
}
For those who need speed but also want to avoid floating-point errors, try something like BigDecimal.js. You can find other javascript BigDecimal libraries in this SO question: "Is there a good Javascript BigDecimal library?"and here's a good blog post about math libraries for Javascript
对于那些需要速度但又想避免浮点错误的人,可以试试BigDecimal.js 之类的东西。您可以在这个问题中找到其他 javascript BigDecimal 库:“是否有一个好的 Javascript BigDecimal 库?” 这是一篇关于Javascript 数学库的好博文
回答by Dogbert
var a = 5.467;
var truncated = Math.floor(a * 100) / 100; // = 5.46
回答by RichardTheKiwi
You can fix the rounding by subtracting 0.5 for toFixed, e.g.
您可以通过为 toFixed 减去 0.5 来修复舍入,例如
(f - 0.005).toFixed(2)
回答by ruffin
Consider taking advantage of the double tilde: ~~
.
考虑利用双波浪线:~~
。
Take in the number. Multiply by significant digits after the decimal so that you can truncateto zero places with ~~
. Divide that multiplier back out. Profit.
取号。乘以小数点后的有效数字,以便您可以使用截断到零位~~
。将该乘数除掉。利润。
function truncator(numToTruncate, intDecimalPlaces) {
var numPower = Math.pow(10, intDecimalPlaces); // "numPowerConverter" might be better
return ~~(numToTruncate * numPower)/numPower;
}
I'm trying to resist wrapping the ~~
call in parens; order of operations should make that work correctly, I believe.
我试图抵制~~
用括号包装调用;我相信,操作顺序应该使其正常工作。
alert(truncator(5.1231231, 1)); // is 5.1
alert(truncator(5.1231231, 1)); // is 5.1
alert(truncator(-5.73, 1)); // is -5.7
alert(truncator(-5.73, 1)); // is -5.7
alert(truncator(-5.73, 0)); // is -5
alert(truncator(-5.73, 0)); // is -5
EDIT:Looking back over, I've unintentionally also handled cases to round off left of the decimal as well.
编辑:回顾过去,我无意中也处理了小数点左边四舍五入的情况。
alert(truncator(4343.123, -2)); // gives 4300.
alert(truncator(4343.123, -2)); // gives 4300.
The logic's a little wacky looking for that usage, and may benefit from a quick refactor. But it still works. Better lucky than good.
寻找这种用法的逻辑有点古怪,可能会从快速重构中受益。但它仍然有效。好运不如好运。
回答by MeestorHok
Nice one-line solution:
不错的单行解决方案:
function truncate (num, places) {
return Math.trunc(num * Math.pow(10, places)) / Math.pow(10, places);
}
Then call it with:
然后调用它:
truncate(3.5636232, 2); // returns 3.56
truncate(5.4332312, 3); // returns 5.433
truncate(25.463214, 4); // returns 25.4632
回答by Daniel X Moore
I thought I'd throw in an answer using |
since it is simple and works well.
我想我会抛出一个答案,|
因为它很简单而且效果很好。
truncate = function(number, places) {
var shift = Math.pow(10, places);
return ((number * shift) | 0) / shift;
};
回答by John Strickler
Truncate using bitwise operators:
使用按位运算符截断:
~~0.5 === 0
~~(-0.5) === 0
~~14.32794823 === 14
~~(-439.93) === -439
回答by zurfyx
@Dogbert's answer can be improved with Math.trunc
, which truncates instead of rounding.
@Dogbert 的答案可以用 改进Math.trunc
,它会截断而不是四舍五入。
There is a difference between rounding and truncating. Truncating is clearly the behaviour this question is seeking. If I call truncate(-3.14) and receive -4 back, I would definitely call that undesirable. – @NickKnowlson
舍入和截断是有区别的。截断显然是这个问题所寻求的行为。如果我调用 truncate(-3.14) 并收到 -4,我肯定会认为这是不受欢迎的。– @尼克诺森
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
回答by Flavio
function toFixed(number, digits) {
var reg_ex = new RegExp("(\d+\.\d{" + digits + "})(\d)")
var array = number.toString().match(reg_ex);
return array ? parseFloat(array[1]) : number.valueOf()
}
var test = 10.123456789
var __fixed = toFixed(test, 6)
console.log(__fixed)
// => 10.123456