如何在 JavaScript 中舍入一个数字? .toFixed() 返回一个字符串?

Posted

技术标签:

【中文标题】如何在 JavaScript 中舍入一个数字? .toFixed() 返回一个字符串?【英文标题】:How can I round a number in JavaScript? .toFixed() returns a string? 【发布时间】:2011-01-18 00:29:54 【问题描述】:

我错过了什么吗?

var someNumber = 123.456;
someNumber = someNumber.toFixed(2);
alert(typeof(someNumber));
//alerts string

为什么.toFixed()返回一个字符串?

我想将数字四舍五入为 2 位小数。

【问题讨论】:

因为它被设计成返回一个字符串? 对我来说这似乎很奇怪。 .toFixed() 只对数字起作用……对吧? 我了解 Math.round() 可以按预期工作。我只是在询问为什么对数字进行操作的函数会返回一个字符串... 生活在 2017 年的人们应该使用像 lodash.com/docs/4.17.4#ceil 这样的库 _也是如此。数数?还没有升级到他的兄弟。 【参考方案1】:

当然它返回一个字符串。如果您想对数值变量进行四舍五入,请改用 Math.round()。 toFixed 的重点是将数字格式化为固定小数位数以显示给用户

【讨论】:

【参考方案2】:

当它应该格式化一个数字时,你希望它返回什么?如果你有一个数字,你几乎不能用它做任何事情,因为例如2 == 2.0 == 2.00 等,所以它必须是一个字符串。

【讨论】:

【参考方案3】:

因为它的主要用途是显示数字?如果要对数字进行四舍五入,请使用带有适当因数的Math.round()

【讨论】:

但它显示的是 NUMBERS 所以它不应该返回一个“数字”吗? @Derek:只是因为'42' 是一个数字......它不是。仅仅因为一个字符串恰好包含数字并不能使它成为一个数字。这不是 php。 :-P 哈哈。它不是包含数字的字符串......它是传递给方法的数字。该方法接受一个数字并返回一个字符串。 @DerekAdair 对,但浏览器无法显示数字,它显示字符串,因此转换。【参考方案4】:

它返回一个字符串,因为 0.1 及其幂(用于显示小数)在二进制浮点系统中不可表示(至少不能完全准确)。

例如,0.1 真的是 0.1000000000000000055511151231257827021181583404541015625,而 0.01 真的是 0.01000000000000000020816681711721686712940859378 (感谢BigDecimal 证明了我的观点。:-P)

因此(没有十进制浮点或有理数类型),将其作为字符串输出是使其精确到显示所需精度的唯一方法。

【讨论】:

至少 javascript 可以为我节省一些手指工作并将其转换回一个数字...嘘... @Derek:是的,但是一旦将其转换回数字,您就会再次遇到同样的不准确问题。 :-P JS 没有十进制浮点数或有理数。 @DerekAdair 我最近写了一篇文章,进一步解释了这一点,你可能会感兴趣。享受吧! ***.com/a/27030789/13 实际上,这让我对这个主题做了一些相当深入的研究!感谢您的所有帮助! 您的回答有点误导:toFixed 是一个格式化函数,其唯一目的是将数字转换为字符串,并使用指定的小数位数对其进行格式化。它返回一个字符串的原因是因为它应该返回一个字符串,如果它被命名为toStringFixed,OP 不会对结果感到惊讶。这里唯一的问题是 OP 希望它像 Math.round 一样工作,而无需咨询 JS 参考。【参考方案5】:

我通过改变这个解决了这个问题:

someNumber = someNumber.toFixed(2)

...到这个:

someNumber = +someNumber.toFixed(2);

但是这会将数字转换为字符串并再次对其进行解析,这将对性能产生重大影响。如果您关心性能或类型安全,请同时查看其他答案。

【讨论】:

不,不,不,不,不! 不要那样做!数字到字符串的转换只是为了舍入它是一个非常糟糕的做法!而是做someNumber = Math.round(someNumber * 1e2) / 1e2!请参阅我的答案以获得更通用的方式。 @jczaplew 因为如果你这样做,32 位二进制数将被转换成一个字符串,每个该死的十进制 digit 使用 16 位! (顺便说一下,在 UTF-16 中存储数字并不是最方便的事情。)然后字符串被转换回 32 位浮点数。一个个数字。 (如果我忽略了在选择正确的解析算法之前必须完成的所有测试。)考虑到您可以在浮点数上使用 3 个快速操作来完成,所有这些都是徒劳的。 @m93a 所以这是出于性能原因?这实际上对性能有显着影响吗? @jczaplew,因为字符串(1)实际上很慢,(2)理论上不正确。 Math.round(someNumber * 1e2) / 1e2 很容易记住。 JavaScript 太有趣了???【参考方案6】:

我通过使用 JavaScript 的 Number() 函数将其转换回数字来解决它

var x = 2.2873424;
x = Number(x.toFixed(2));

【讨论】:

【参考方案7】:

Number.prototype.toFixed 是一个用于在打印出来之前格式化数字的函数。它来自toStringtoExponentialtoPrecision 家族。

要对数字进行四舍五入,您可以这样做:

someNumber = 42.008;
someNumber = Math.round( someNumber * 1e2 ) / 1e2;
someNumber === 42.01;

// if you need 3 digits, replace 1e2 with 1e3 etc.
// or just copypaste this function to your code:

function toFixedNumber(num, digits, base)
  var pow = Math.pow(base||10, digits);
  return Math.round(num*pow) / pow;

.

或者如果你想要一个“native-like”的功能,你可以扩展原型:

Number.prototype.toFixedNumber = function(digits, base)
  var pow = Math.pow(base||10, digits);
  return Math.round(this*pow) / pow;

someNumber = 42.008;
someNumber = someNumber.toFixedNumber(2);
someNumber === 42.01;


//or even hexadecimal

someNumber = 0xAF309/256  //which is af3.09
someNumber = someNumber.toFixedNumber(1, 16);
someNumber.toString(16) === "af3.1";

然而,请记住,在编写模块时污染原型被认为是不好的,因为模块不应该有任何副作用。所以,对于一个模块,使用第一个函数

【讨论】:

我认为这是最好的答案。它避免了类型转换。太棒了! 很好的答案!但是......我已经做了 20 年左右的 JavaScript,但我不明白你为什么在返回值周围使用 +(...) 构造?感谢@sam 把它揉进去:) 因为我从来没有老到不能学习,请详细说明:-) @HammerNL 尽管 Sam 坚信这一点,但它实际上并没有做任何事情 :) 这只是一种实践——它使 IDE 将这个函数识别为type Number。问题是+(anyValue) 总是返回一个数字——例如。 +("45") 返回 45+(new Number(42)) 返回 42。这有点像函数的强类型。如果你养成它的习惯,你可以避免很多错误:) 为什么这没有融入核心 javascript :s someNumber = Math.round( 42.008 * 1e2 ) / 1e2; 的结果不是42.01,而是~42.0099999999999980。原因:数字42.01 不存在,四舍五入到最接近的现有数字。顺便说一句,toPrecision(18) 的证明编号用所有相关数字打印出来。【参考方案8】:

为什么不使用parseFloat

var someNumber = 123.456;
someNumber = parseFloat(someNumber.toFixed(2));
alert(typeof(someNumber));
//alerts number

【讨论】:

或者简单地用 + 号代替 parseFloat() 来转换成数字。【参考方案9】:

您可以简单地使用“+”将结果转换为数字。

var x = 22.032423;
x = +x.toFixed(2); // x = 22.03

【讨论】:

【参考方案10】:

这是答案m93a 提供的功能稍强的版本。

const toFixedNumber = (toFixTo = 2, base = 10) => num => 
  const pow = Math.pow(base, toFixTo)
  return +(Math.round(num * pow) / pow)


const oneNumber = 10.12323223

const result1 = toFixedNumber(2)(oneNumber) // 10.12
const result2 = toFixedNumber(3)(oneNumber) // 10.123

// or using pipeline-operator
const result3 = oneNumber |> toFixedNumber(2) // 10.12

【讨论】:

这是一个方便的功能,对于未定义的类型它不起作用,我已经为这种情况添加了代码; if (num !== undefined) return +(Math.round(num * pow) / pow) else return 0; 【参考方案11】:

提供一个为什么它必须是字符串的例子:

如果你格式化 1.toFixed(2) 你会得到 '1.00'。

这与 1 不同,因为 1 没有 2 个小数。


我知道 JavaScript 并不完全是一种 性能 语言,但如果您使用以下内容,您可能会在舍入时获得更好的性能: roundedValue = Math.round(value * 100) * 0.01

【讨论】:

【参考方案12】:

对于像我这样遇到这个非常古老的问题的人来说,一个现代的解决方案:

const roundValue = (num, decimals = 2) => 
    let scaling = 10 ** decimals;
    return Math.round((num + Number.EPSILON) * scaling) / scaling;

参考:https://***.com/a/11832950

【讨论】:

【参考方案13】:

回答可能为时已晚,但您可以将输出与 1 相乘以再次转换为数字,这是一个示例。

const x1 = 1211.1212121;
const x2 = x1.toFixed(2)*1;
console.log(typeof(x2));

【讨论】:

【参考方案14】:

你应该像下面这样使用它。

var someNumber: number = 0.000000;
someNumber = Number(someNumber.toFixed(2))

【讨论】:

【参考方案15】:

为什么不将结果 * 1 即

someNumber.toFixed(2) * 1

【讨论】:

以上是关于如何在 JavaScript 中舍入一个数字? .toFixed() 返回一个字符串?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 PL-SQL 中舍入数字?

如何在 R 中舍入包含一些字符变量的 data.frame?

在 Python 中舍入到给定的数字

如何在PHP中舍入浮点数?

在 SQL 中舍入平均值时如何检索小数

如何在 extjs4.1 中舍入浮点值