你如何在Javascript中四舍五入到小数点后一位?

Posted

技术标签:

【中文标题】你如何在Javascript中四舍五入到小数点后一位?【英文标题】:How do you round to 1 decimal place in Javascript? 【发布时间】:2011-11-12 15:58:09 【问题描述】:

你可以将javascript中的数字四舍五入到小数点后1个字符(正确四舍五入)吗?

我尝试了 *10, round, /10 但它在 int 的末尾留下了两位小数。

【问题讨论】:

Math.round(n * 10) / 10 确实有效。你的代码是什么? 仅供参考developer.mozilla.org/en/JavaScript/Reference/Global_Objects/… 【参考方案1】:

Math.round(num * 10) / 10 有效,这是一个例子......

var number = 12.3456789
var rounded = Math.round(number * 10) / 10
// rounded is 12.3

如果你希望它有一位小数,即使它是 0,那么添加...

var fixed = rounded.toFixed(1)
// fixed is always to 1 d.p.
// NOTE: .toFixed() returns a string!

// To convert back to number format
parseFloat(number.toFixed(2))
// 12.34
// but that will not retain any trailing zeros

// So, just make sure it is the last step before output,
// and use a number format during calculations!

编辑:添加带精度函数的圆...

利用这个原理,作为参考,这里有一个方便的小圆函数,需要精度...

function round(value, precision) 
    var multiplier = Math.pow(10, precision || 0);
    return Math.round(value * multiplier) / multiplier;

...用法...

round(12345.6789, 2) // 12345.68
round(12345.6789, 1) // 12345.7

... 默认舍入到最接近的整数(精度为 0)...

round(12345.6789) // 12346

...可用于四舍五入到最接近的 10 或 100 等...

round(12345.6789, -1) // 12350
round(12345.6789, -2) // 12300

...以及正确处理负数...

round(-123.45, 1) // -123.4
round(123.45, 1) // 123.5

... 并且可以与 toFixed 结合以一致地格式化为字符串 ...

round(456.7, 2).toFixed(2) // "456.70"

【讨论】:

小心使用.toFixed(),因为当您可能需要一个数字时,它会返回一个字符串。 酷,显然使用parseFloat 将删除.toFixed() 留下的小数,如果它是一个整数(零)。一般来说,如果你想做数学,最好按照你的第一个例子。如果您想在 UI 中显示数字,请使用 .toFixed() 嗯...这是有道理的,任何转换为​​数字的方式都必须始终去掉错误的零,这就是为什么它必须保留一个字符串。我想它应该始终是显示前的最后一步,而不是用于计算。 小心使用.toFixed(),因为它可能会针对不同的浏览器返回不同的舍入结果。阅读this post 了解有关该主题的详细信息! 如果没有 DP,我可以加零吗?【参考方案2】:
var number = 123.456;

console.log(number.toFixed(1)); // should round to 123.5

【讨论】:

有时toFixed() 有故障 - 我在 Chrome 浏览器中看到它,我调用 toFixed(),然后转换为字符串,它显示类似 10.00000000068 的东西 - 很奇怪。虽然无法可靠地重现这一点。 是的,我用 toFixed() 计算了故障,即使只有几个小数。如果我没记错的话,它将分数 4 舍入到下一个更高的数字而不是更低的数字。 正如上面@cobby 所提到的:小心使用.toFixed(),因为当您可能需要Number 时,它会返回String【参考方案3】:

如果你使用Math.round(5.01),你会得到5而不是5.0

如果你使用toFixed,你会遇到roundingissues。

如果您想要两全其美,请将两者结合起来:

(Math.round(5.01 * 10) / 10).toFixed(1)

您可能想为此创建一个函数:

function roundedToFixed(input, digits)
  var rounded = Math.pow(10, digits);
  return (Math.round(input * rounded) / rounded).toFixed(digits);

【讨论】:

【参考方案4】:

lodash 有一个round 方法:

_.round(4.006);
// => 4

_.round(4.006, 2);
// => 4.01

_.round(4060, -2);
// => 4100

Docs.

Source.

【讨论】:

【参考方案5】:

我投票给toFixed(),但是,为了记录,这是另一种使用位移将数字转换为整数的方法。因此,它总是向零舍入(正数向下舍入,负数向上舍入)。

var rounded = ((num * 10) << 0) * 0.1;

但是,嘿,因为没有函数调用,所以速度很快。 :)

还有一个使用字符串匹配的:

var rounded = (num + '').replace(/(^.*?\d+)(\.\d)?.*/, '$1$2');

我不建议使用字符串变体,只是说。

【讨论】:

【参考方案6】:

试试这个:

var original=28.453

// 1.- round "original" to two decimals
var result = Math.round (original * 100) / 100  //returns 28.45

// 2.- round "original" to 1 decimal
var result = Math.round (original * 10) / 10  //returns 28.5

// 3.- round 8.111111 to 3 decimals
var result = Math.round (8.111111 * 1000) / 1000  //returns 8.111

不太复杂,更容易实现...

有了这个,你可以创建一个函数来做:

function RoundAndFix (n, d) 
    var m = Math.pow (10, d);
    return Math.round (n * m) / m;

function RoundAndFix (n, d) 
    var m = Math.pow (10, d);
    return Math.round (n * m) / m;

console.log (RoundAndFix(8.111111, 3));

编辑:见How to round using ROUND HALF UP. Rounding mode that most of us were taught in grade school

【讨论】:

不:RoundAndFix(1.005, 2) .【参考方案7】:

为什么不直接

let myNumber = 213.27321;
+myNumber.toFixed(1); // => 213.3
    toFixed: 使用定点表示法返回表示给定数字的字符串。 Unary plus (+):一元加号运算符在其操作数之前并计算其操作数,但如果尚未转换为数字,则尝试将其转换为数字。

【讨论】:

【参考方案8】:

使用 toPrecision 方法:

var a = 1.2345
a.toPrecision(2)

// result "1.2"

【讨论】:

但你必须小心,因为12.345.toPrecision( 2 )"12"【参考方案9】:

您可以简单地执行以下操作:

let n = 1.25
let result = Number(n).toFixed(1)
// output string: 1.3

【讨论】:

【参考方案10】:
var num = 34.7654;

num = Math.round(num * 10) / 10;

console.log(num); // Logs: 34.8

【讨论】:

【参考方案11】:

完成最佳答案:

var round = function ( number, precision )

    precision = precision || 0;
    return parseFloat( parseFloat( number ).toFixed( precision ) );

输入参数编号可能“不”总是一个数字,在这种情况下 .toFixed 不存在。

【讨论】:

【参考方案12】:

一般来说,小数舍入是通过缩放来完成的:round(num * p) / p

简单实现

使用以下带有中间数字的函数,您将获得预期的上舍入值,或者有时取决于输入的下舍入值。

inconsistency 舍入可能会在客户端代码中引入难以检测的错误。

function naiveRound(num, decimalPlaces) 
    var p = Math.pow(10, decimalPlaces);
    return Math.round(num * p) / p;


console.log( naiveRound(1.245, 2) );  // 1.25 correct (rounded as expected)
console.log( naiveRound(1.255, 2) );  // 1.25 incorrect (should be 1.26)

更好的实现

通过将数字转换为 指数表示法 中的字符串,正数按预期四舍五入。 但是,请注意,负数与正数的舍入方式不同。

事实上,它执行的规则基本上等同于"round half up",您会看到round(-1.005, 2) 的计算结果为-1,即使round(1.005, 2) 的计算结果为1.01。 lodash _.round 方法使用了这种技术。

/**
 * Round half up ('round half towards positive infinity')
 * Uses exponential notation to avoid floating-point issues.
 * Negative numbers round differently than positive numbers.
 */
function round(num, decimalPlaces) 
    num = Math.round(num + "e" + decimalPlaces);
    return Number(num + "e" + -decimalPlaces);


// test rounding of half
console.log( round(0.5, 0) );  // 1
console.log( round(-0.5, 0) ); // 0

// testing edge cases
console.log( round(1.005, 2) );   // 1.01
console.log( round(2.175, 2) );   // 2.18
console.log( round(5.015, 2) );   // 5.02

console.log( round(-1.005, 2) );  // -1
console.log( round(-2.175, 2) );  // -2.17
console.log( round(-5.015, 2) );  // -5.01

如果您希望在舍入负数时保持通常的行为,则需要在调用 Math.round() 之前将负数转换为正数,然后在返回之前将它们转换回负数。

// Round half away from zero
function round(num, decimalPlaces) 
    num = Math.round(Math.abs(num) + "e" + decimalPlaces) * Math.sign(num);
    return Number(num + "e" + -decimalPlaces);

有一种不同的纯数学技术来执行舍入到最近(使用"round half away from zero"),其中在调用舍入函数之前应用epsilon 校正

简单地说,我们在四舍五入之前将可能的最小浮点值(= 1.0 ulp;最后一个单位)添加到数字中。这将移动到数字之后的下一个可表示值,远离零。

/**
 * Round half away from zero ('commercial' rounding)
 * Uses correction to offset floating-point inaccuracies.
 * Works symmetrically for positive and negative numbers.
 */
function round(num, decimalPlaces) 
    var p = Math.pow(10, decimalPlaces);
    var e = Number.EPSILON * num * p;
    return Math.round((num * p) + e) / p;


// test rounding of half
console.log( round(0.5, 0) );  // 1
console.log( round(-0.5, 0) ); // -1

// testing edge cases
console.log( round(1.005, 2) );  // 1.01
console.log( round(2.175, 2) );  // 2.18
console.log( round(5.015, 2) );  // 5.02

console.log( round(-1.005, 2) ); // -1.01
console.log( round(-2.175, 2) ); // -2.18
console.log( round(-5.015, 2) ); // -5.02

这是为了抵消在十进制数编码期间可能出现的隐式round-off error,尤其是在最后一个小数位具有“5”的数字,例如 1.005、2.675 和 16.235。实际上,十进制的1.005被编码为64位二进制浮点的1.0049999999999999;而十进制的1234567.005 编码为64 位二进制浮点数的1234567.0049999998882413

值得注意的是,最大二进制 round-off error 取决于 (1) 数字的大小和 (2) 相对机器 epsilon (2^-52)。

【讨论】:

【参考方案13】:

已接受答案的 ES 6 版本:

function round(value, precision) 
    const multiplier = 10 ** (precision || 0);
    return Math.round(value * multiplier) / multiplier;

【讨论】:

【参考方案14】:

如果您的方法不起作用,请发布您的代码。

但是,您可以通过以下方式完成四舍五入任务:

var value = Math.round(234.567*100)/100

会给你 234.56

同样

 var value = Math.round(234.567*10)/10

会给234.5

通过这种方式,您可以使用变量代替上面使用的常量。

【讨论】:

【参考方案15】:

我做了一个返回数字类型并且仅在需要时才放置小数(没有 0 填充)。

例子:

roundWithMaxPrecision(11.234, 2); //11.23
roundWithMaxPrecision(11.234, 1); //11.2
roundWithMaxPrecision(11.234, 4); //11.23
roundWithMaxPrecision(11.234, -1); //10

roundWithMaxPrecision(4.2, 2); //4.2
roundWithMaxPrecision(4.88, 1); //4.9

代码:

function roundWithMaxPrecision (n, precision) 
    const precisionWithPow10 = Math.pow(10, precision);
    return Math.round(n * precisionWithPow10) / precisionWithPow10;

【讨论】:

不是最佳的。您使用相同的参数计算 pow() 两次。【参考方案16】:

小角度过滤器,如果有人想要的话:

angular.module('filters').filter('decimalPlace', function() 
    return function(num, precision) 
        var multiplier = Math.pow(10, precision || 0);
        return Math.round(num * multiplier) / multiplier;
    ;
);

使用如果通过:

model.value| decimalPlace
model.value| decimalPlace:1
model.value| decimalPlace:2

:)

【讨论】:

【参考方案17】:

这似乎在我扔给它的任何东西上都能可靠地工作:

function round(val, multiplesOf) 
  var s = 1 / multiplesOf;
  var res = Math.ceil(val*s)/s;
  res = res < val ? res + multiplesOf: res;
  var afterZero = multiplesOf.toString().split(".")[1];
  return parseFloat(res.toFixed(afterZero ? afterZero.length : 0));

它是四舍五入的,因此您可能需要根据用例对其进行修改。这应该有效:

console.log(round(10.01, 1)); //outputs 11
console.log(round(10.01, 0.1)); //outputs 10.1

【讨论】:

【参考方案18】:

如果您关心正确的四舍五入,那么:

function roundNumericStrings(str , numOfDecPlacesRequired) 
     var roundFactor = Math.pow(10, numOfDecPlacesRequired);  
     return (Math.round(parseFloat(str)*roundFactor)/roundFactor).toString();  

否则,如果您不这样做,那么您已经收到了以前帖子的回复

str.slice(0, -1)

【讨论】:

【参考方案19】:

Math.round( num * 10) / 10 不起作用。

例如,1455581777.8-145558160.4 为您提供1310023617.3999999

所以只能使用num.toFixed(1)

【讨论】:

【参考方案20】:

我找到了避免精度问题的方法:

function badRound (num, precision) 
    const x = 10 ** precision;
    return Math.round(num * x) / x

// badRound(1.005, 2) --> 1

function round (num, precision) 
    const x = 10 ** (precision + 1);
    const y = 10 ** precision;
    return Math.round(Math.round(num * x) / 10) / y

// round(1.005, 2) --> 1.01

【讨论】:

【参考方案21】:
Math.round( mul/count * 10 ) / 10

Math.round(Math.sqrt(sqD/y) * 10 ) / 10

谢谢

【讨论】:

【参考方案22】:
function rnd(v,n=2) 
    return Math.round((v+Number.EPSILON)*Math.pow(10,n))/Math.pow(10,n)

这个很好地抓住了角落里的情况

【讨论】:

【参考方案23】:

如果你的源代码是打字稿,你可以使用这样的函数:

public static ToFixedRounded(decimalNumber: number, fractionDigits: number): number 
    var rounded = Math.pow(10, fractionDigits);
    return (Math.round(decimalNumber * rounded) / rounded).toFixed(fractionDigits) as unknown as number;

【讨论】:

以上是关于你如何在Javascript中四舍五入到小数点后一位?的主要内容,如果未能解决你的问题,请参考以下文章

C#中如何保留小数点后一位

将双精度数舍入到小数点后一位(去掉小数位)

PTA乙级 (1012 数字分类 (20分),四舍五入小数点后一位)

C++编程如何保留小数点后6位 求高手精解.....这里提前表示感谢了!!!

怎么对Float小数点后一位四舍五入,并且取绝对值

从值中减去百分比