sti*_*man 2492 javascript decimal decimal-point rounding
我想最多舍入2位小数,但只在必要时.
输入:
10
1.7777777
9.1
Run Code Online (Sandbox Code Playgroud)
输出:
10
1.78
9.1
Run Code Online (Sandbox Code Playgroud)
我怎么能这样做__CODE__
?
Bri*_*tas 3124
使用 Math.round(num * 100) / 100
A K*_*nin 2887
如果值是文本类型:
parseFloat("123.456").toFixed(2);
Run Code Online (Sandbox Code Playgroud)
如果值是数字:
var numb = 123.23454;
numb = numb.toFixed(2);
Run Code Online (Sandbox Code Playgroud)
有一个缺点,像1.5这样的值会给出"1.50"作为输出.@minitech建议修复:
var numb = 1.5;
numb = +numb.toFixed(2);
// Note the plus sign that drops any "extra" zeroes at the end.
// It changes the result (which is a string) into a number again (think "0 + foo"),
// which means that it uses only as many digits as necessary.
Run Code Online (Sandbox Code Playgroud)
这似乎Math.round
是一个更好的解决方案.但事实并非如此!在某些情况下,它不会正确圆:
Math.round(1.005 * 1000)/1000 // Returns 1 instead of expected 1.01!
Run Code Online (Sandbox Code Playgroud)
在某些情况下,toFixed()也不会正确舍入(在Chrome v.55.0.2883.87中测试)!
例子:
parseFloat("1.555").toFixed(2); // Returns 1.55 instead of 1.56.
parseFloat("1.5550").toFixed(2); // Returns 1.55 instead of 1.56.
// However, it will return correct result if you round 1.5551.
parseFloat("1.5551").toFixed(2); // Returns 1.56 as expected.
1.3555.toFixed(3) // Returns 1.355 instead of expected 1.356.
// However, it will return correct result if you round 1.35551.
1.35551.toFixed(2); // Returns 1.36 as expected.
Run Code Online (Sandbox Code Playgroud)
我想,这是因为1.555实际上就像浮动1.55499994幕后.
解决方案1是使用具有所需舍入算法的脚本,例如:
function roundNumber(num, scale) {
if(!("" + num).includes("e")) {
return +(Math.round(num + "e+" + scale) + "e-" + scale);
} else {
var arr = ("" + num).split("e");
var sig = ""
if(+arr[1] + scale > 0) {
sig = "+";
}
return +(Math.round(+arr[0] + "e" + sig + (+arr[1] + scale)) + "e-" + scale);
}
}
Run Code Online (Sandbox Code Playgroud)
https://plnkr.co/edit/uau8BlS1cqbvWPCHJeOy?p=preview
解决方案2是避免前端计算并从后端服务器中提取舍入值.
Mar*_*rkG 429
您可以使用
function roundToTwo(num) {
return +(Math.round(num + "e+2") + "e-2");
}
Run Code Online (Sandbox Code Playgroud)
我在MDN上发现了这个.他们的方式避免了提到的 1.005的问题.
roundToTwo(1.005)
1.01
roundToTwo(10)
10
roundToTwo(1.7777777)
1.78
roundToTwo(9.1)
9.1
roundToTwo(1234.5678)
1234.57
Run Code Online (Sandbox Code Playgroud)
Lav*_*tis 140
MarkG的答案是正确的.这是任意数量小数位的通用扩展名.
Number.prototype.round = function(places) {
return +(Math.round(this + "e+" + places) + "e-" + places);
}
Run Code Online (Sandbox Code Playgroud)
用法:
var n = 1.7777;
n.round(2); // 1.78
Run Code Online (Sandbox Code Playgroud)
单元测试:
it.only('should round floats to 2 places', function() {
var cases = [
{ n: 10, e: 10, p:2 },
{ n: 1.7777, e: 1.78, p:2 },
{ n: 1.005, e: 1.01, p:2 },
{ n: 1.005, e: 1, p:0 },
{ n: 1.77777, e: 1.8, p:1 }
]
cases.forEach(function(testCase) {
var r = testCase.n.round(testCase.p);
assert.equal(r, testCase.e, 'didn\'t get right number');
});
})
Run Code Online (Sandbox Code Playgroud)
cro*_*vel 85
你应该使用:
Math.round( num * 100 + Number.EPSILON ) / 100
Run Code Online (Sandbox Code Playgroud)
似乎没有人知道Number.EPSILON
.
另外值得注意的是,这并不是像某些人所说的JavaScript怪异.
这就是浮点数在计算机中的工作方式.像99%的编程语言一样,JavaScript没有自制的浮点数; 它依赖于CPU/FPU.计算机使用二进制,并且在二进制中,没有任何数字0.1
,但仅仅是二进制近似.为什么?出于同样的原因,1/3不能写成十进制:它的值是0.33333333 ......无穷大的三分.
来了Number.EPSILON
.该数字是1和双精度浮点数中存在的下一个数字之间的差值.就是这样:1
1 + 之间没有数字Number.EPSILON
.
编辑:
正如评论中所要求的那样,让我们澄清一件事:Number.EPSILON
只有当round的值是算术运算的结果时才添加,因为它可以吞下一些浮点误差delta.
当值来自直接源(例如:文字,用户输入或传感器)时,它没有用.
Gou*_*gla 80
一个人可以使用.toFixed(NumberOfDecimalPlaces)
.
var str = 10.234.toFixed(2); // => '10.23'
var number = Number(str); // => 10.23
Run Code Online (Sandbox Code Playgroud)
Ace*_*ban 70
考虑.toFixed()
并.toPrecision()
:
http://www.javascriptkit.com/javatutors/formatnumber.shtml
Mar*_*ery 69
这个问题很复杂.
假设我们有一个函数,roundTo2DP(num)
它将float作为参数并返回一个舍入到2位小数的值.每个表达式应该评估什么?
roundTo2DP(0.014999999999999999)
roundTo2DP(0.0150000000000000001)
roundTo2DP(0.015)
"显而易见"的答案是第一个例子应该舍入到0.01(因为它接近0.01而不是0.02),而另外两个应该舍入到0.02(因为0.0150000000000000001接近0.02而不是0.01,因为0.015恰好在中间他们并且有一个数学约定,这些数字被四舍五入).
您可能已经猜到的问题是,roundTo2DP
无法实现这些明显的答案,因为传递给它的所有三个数字都是相同的数字.IEEE 754二进制浮点数(JavaScript使用的类型)不能精确地表示大多数非整数数字,因此上面的所有三个数字文字都会四舍五入到附近的有效浮点数.事实上,这个数字正是如此
0.01499999999999999944488848768742172978818416595458984375
它接近0.01而不是0.02.
您可以在浏览器控制台,Node shell或其他JavaScript解释器中看到所有三个数字相同.只是比较它们:
> 0.014999999999999999 === 0.0150000000000000001
true
Run Code Online (Sandbox Code Playgroud)
因此,当我写作时m = 0.0150000000000000001
,我最终得到的确切值m
更接近于0.01
它0.02
.然而,如果我转换m
为String ...
> var m = 0.0150000000000000001;
> console.log(String(m));
0.015
> var m = 0.014999999999999999;
> console.log(String(m));
0.015
Run Code Online (Sandbox Code Playgroud)
...我得到0.015,它应该舍入到0.02,这显然不是我之前说过的所有这些数字完全相等的56位小数位数.那么黑暗魔法是什么呢?
答案可以在ECMAScript规范的7.1.12.1节中找到:ToString应用于Number类型.这里规定了将一些数字m转换为字符串的规则.关键部分是第5点,其中生成一个整数s,其数字将用于m的字符串表示:
让Ñ,ķ,和小号是整数,使得ķ ≥1,10 ķ -1 ≤ 小号 <10 ķ,为对数的值小号 ×10 ñ - ķ是米,并且ķ是尽可能小.注意,k是s的十进制表示中的位数,s不能被10整除,并且s的最低有效位不一定由这些标准唯一确定.
这里的关键部分是要求" k尽可能小".该要求相当于一个要求,给定一个数字m
,String(m)
必须具有最小可能的位数,同时仍满足要求Number(String(m)) === m
.既然我们已经知道,0.015 === 0.0150000000000000001
现在已经清楚为什么String(0.0150000000000000001) === '0.015'
必须如此.
当然,这些讨论都没有直接回答roundTo2DP(m)
应该返回的内容.如果m
确切的值是0.01499999999999999944488848768742172978818416595458984375,但它的字符串表示是'0.015',那么当我们将它舍入到两个小数位时,什么是正确的答案 - 数学,实际,哲学或其他什么?
对此没有一个正确的答案.这取决于您的用例.在下列情况下,您可能希望尊重String表示并向上舍入:
另一方面,当您的值来自固有的连续标度时,您可能希望尊重二进制浮点值并向下舍入 - 例如,如果它是来自传感器的读数.
这两种方法需要不同的代码.为了尊重Number的String表示,我们可以(通过相当多一些相当微妙的代码)实现我们自己的舍入,它直接作用于String表示,逐位,使用您在学校时使用的相同算法被教导如何围绕数字.下面是一个例子,它尊重OP要求通过在小数点后剥去尾随零来"仅在必要时"将数字表示为2位小数的要求; 当然,您可能需要根据您的确切需求进行调整.
/**
* Converts num to a decimal string (if it isn't one already) and then rounds it
* to at most dp decimal places.
*
* For explanation of why you'd want to perform rounding operations on a String
* rather than a Number, see http://stackoverflow.com/a/38676273/1709587
*
* @param {(number|string)} num
* @param {number} dp
* @return {string}
*/
function roundStringNumberWithoutTrailingZeroes (num, dp) {
if (arguments.length != 2) throw new Error("2 arguments required");
num = String(num);
if (num.indexOf('e+') != -1) {
// Can't round numbers this large because their string representation
// contains an exponent, like 9.99e+37
throw new Error("num too large");
}
if (num.indexOf('.') == -1) {
// Nothing to do
return num;
}
var parts = num.split('.'),
beforePoint = parts[0],
afterPoint = parts[1],
shouldRoundUp = afterPoint[dp] >= 5,
finalNumber;
afterPoint = afterPoint.slice(0, dp);
if (!shouldRoundUp) {
finalNumber = beforePoint + '.' + afterPoint;
} else if (/^9+$/.test(afterPoint)) {
// If we need to round up a number like 1.9999, increment the integer
// before the decimal point and discard the fractional part.
finalNumber = Number(beforePoint)+1;
} else {
// Starting from the last digit, increment digits until we find one
// that is not 9, then stop
var i = dp-1;
while (true) {
if (afterPoint[i] == '9') {
afterPoint = afterPoint.substr(0, i) +
'0' +
afterPoint.substr(i+1);
i--;
} else {
afterPoint = afterPoint.substr(0, i) +
(Number(afterPoint[i]) + 1) +
afterPoint.substr(i+1);
break;
}
}
finalNumber = beforePoint + '.' + afterPoint;
}
// Remove trailing zeroes from fractional part before returning
return finalNumber.replace(/0+$/, '')
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
> roundStringNumberWithoutTrailingZeroes(1.6, 2)
'1.6'
> roundStringNumberWithoutTrailingZeroes(10000, 2)
'10000'
> roundStringNumberWithoutTrailingZeroes(0.015, 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes('0.015000', 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes(1, 1)
'1'
> roundStringNumberWithoutTrailingZeroes('0.015', 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes(0.01499999999999999944488848768742172978818416595458984375, 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes('0.01499999999999999944488848768742172978818416595458984375', 2)
'0.01'
Run Code Online (Sandbox Code Playgroud)
上面的函数可能就是你想要用来避免用户看到他们输入的数字被错误舍入的内容.
(作为替代方案,您也可以尝试使用round10库,该库提供类似行为的函数,具有完全不同的实现.)
但是,如果你有第二种数字 - 从连续尺度中取得的值,那么没有理由认为具有较少小数位的近似十进制表示比具有更多数字的数字更准确?在这种情况下,我们不希望尊重String表示,因为该表示(如规范中所述)已经是排序的; 我们不想错误地说"0.014999999 ... 375轮到0.015,最高为0.02,所以0.014999999 ...... 375轮到0.02".
在这里,我们可以简单地使用内置toFixed
方法.请注意,通过调用Number()
返回的String toFixed
,我们得到一个Number,其String表示没有尾随零(由于JavaScript计算数字的String表示的方式,在本回答前面讨论过).
/**
* Takes a float and rounds it to at most dp decimal places. For example
*
* roundFloatNumberWithoutTrailingZeroes(1.2345, 3)
*
* returns 1.234
*
* Note that since this treats the value passed to it as a floating point
* number, it will have counterintuitive results in some cases. For instance,
*
* roundFloatNumberWithoutTrailingZeroes(0.015, 2)
*
* gives 0.01 where 0.02 might be expected. For an explanation of why, see
* http://stackoverflow.com/a/38676273/1709587. You may want to consider using the
* roundStringNumberWithoutTrailingZeroes function there instead.
*
* @param {number} num
* @param {number} dp
* @return {number}
*/
function roundFloatNumberWithoutTrailingZeroes (num, dp) {
var numToFixedDp = Number(num).toFixed(dp);
return Number(numToFixedDp);
}
Run Code Online (Sandbox Code Playgroud)
use*_*ser 62
精确的舍入方法.资料来源:Mozilla
(function(){
/**
* Decimal adjustment of a number.
*
* @param {String} type The type of adjustment.
* @param {Number} value The number.
* @param {Integer} exp The exponent (the 10 logarithm of the adjustment base).
* @returns {Number} The adjusted value.
*/
function decimalAdjust(type, value, exp) {
// If the exp is undefined or zero...
if (typeof exp === 'undefined' || +exp === 0) {
return Math[type](value);
}
value = +value;
exp = +exp;
// If the value is not a number or the exp is not an integer...
if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {
return NaN;
}
// Shift
value = value.toString().split('e');
value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp)));
// Shift back
value = value.toString().split('e');
return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp));
}
// Decimal round
if (!Math.round10) {
Math.round10 = function(value, exp) {
return decimalAdjust('round', value, exp);
};
}
// Decimal floor
if (!Math.floor10) {
Math.floor10 = function(value, exp) {
return decimalAdjust('floor', value, exp);
};
}
// Decimal ceil
if (!Math.ceil10) {
Math.ceil10 = function(value, exp) {
return decimalAdjust('ceil', value, exp);
};
}
})();
Run Code Online (Sandbox Code Playgroud)
例子:
// Round
Math.round10(55.55, -1); // 55.6
Math.round10(55.549, -1); // 55.5
Math.round10(55, 1); // 60
Math.round10(54.9, 1); // 50
Math.round10(-55.55, -1); // -55.5
Math.round10(-55.551, -1); // -55.6
Math.round10(-55, 1); // -50
Math.round10(-55.1, 1); // -60
Math.round10(1.005, -2); // 1.01 -- compare this with Math.round(1.005*100)/100 above
// Floor
Math.floor10(55.59, -1); // 55.5
Math.floor10(59, 1); // 50
Math.floor10(-55.51, -1); // -55.6
Math.floor10(-51, 1); // -60
// Ceil
Math.ceil10(55.51, -1); // 55.6
Math.ceil10(51, 1); // 60
Math.ceil10(-55.59, -1); // -55.5
Math.ceil10(-59, 1); // -50
Run Code Online (Sandbox Code Playgroud)
mac*_*ict 59
这里找到的答案都不正确.@stinkycheeseman要求围捕,你们四舍五入.
要整理,请使用:
Math.ceil(num * 100)/100;
Run Code Online (Sandbox Code Playgroud)
Jay*_*yDM 46
这是一个简单的方法:
Math.round(value * 100) / 100
Run Code Online (Sandbox Code Playgroud)
您可能希望继续执行单独的功能来为您执行此操作:
function roundToTwo(value) {
return(Math.round(value * 100) / 100);
}
Run Code Online (Sandbox Code Playgroud)
然后你只需传入值.
您可以通过添加第二个参数来增强它以舍入到任意数量的小数.
function myRound(value, places) {
var multiplier = Math.pow(10, places);
return (Math.round(value * multiplier) / multiplier);
}
Run Code Online (Sandbox Code Playgroud)
小智 36
+(10).toFixed(2); // = 10
+(10.12345).toFixed(2); // = 10.12
(10).toFixed(2); // = 10.00
(10.12345).toFixed(2); // = 10.12
Run Code Online (Sandbox Code Playgroud)
Vik*_*ngh 36
对我来说,Math.round()没有给出正确答案.我发现固定(2)效果更好.以下是两者的示例:
console.log(Math.round(43000 / 80000) * 100); // wrong answer
console.log(((43000 / 80000) * 100).toFixed(2)); // correct answer
Run Code Online (Sandbox Code Playgroud)
小智 35
使用此功能 Number(x).toFixed(2);
pet*_*ner 32
尝试这个轻量级解决方案:
function round(x, digits){
return parseFloat(x.toFixed(digits))
}
round(1.222, 2) ;
// 1.22
round(1.222, 10) ;
// 1.222
Run Code Online (Sandbox Code Playgroud)
per*_*mon 32
2017
只需使用本机代码.toFixed()
number = 1.2345;
number.toFixed(2) // "1.23"
Run Code Online (Sandbox Code Playgroud)
如果您需要严格并且只在需要时添加数字,它可以使用 replace
number = 1; // "1"
number.toFixed(5).replace(/\.?0*$/g,'');
Run Code Online (Sandbox Code Playgroud)
小智 32
另一个简单的解决方案(无需编写任何函数)可以使用 toFixed() 然后再次转换为 float:
例如:
var objNumber = 1201203.1256546456;
objNumber = parseFloat(objNumber.toFixed(2))
Run Code Online (Sandbox Code Playgroud)
sta*_*005 28
有几种方法可以做到这一点.像我这样的人,Lodash的变种
function round(number, precision) {
var pair = (number + 'e').split('e')
var value = Math.round(pair[0] + 'e' + (+pair[1] + precision))
pair = (value + 'e').split('e')
return +(pair[0] + 'e' + (+pair[1] - precision))
}
Run Code Online (Sandbox Code Playgroud)
用法:
round(0.015, 2) // 0.02
round(1.005, 2) // 1.01
Run Code Online (Sandbox Code Playgroud)
如果你的项目使用jQuery或lodash,你也可以round
在库中找到合适的方法.
我删除了变体n.toFixed(2)
,因为它不正确.谢谢@ avalanche1
Mad*_*eep 24
如果您使用的是lodash库,则可以使用lodash的圆形方法,如下所示.
_.round(number, precision)
Run Code Online (Sandbox Code Playgroud)
例如:
_.round(1.7777777, 2) = 1.78
Run Code Online (Sandbox Code Playgroud)
Mar*_*ago 24
最简单的方法是使用 toFixed,然后使用 Number 函数去除尾随零:
const number = 15.5;
Number(number.toFixed(2)); // 15.5
Run Code Online (Sandbox Code Playgroud)
const number = 1.7777777;
Number(number.toFixed(2)); // 1.78
Run Code Online (Sandbox Code Playgroud)
ast*_*ije 22
MarkG和Lavamantis提供了一个比被接受的解决方案更好的解决方案.遗憾的是他们没有得到更多的赞成!
这是我用来解决基于MDN的浮点小数问题的函数.它比Lavamantis的解决方案更通用(但更简洁):
function round(value, exp) {
if (typeof exp === 'undefined' || +exp === 0)
return Math.round(value);
value = +value;
exp = +exp;
if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0))
return NaN;
// Shift
value = value.toString().split('e');
value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)));
// Shift back
value = value.toString().split('e');
return +(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp));
}
Run Code Online (Sandbox Code Playgroud)
使用它:
round(10.8034, 2); // Returns 10.8
round(1.275, 2); // Returns 1.28
round(1.27499, 2); // Returns 1.27
round(1.2345678e+2, 2); // Returns 123.46
Run Code Online (Sandbox Code Playgroud)
与Lavamantis的解决方案相比,我们可以......
round(1234.5678, -2); // Returns 1200
round("123.45"); // Returns 123
Run Code Online (Sandbox Code Playgroud)
Mat*_*ius 20
从ES6开始,有一种"正确的"方式(没有覆盖静态和创建变通方法),通过使用toPrecision来实现这一点
var x = 1.49999999999;
console.log(x.toPrecision(4));
console.log(x.toPrecision(3));
console.log(x.toPrecision(2));
var y = Math.PI;
console.log(y.toPrecision(6));
console.log(y.toPrecision(5));
console.log(y.toPrecision(4));
var z = 222.987654
console.log(z.toPrecision(6));
console.log(z.toPrecision(5));
console.log(z.toPrecision(4));
Run Code Online (Sandbox Code Playgroud)
tot*_*ten 16
这可能对您有所帮助:
var result = (Math.round(input*100)/100);
Run Code Online (Sandbox Code Playgroud)
有关更多信息,您可以查看此链接
Math.round(num)vs num.toFixed(0)和浏览器不一致
小智 16
var roundUpto = function(number, upto){
return Number(number.toFixed(upto));
}
roundUpto(0.1464676, 2);
Run Code Online (Sandbox Code Playgroud)
toFixed(2)
这里2是我们想要对这个数字进行舍入的数字位数.
Vic*_*dlf 16
function round(
value,
minimumFractionDigits,
maximumFractionDigits
) {
const formattedValue = value.toLocaleString('en', {
useGrouping: false,
minimumFractionDigits,
maximumFractionDigits
})
return Number(formattedValue)
}
console.log(round(21.891, 2, 3)) // 21.891
console.log(round(1.8, 2)) // 1.8, if you need 1.80, remove the `Number` function. Return directly the `formattedValue`.
console.log(round(21.0001, 0, 1)) // 21
console.log(round(0.875, 3)) // 0.875
Run Code Online (Sandbox Code Playgroud)
Shr*_*har 15
它可能适合你,
Math.round(num * 100)/100;
Run Code Online (Sandbox Code Playgroud)
知道toFixed和round之间的区别.您可以查看Math.round(num)与num.toFixed(0)和浏览器不一致.
小智 13
这是一个原型方法:
Number.prototype.round = function(places){
places = Math.pow(10, places);
return Math.round(this * places)/places;
}
var yournum = 10.55555;
yournum = yournum.round(2);
Run Code Online (Sandbox Code Playgroud)
小智 13
使用类似"parseFloat(parseFloat(value).toFixed(2))"的内容
parseFloat(parseFloat("1.7777777").toFixed(2))-->1.78
parseFloat(parseFloat("10").toFixed(2))-->10
parseFloat(parseFloat("9.1").toFixed(2))-->9.1
Run Code Online (Sandbox Code Playgroud)
Jav*_*ome 11
只在必要时才实现这种舍入的一种方法是使用Number.prototype.toLocaleString():
myNumber.toLocaleString('en', {maximumFractionDigits:2, useGrouping:false})
Run Code Online (Sandbox Code Playgroud)
这将提供您期望的输出,但作为字符串.如果这不是您期望的数据类型,您仍然可以将它们转换回数字.
Amr*_*Ali 11
通常,舍入是通过缩放来完成的: round(num / p) * p
使用指数表示法正确处理+ ve数字的舍入.但是,此方法无法正确舍入边缘情况.
function round(num, precision = 2) {
var scaled = Math.round(num + "e" + precision);
return Number(scaled + "e" + -precision);
}
// testing some edge cases
console.log( round(1.005, 2) ); // 1.01 correct
console.log( round(2.175, 2) ); // 2.18 correct
console.log( round(5.015, 2) ); // 5.02 correct
console.log( round(-1.005, 2) ); // -1 wrong
console.log( round(-2.175, 2) ); // -2.17 wrong
console.log( round(-5.015, 2) ); // -5.01 wrong
Run Code Online (Sandbox Code Playgroud)
在这里,我也写了一个函数正确地进行算术舍入.你可以自己测试一下.
/**
* MidpointRounding away from zero ('arithmetic' rounding)
* Uses a half-epsilon for correction. (This offsets IEEE-754
* half-to-even rounding that was applied at the edge cases).
*/
function RoundCorrect(num, precision = 2) {
// half epsilon to correct edge cases.
var c = 0.5 * Number.EPSILON * num;
// var p = Math.pow(10, precision); //slow
var p = 1; while (precision--> 0) p *= 10;
if (num < 0)
p *= -1;
return Math.round((num + c) * p) / p;
}
// testing some edge cases
console.log(RoundCorrect(1.005, 2)); // 1.01 correct
console.log(RoundCorrect(2.175, 2)); // 2.18 correct
console.log(RoundCorrect(5.015, 2)); // 5.02 correct
console.log(RoundCorrect(-1.005, 2)); // -1.01 correct
console.log(RoundCorrect(-2.175, 2)); // -2.18 correct
console.log(RoundCorrect(-5.015, 2)); // -5.02 correct
Run Code Online (Sandbox Code Playgroud)
小智 11
我不喜欢Math.round
像Brian Ustas 建议的那样使用,而是更喜欢Math.trunc
解决以下情况的方法:
const twoDecimalRound = num => Math.round(num * 100) / 100;
const twoDecimalTrunc = num => Math.trunc(num * 100) / 100;
console.info(twoDecimalRound(79.996)); // Not desired output: 80;
console.info(twoDecimalTrunc(79.996)); // Desired output: 79.99;
Run Code Online (Sandbox Code Playgroud)
如果你碰巧已经在使用d3库,他们有一个强大的数字格式库:https://github.com/mbostock/d3/wiki/Formatting
具体舍入在这里:https://github.com/mbostock/d3/wiki/Formatting#d3_round
在您的情况下,答案是:
> d3.round(1.777777, 2)
1.78
> d3.round(1.7, 2)
1.7
> d3.round(1, 2)
1
Run Code Online (Sandbox Code Playgroud)
这是最简单,更优雅的解决方案(我是世界上最好的解决方案;):
function roundToX(num, X) {
return +(Math.round(num + "e+"+X) + "e-"+X);
}
//roundToX(66.66666666,2) => 66.67
//roundToX(10,2) => 10
//roundToX(10.904,2) => 10.9
Run Code Online (Sandbox Code Playgroud)
更简单的ES6方式是
const round = (x, n) =>
parseFloat(Math.round(x * Math.pow(10, n)) / Math.pow(10, n)).toFixed(n);
Run Code Online (Sandbox Code Playgroud)
此模式还返回所要求的精度.
例如:
round(44.7826456, 4) // yields 44.7826
round(78.12, 4) // yields 78.1200
Run Code Online (Sandbox Code Playgroud)
如果你想要整理,简单的解决方案就是使用lodash的ceil功能......
https://lodash.com/docs/4.17.10#ceil
_.round(6.001,2)
Run Code Online (Sandbox Code Playgroud)
给出6
_.ceil(6.001, 2);
Run Code Online (Sandbox Code Playgroud)
给出6.01
_.ceil(37.4929,2);
Run Code Online (Sandbox Code Playgroud)
给出37.5
_.round(37.4929,2);
Run Code Online (Sandbox Code Playgroud)
给出37.49
小智 8
另一种方法是使用库。为什么不呢lodash
?
const _ = require("lodash")
const roundedNumber = _.round(originalNumber, 2)
Run Code Online (Sandbox Code Playgroud)
一个简单的通用解决方案
const round = (n, dp) => {
const h = +('1'.padEnd(dp + 1, '0')) // 10 or 100 or 1000 or etc
return Math.round(n * h) / h
}
console.log('round(2.3454, 3)', round(2.3454, 3)) // 2.345
console.log('round(2.3456, 3)', round(2.3456, 3)) // 2.346
console.log('round(2.3456, 2)', round(2.3456, 2)) // 2.35
Run Code Online (Sandbox Code Playgroud)
或者只使用具有相同签名的Lodash round - 例如 _.round(2.3456, 2)
Math.round((num + 0.00001) * 100) / 100
Run Code Online (Sandbox Code Playgroud)
这适用于以下两个示例:
Math.round((1.005 + 0.00001) * 100) / 100
Math.round((1.0049 + 0.00001) * 100) / 100
Run Code Online (Sandbox Code Playgroud)
parseFloat(“ 1.555”)。toFixed(2); //返回1.55,而不是1.56。
1.55是绝对正确的结果,因为计算机中不存在1.555的确切表示。如果读数为1.555,则四舍五入为最接近的可能值= 1.55499999999999994(64位浮点型)。并将此数字四舍五入到toFixed(2)将得出1.55。
如果输入为1.55499999999999,则此处提供的所有其他功能都会给出故障结果。
解决方案:在扫描之前将数字“ 5”附加到四舍五入(更精确地说:从0舍入)。仅当数字确实是浮点数(有小数点)时才这样做。
parseFloat("1.555"+"5").toFixed(2); // Returns 1.56
Run Code Online (Sandbox Code Playgroud)
在经过所有可能的方式的各种迭代以达到真正准确的十进制舍入精度之后,很明显,最准确和有效的解决方案是使用Number.EPSILON。这为浮点数学精度问题提供了一个真正的数学解决方案。可以很容易地对其进行填充,如下所示:https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON以支持所有剩余的IE用户(那么也许我们再次应该停止这样做)。
改编自此处提供的解决方案:https : //stackoverflow.com/a/48850944/6910392
一种简单的解决方案,可提供准确的小数舍入,下限和上限,并带有可选的precision变量,而无需添加整个库。
var DecimalPrecision = (function(){
if (Number.EPSILON === undefined) {
Number.EPSILON = Math.pow(2, -52);
}
this.round = function(n, p=2){
let r = 0.5 * Number.EPSILON * n;
let o = 1; while(p-- > 0) o *= 10;
if(n < 0)
o *= -1;
return Math.round((n + r) * o) / o;
}
this.ceil = function(n, p=2){
let r = 0.5 * Number.EPSILON * n;
let o = 1; while(p-- > 0) o *= 10;
if(n < 0)
o *= -1;
return Math.ceil((n + r) * o) / o;
}
this.floor = function(n, p=2){
let r = 0.5 * Number.EPSILON * n;
let o = 1; while(p-- > 0) o *= 10;
if(n < 0)
o *= -1;
return Math.floor((n + r) * o) / o;
}
return this;
})();
console.log(DecimalPrecision.round(1.005));
console.log(DecimalPrecision.ceil(1.005));
console.log(DecimalPrecision.floor(1.005));
console.log(DecimalPrecision.round(1.0049999));
console.log(DecimalPrecision.ceil(1.0049999));
console.log(DecimalPrecision.floor(1.0049999));
console.log(DecimalPrecision.round(2.175495134384,7));
console.log(DecimalPrecision.round(2.1753543549,8));
console.log(DecimalPrecision.round(2.1755465135353,4));
Run Code Online (Sandbox Code Playgroud)
我将再添加一个方法.
number = 16.6666666;
console.log(parseFloat(number.toFixed(2)));
"16.67"
number = 16.6;
console.log(parseFloat(number.toFixed(2)));
"16.6"
number = 16;
console.log(parseFloat(number.toFixed(2)));
"16"
Run Code Online (Sandbox Code Playgroud)
.toFixed(2)
返回一个带有2个小数点的字符串,可能是也可能不是尾随零.做一个parseFloat()
将消除那些尾随零.
将类型保留为整数,以便以后进行排序或其他数学运算:
Math.round(1.7777777 * 100)/100
Run Code Online (Sandbox Code Playgroud)
1.78
// Round up!
Math.ceil(1.7777777 * 100)/100
Run Code Online (Sandbox Code Playgroud)
1.78
// Round down!
Math.floor(1.7777777 * 100)/100
Run Code Online (Sandbox Code Playgroud)
1.77
或转换为字符串:
(1.7777777).toFixed(2)
Run Code Online (Sandbox Code Playgroud)
“ 1.77”
问题是四舍五入到小数点后两位。
\n让\xe2\x80\x99s不要让这个变得复杂,修改原型链等等。
\n这是单行解决方案
\nlet round2dec = num => Math.round(num * 100) / 100;\n\nconsole.log(round2dec(1.77));\nconsole.log(round2dec(1.774));\nconsole.log(round2dec(1.777));\nconsole.log(round2dec(10));
Run Code Online (Sandbox Code Playgroud)\r\n带领我们到
let round= x=> ( x+0.005 - (x+0.005)%0.01 +'' ).replace(/(\...)(.*)/,'$1');
// for a case like 1.384 we need to use a regexp to get only 2 digits after the dot
// and cut off machine-error (epsilon)
console.log(round(10));
console.log(round(1.7777777));
console.log(round(1.7747777));
console.log(round(1.384));
Run Code Online (Sandbox Code Playgroud)
我查看了这篇文章的每个答案。以下是我对此事的看法:
const nbRounds = 7;
const round = (x, n=2) => {
const precision = Math.pow(10, n)
return Math.round((x+Number.EPSILON) * precision ) / precision;
}
let i = 0;
while( nbRounds > i++ ) {
console.log("round(1.00083899, ",i,") > ", round(1.00083899, i))
console.log("round(1.83999305, ",i,") > ", round(1.83999305, i))
}
Run Code Online (Sandbox Code Playgroud)
小智 6
我读过所有的答案,类似问题的答案和最“好”解决方案的复杂性并不能令我满意。我不想放置一个巨大的圆形函数集,或者一个小但在科学记数法上失败的函数集。所以,我想出了这个功能。它可能会帮助处于我这种情况的人:
function round(num, dec) {
const [sv, ev] = num.toString().split('e');
return Number(Number(Math.round(parseFloat(sv + 'e' + dec)) + 'e-' + dec) + 'e' + (ev || 0));
}
Run Code Online (Sandbox Code Playgroud)
我没有运行任何性能测试,因为我调用它只是为了更新应用程序的 UI。该函数给出以下快速测试结果:
// 1/3563143 = 2.806510993243886e-7
round(1/3563143, 2) // returns `2.81e-7`
round(1.31645, 4) // returns 1.3165
round(-17.3954, 2) // returns -17.4
Run Code Online (Sandbox Code Playgroud)
这对我来说就足够了。
要按小数点四舍五入pos
(包括没有小数),请执行以下操作Math.round(num * Math.pow(10,pos)) / Math.pow(10,pos)
var console = {
log: function(s) {
document.getElementById("console").innerHTML += s + "<br/>"
}
}
var roundDecimals=function(num,pos) {
return (Math.round(num * Math.pow(10,pos)) / Math.pow(10,pos) );
}
//https://en.wikipedia.org/wiki/Pi
var pi=3.14159265358979323846264338327950288419716939937510;
for(var i=2;i<15;i++) console.log("pi="+roundDecimals(pi,i));
for(var i=15;i>=0;--i) console.log("pi="+roundDecimals(pi,i));
Run Code Online (Sandbox Code Playgroud)
<div id="console" />
Run Code Online (Sandbox Code Playgroud)
我知道有很多答案,但大多数答案在某些特定情况下都有副作用.
最简单,最短的解决方案没有任何副作用如下:
Number((2.3456789).toFixed(2)) // 2.35
Run Code Online (Sandbox Code Playgroud)
它正确地舍入并返回数字而不是字符串
console.log(Number((2.345).toFixed(2))) // 2.35
console.log(Number((2.344).toFixed(2))) // 2.34
console.log(Number((2).toFixed(2))) // 2
console.log(Number((-2).toFixed(2))) // -2
console.log(Number((-2.345).toFixed(2))) // -2.35
console.log(Number((2.345678).toFixed(3))) // 2.346
Run Code Online (Sandbox Code Playgroud)
这对我来说是个窍门(TypeScript):
round(decimal: number, decimalPoints: number): number{
let roundedValue = Math.round(decimal * Math.pow(10, decimalPoints)) / Math.pow(10, decimalPoints);
console.log(`Rounded ${decimal} to ${roundedValue}`);
return roundedValue;
}
// Sample output:
Rounded 18.339840000000436 to 18.34
Rounded 52.48283999999984 to 52.48
Rounded 57.24612000000036 to 57.25
Rounded 23.068320000000142 to 23.07
Rounded 7.792980000000398 to 7.79
Rounded 31.54157999999981 to 31.54
Rounded 36.79686000000004 to 36.8
Rounded 34.723080000000124 to 34.72
Rounded 8.4375 to 8.44
Rounded 15.666960000000074 to 15.67
Rounded 29.531279999999924 to 29.53
Rounded 8.277420000000006 to 8.28
Run Code Online (Sandbox Code Playgroud)
小智 5
这个功能对我有用。您只需传入数字和要舍入的位置,它就可以轻松完成所需的工作。
round(source, n) {
let places = Math.pow(10, n);
return Math.round(source * places) / places;
}
Run Code Online (Sandbox Code Playgroud)
一个简单的通用舍入函数可能如下:
数字是: 1.2375 四舍五入到小数点后 3 位
(注意:10^3 表示 Math.pow(10,3))。
function numberRoundDecimal(v,n) {
return Math.round((v+Number.EPSILON)*Math.pow(10,n))/Math.pow(10,n)}
// ------- tests --------
console.log(numberRoundDecimal(-0.024641163062896567,3)) // -0.025
console.log(numberRoundDecimal(0.9993360575508052,3)) // 0.999
console.log(numberRoundDecimal(1.0020739645577939,3)) // 1.002
console.log(numberRoundDecimal(0.975,0)) // 1
console.log(numberRoundDecimal(0.975,1)) // 1
console.log(numberRoundDecimal(0.975,2)) // 0.98
console.log(numberRoundDecimal(1.005,2)) // 1.01
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2198849 次 |
最近记录: |