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

IT技术 javascript types rounding
2021-01-29 12:47:53

我在这里错过了什么吗?

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

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

我想将数字四舍五入为 2 个十进制数字。

6个回答

Number.prototype.toFixed是一种用于在打印之前格式化数字的函数它来自toString,toExponential的家庭toPrecision

要舍入一个数字,您可以这样做:

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

.

或者,如果你想要一个“类似原生”的函数,你可以扩展原型:

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";

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

结果someNumber = Math.round( 42.008 * 1e2 ) / 1e2;不是42.01,是~42.0099999999999980原因:该数字42.01不存在并四舍五入到最接近的现有数字。顺便说一句,证明编号通过toPrecision(18)打印所有相关数字。
2021-03-24 12:47:53
@HammerNL 尽管 Sam 坚信,但它实际上并没有做任何事情:) 这只是一种练习——它使 IDE 将此函数识别为type Number. 问题是+(anyValue)总是返回一个数字 - 例如。+("45")返回45+(new Number(42))返回42这有点像强类型函数。如果你养成了它的习惯,你可以避免很多错误:)
2021-04-01 12:47:53
很好的答案!但是......我已经使用 JavaScript 大约 20 年了,但我不明白你为什么在返回值周围使用 +(...) 构造?感谢@sam 的磨练:) 因为我永远不会太老而无法学习,请详细说明:-)
2021-04-04 12:47:53
我认为这是最好的答案。它避免了类型转换。很棒的酱!
2021-04-09 12:47:53
为什么这没有融入核心 javascript :s
2021-04-11 12:47:53

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

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

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

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

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

someNumber = someNumber.toFixed(2)

...到这个:

someNumber = +someNumber.toFixed(2);

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

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

为什么不使用parseFloat

var someNumber = 123.456;
someNumber = parseFloat(someNumber.toFixed(2));
alert(typeof(someNumber));
//alerts number
或者简单地用 + 符号代替 parseFloat() 来转换为数字。
2021-04-09 12:47:53

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

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