在javascript中截断(不舍入)十进制数字

我正在尝试将十进制数字截断为小数位。 像这样的东西:

5.467 -> 5.46 985.943 -> 985.94 

toFixed(2)只是做了正确的事情,但是却把价值收掉了。 我不需要四舍五入的价值。 希望这是可能的JavaScript。

upd

所以,事实certificate,无论你多么努力地补偿他们,四舍五入的错误总会困扰着你。 因此,应该用十进制表示法来表示数字。

 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] 

旧的容易出错的解决scheme是基于编译他人的:

 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); } 

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 

这是这个函数的一个更方便的版本:

 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正确地指出,使用这个解决scheme与a = 17.56将错误地产生17.55 。 有关这种情况的更多信息,请阅读计算机科学家有关浮点运算的知识 。 不幸的是,编写一个消除所有浮点错误的解决scheme对于javascript来说是相当棘手的。 在另一种语言,你会使用整数或可能是十进制types,但与JavaScript …

这个解决scheme应该是 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问题中find其他的JavaScript BigDecimal库: “有一个好的Javascript BigDecimal库吗? 这里有一个关于Javascript的math库的好博客文章

 var a = 5.467; var truncated = Math.floor(a * 100) / 100; // = 5.46 

你可以通过减去0.5来固定舍入,例如

 (f - 0.005).toFixed(2) 

考虑利用双波浪号: ~~

接收号码。 乘以小数点后的有效数字,以便可以用~~ 截断零位。 把这个乘数分开。 利润。

 function truncator(numToTruncate, intDecimalPlaces) { var numPower = Math.pow(10, intDecimalPlaces); // "numPowerConverter" might be better return ~~(numToTruncate * numPower)/numPower; } 

我试图抵制包裹呼吁, 我相信,操作顺序应该能够正确地工作。

alert(truncator(5.1231231, 1)); // is 5.1

alert(truncator(-5.73, 1)); // is -5.7

alert(truncator(-5.73, 0)); // is -5

JSFiddle链接 。

编辑:回顾过去,我也无意中也处理了小数点左边的情况。

alert(truncator(4343.123, -2)); // gives 4300.

该逻辑有点古怪寻找这种用法,并可能受益于快速重构。 但它仍然有效。 比好的好幸运。

我以为我会用|回答问题 因为它很简单,运作良好。

 truncate = function(number, places) { var shift = Math.pow(10, places); return ((number * shift) | 0) / shift; }; 

很好的单线解决scheme:

 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 

使用按位运算符截断:

 ~~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 

标记为解决scheme的是我直到今天发现的更好的解决scheme,但是具有0的严重问题(例如0.toFixedDown(2)给出-0.01)。 所以我build议使用这个:

 Number.prototype.toFixedDown = function(digits) { if(this == 0) { return 0; } 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); } 

这是简单的,但工作函数截断数字高达2小数位。

  function truncateNumber(num) { var num1 = ""; var num2 = ""; var num1 = num.split('.')[0]; num2 = num.split('.')[1]; var decimalNum = num2.substring(0, 2); var strNum = num1 +"."+ decimalNum; var finalNum = parseFloat(strNum); return finalNum; } 
 Number.prototype.trim = function(decimals) { var s = this.toString(); var d = s.split("."); d[1] = d[1].substring(0, decimals); return parseFloat(d.join(".")); } console.log((5.676).trim(2)); //logs 5.67 

我发现一个问题:考虑下一个情况:2.1或1.2或-6.4

如果你总是想要3位小数或2或者wharever,那么你必须完成前面的0到右边

 // 3 decimals numbers 0.5 => 0.500 // 6 decimals 0.1 => 0.10000 // 4 decimales -2.1 => -2.1000 // truncate to 3 decimals 3.11568 => 3.115 

这是Nick Knowlson的固定function

 function truncateDecimals (num, digits) { var numS = num.toString(); var decPos = numS.indexOf('.'); var substrLength = decPos == -1 ? numS.length : 1 + decPos + digits; var trimmedResult = numS.substr(0, substrLength); var finalResult = isNaN(trimmedResult) ? 0 : trimmedResult; // adds leading zeros to the right if (decPos != -1){ var s = trimmedResult+""; decPos = s.indexOf('.'); var decLength = s.length - decPos; while (decLength <= digits){ s = s + "0"; decPos = s.indexOf('.'); decLength = s.length - decPos; substrLength = decPos == -1 ? s.length : 1 + decPos + digits; }; finalResult = s; } return finalResult; }; 

https://jsfiddle.net/huttn155/7/

结果types仍然是一个数字…

 /* Return the truncation of n wrt base */ var trunc = function(n, base) { n = (n / base) | 0; return base * n; }; var t = trunc(5.467, 0.01); 

在这里,我谈谈这个问题:

 convert.truncate = function(value, decimals) { decimals = (decimals === undefined ? 0 : decimals); return parseFloat((value-(0.5/Math.pow(10, decimals))).toFixed(decimals),10); }; 

这只是一个稍微更复杂的版本

 (f - 0.005).toFixed(2) 

只是为了指出一个简单的解决scheme,为我工作

将其转换为string,然后将其正则expression…

 var number = 123.45678; var number_s = '' + number; var number_truncated_s = number_s.match(/\d*\.\d{4}/)[0] var number_truncated = parseFloat(number_truncated_s) 

它可以缩写为

 var number_truncated = parseFloat(('' + 123.4568908).match(/\d*\.\d{4}/)[0]) 

这是我使用的:

 var t = 1; for (var i = 0; i < decimalPrecision; i++) t = t * 10; var f = parseFloat(value); return (Math.floor(f * t)) / t; 

这是一个ES6代码,它可以做你想做的事情

 const truncateTo = (unRouned, nrOfDecimals = 2) => { const parts = String(unRouned).split("."); if (parts.length !== 2) { // without any decimal part return unRouned; } const newDecimals = parts[1].slice(0, nrOfDecimals), newString = `${parts[0]}.${newDecimals}`; return Number(newString); }; // your examples console.log(truncateTo(5.467)); // ---> 5.46 console.log(truncateTo(985.943)); // ---> 985.94 // other examples console.log(truncateTo(5)); // ---> 5 console.log(truncateTo(-5)); // ---> -5 console.log(truncateTo(-985.943)); // ---> -985.94 
 Number.prototype.truncate = function(places) { var shift = Math.pow(10, places); return Math.trunc(this * shift) / shift; }; 

@kirilloid的答案似乎是正确的答案,但是,主代码需要更新。 他的解决scheme不考虑负数(有人在评论部分提到过,但在主代码中没有更新)。

将其更新为完整的最终testing解决scheme:

 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(); }; 

样本用法:

 var x = 3.1415629; Logger.log(x.toFixedDown(2)); //or use whatever you use to log 

小提琴: JS编号向下舍入

PS:没有足够的回购评论该解决scheme。