kcs*_*ssm 76 javascript floating-point floating-accuracy
我试图将十进制数截断为小数位.像这样的东西:
5.467 -> 5.46
985.943 -> 985.94
Run Code Online (Sandbox Code Playgroud)
toFixed(2)
做正确的事情,但它完成了价值.我不需要四舍五入的值.希望这在javascript中是可能的.
Nic*_*son 52
Dogbert的答案很好,但是如果你的代码可能需要处理负数,那么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
Run Code Online (Sandbox Code Playgroud)
这是这个函数的一个更方便的版本:
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
Run Code Online (Sandbox Code Playgroud)
如果这不是所需的行为,请Math.abs
在第一行插入呼叫:
var multiplier = Math.pow(10, Math.abs(digits)),
Run Code Online (Sandbox Code Playgroud)
编辑: shendz正确指出使用此解决方案a = 17.56
将错误地生成17.55
.有关为什么会发生这种情况的更多信息,请阅读每个计算机科学家应该知道的关于浮点运算的内容.不幸的是,编写一个消除所有浮点错误源的解决方案对于javascript来说非常棘手.在另一种语言中,你使用整数或者可能是十进制类型,但是使用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);
}
Run Code Online (Sandbox Code Playgroud)
对于那些需要速度但又想避免浮点错误的人,可以试试像BigDecimal.js这样的东西.你可以在这个SO问题中找到其他javascript BigDecimal库:"有一个好的Javascript BigDecimal库吗?" 这是一篇关于Javascript数学库的好文章
kir*_*oid 47
更新:
所以,事实证明,无论你多么努力地补偿它们,四舍五入的错误总会困扰着你.因此,应该通过以十进制表示法精确表示数字来攻击该问题.
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]
Run Code Online (Sandbox Code Playgroud)
基于其他人编译的容易出错的解决方案:
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);
}
Run Code Online (Sandbox Code Playgroud)
Dog*_*ert 31
var a = 5.467;
var truncated = Math.floor(a * 100) / 100; // = 5.46
Run Code Online (Sandbox Code Playgroud)
Ric*_*iwi 21
您可以通过减去0.5为toFixed来修复舍入,例如
(f - 0.005).toFixed(2)
Run Code Online (Sandbox Code Playgroud)
ruf*_*fin 16
考虑利用双重波形:~~
.
记下号码.乘以小数点后的有效数字,以便您可以截断到零位~~
.将乘数除去.利润.
function truncator(numToTruncate, intDecimalPlaces) {
var numPower = Math.pow(10, intDecimalPlaces); // "numPowerConverter" might be better
return ~~(numToTruncate * numPower)/numPower;
}
Run Code Online (Sandbox Code Playgroud)
我试图抵制~~
在parens 包裹呼叫; 我相信,操作的顺序应该能够正常工作.
alert(truncator(5.1231231, 1)); // is 5.1
alert(truncator(-5.73, 1)); // is -5.7
alert(truncator(-5.73, 0)); // is -5
编辑:回顾过去,我也无意中处理了小数点左边的情况.
alert(truncator(4343.123, -2)); // gives 4300.
逻辑有点古怪,寻找这种用法,并可能从快速重构中受益.但它仍然有效.比幸运更好.
Dan*_*ore 10
我以为我会用一个答案,|
因为它简单而且效果很好.
truncate = function(number, places) {
var shift = Math.pow(10, places);
return ((number * shift) | 0) / shift;
};
Run Code Online (Sandbox Code Playgroud)
小智 9
不错的单线解决方案:
function truncate (num, places) {
return Math.trunc(num * Math.pow(10, places)) / Math.pow(10, places);
}
Run Code Online (Sandbox Code Playgroud)
然后用:
truncate(3.5636232, 2); // returns 3.56
truncate(5.4332312, 3); // returns 5.433
truncate(25.463214, 4); // returns 25.4632
Run Code Online (Sandbox Code Playgroud)
@ Dogbert的答案可以改进Math.trunc
,截断而不是舍入.
舍入和截断之间存在差异.截断显然是这个问题正在寻求的行为.如果我调用truncate(-3.14)并接收-4返回,我肯定会称之为不合需要的. - @NickKnowlson
var a = 5.467;
var truncated = Math.trunc(a * 100) / 100; // = 5.46
Run Code Online (Sandbox Code Playgroud)
var a = -5.467;
var truncated = Math.trunc(a * 100) / 100; // = -5.46
Run Code Online (Sandbox Code Playgroud)
小智 6
我用更短的方法写了一个答案。这是我想出的
function truncate(value, precision) {
var step = Math.pow(10, precision || 0);
var temp = Math.trunc(step * value);
return temp / step;
}
Run Code Online (Sandbox Code Playgroud)
该方法可以像这样使用
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
Run Code Online (Sandbox Code Playgroud)
或者,如果你想要一个更短的语法,就在这里
function truncate(v, p) {
var s = Math.pow(10, p || 0);
return Math.trunc(s * v) / s;
}
Run Code Online (Sandbox Code Playgroud)
使用按位运算符截断:
~~0.5 === 0
~~(-0.5) === 0
~~14.32794823 === 14
~~(-439.93) === -439
Run Code Online (Sandbox Code Playgroud)
我认为这个功能可能是一个简单的解决方案:
function trunc(decimal,n=2){
let x = decimal + ''; // string
return x.lastIndexOf('.')>=0?parseFloat(x.substr(0,x.lastIndexOf('.')+(n+1))):decimal; // You can use indexOf() instead of lastIndexOf()
}
console.log(trunc(-241.31234,2));
console.log(trunc(241.312,5));
console.log(trunc(-241.233));
console.log(trunc(241.2,0));
console.log(trunc(241));
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
132680 次 |
最近记录: |