从数字中删除不重要的尾随零?

266

我是否错过了一个标准的API调用,可以将数字末尾无关的零去掉?

var x = 1.234000; // to become 1.234
var y = 1.234001; // stays 1.234001

Number.toFixed()Number.toPrecision()并不完全符合我的需求。


6
嗯,1.234000 === 1.234的意思是“1.234000等于1.234”。 - Gumbo
5
如果您执行alert(x),它会弹出没有尾随零的值。 - JKirchartz
78
经过与多个客户的合作,我可以证明即使 1.234000 === 1.234,如果没有必要,客户也不想看到那些多余的零。 - contactmatt
32
使用 parseFloat(n) ? - Mr. Alien
我的问题是:前导零无关紧要吗?从数学角度来看,1.2300表示:小数点后面的4位数字是精确的。而1.23表示:只有2位数字是精确的,可能会四舍五入。例如:比较12m和12.00m。 - Wiimm
显示剩余2条评论
24个回答

371

我曾经遇到过类似的情况,想在需要时使用.toFixed(),但是当不需要填充时就不想要。所以最终我使用parseFloat与toFixed结合使用。

不填充的toFixed

parseFloat(n.toFixed(4));

另一个选项几乎可以做相同的事情
这个答案可能有助于您的决定

Number(n.toFixed(4));

toFixed 方法将数字四舍五入或填充到指定长度,并将其转换为字符串。将其转换回数值类型不仅可以使数字在算术运算中更安全,而且还会自动删除任何尾随的零。例如:

var n = "1.234000";
    n = parseFloat(n);
 // n is 1.234 and in number form

因为即使你在数字后面加上尾随的零,它们也会被省略。

var n = 1.23000;
 // n == 1.23;

2
请注意,仅当小数位数等于或大于 toFixed 参数时,此方法才有效。例如,如果数字为 1.200000,则 toFixed(3) 的结果将为 1.200,因此不会删除所有尾随零。 - Leopoldo Sanczyk
@LeopoldoSanczyk 不,只有在使用toFixed时才是这样,因为它返回一个字符串。数字类型会自动丢失尾随零。这就是为什么我同时使用这两个的原因。 - Gary
@Gary,我撤回我的评论,我看到了 parseFloat(n).toFixed(4); 而不是你实际的答案。对不起。 - Leopoldo Sanczyk
4
为什么不用 +(n.toFixed(4)) - Константин Ван
9
点赞了!您的回答只有一个问题,就是0.00000005被转换为5e-8,我如何去除末尾的无意义零而不出现这个问题?我正在处理像0.000058000这样的小数,需要去除末尾多余的零。 - PirateApp
显示剩余3条评论

184

如果将其转换为字符串,它将不会显示任何尾随的零,因为这些零并没有在变量中存储,最初它作为一个数字创建而不是字符串。

var n = 1.245000
var noZeroes = n.toString() // "1.245" 

6
我本打算发布一些代码来去除零,但Daniel的解决方案似乎可行。它甚至可以用于像"1.2345000"这样的字符串。("1.2345000" * 1).toString(); // 变成了1.2345 - Steven
8
当然,如果你的变量已经是一个字符串,你需要先将它转换为数字,然后再转回字符串。 - derekcohen
16
这不是完整的解决方案。当您的变量存在某些浮点表示误差时,它将无法工作,例如: var n = 1.245000000000001(假设这对用户来说不重要) - augur
11
可能会对像这样的数字产生意想不到的结果:1231111111111111111111111111111222222222222222222222222222222222222222222222222222.00。其字符串表示将采用指数格式:1.231111111111111e+81 - Stas Makutin
3
我需要重新查看并修订自己下面的答案。这个答案可以解决问题,但不能解决提问者给出的第二种情况,即(1.234001).toString()仍然会产生"1.234001"的结果。可以使用以下一行代码来解决问题:(new Intl.NumberFormat('en-US', { style: 'decimal', minimumFractionDigits: 2, maximumFractionDigits: 2 })).format(1.234001) - dperish
显示剩余5条评论

58

我最初使用了 matti-lyra 和 gary 的答案的组合:

r=(+n).toFixed(4).replace(/\.0+$/,'')

结果:

  • 1234870.98762341: "1234870.9876"
  • 1230009100: "1230009100"
  • 0.0012234: "0.0012"
  • 0.1200234: "0.12"
  • 0.000001231: "0"
  • 0.10001: "0.1000"
  • "asdf": "NaN" (所以没有运行时错误)

略有问题的情况是0.10001。我最终使用了这个较长的版本:

    r = (+n).toFixed(4);
    if (r.match(/\./)) {
      r = r.replace(/\.?0+$/, '');
    }
  • 1234870.98762341: "1234870.9876"
  • 1230009100: "1230009100"
  • 0.0012234: "0.0012"
  • 0.1200234: "0.12"
  • 0.000001231: "0"
  • 0.10001: "0.1"
  • "asdf": "NaN" (so no runtime error)
r=(+n).toFixed(4).replace(/([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/,'$1')

这将得到与上面相同的结果。


1
我有一个纯正的正则表达式解决方案,我相信它可以工作 toFixed(4).replace(/([0-9]+(\.[1-9]+)?)(\.?0+$)/,"$1") - Gary
1
糟糕!显然我自己无法像其他人那样很好地打破我的正则表达式。我不会让这打败我!我已经对所有您的测试用例以及我能想到的任何(有效的)测试用例运行了此正则表达式:([0-9]+(\.[0-9]+[1-9])?)(\.?0+$) - Gary
2
正则表达式太贪婪了,有时会从整数部分中删除“0”! :-( 为什么不只是使用 replace(/[,.][1-9]+(0+)/,'') - Sebastian Sebald
2
被低估的答案。 - Charlie
4
Gary的正则表达式对于1230009100无法匹配成功,使用replace(/\.0*$|(\.\d*[1-9])0+$/, '$1')或者João Costa提供的正则表达式。参见https://regex101.com/r/KmsEFd/1 - geekley
显示剩余11条评论

40

toFixed方法会在必要时进行适当的四舍五入。它还会添加尾随零,这并不总是理想的。

(4.55555).toFixed(2);
//-> "4.56"

(4).toFixed(2);
//-> "4.00"

如果您将返回值转换为数字,那些末尾的零将被删除。 这比进行自己的四舍五入或截断数学运算更简单。

+(4.55555).toFixed(2);
//-> 4.56

+(4).toFixed(2);
//-> 4

1
有点棘手,但正是我一直在寻找的:去除显著的尾随零(当然,我们通过toFixed调用使它们显著)。 这是一个奇怪的UX边缘情况。 - worc

35

这样就直接乘以1,怎么样?

var x = 1.234000*1; // becomes 1.234

var y = 1.234001*1; // stays as 1.234001

2
天才之举... - messerbill
1
它什么都不做!你只是在代码中多输入了几个零,无论你是否乘以1,x都将是1.234。 - undefined
它什么都不做!你只是在代码中多输入了几个零,无论你是否乘以1,x都将是1.234。 - Salman A

19

我有基本相同的需求,但发现没有内置机制来实现此功能。

除了修剪尾数零之外,我还需要将输出四舍五入并格式化为用户当前地区的格式(即123,456.789)。

我在GitHub上包含所有这方面的工作,名为prettyFloat.js(MIT许可证):https://github.com/dperish/prettyFloat.js


用法示例:

prettyFloat(1.111001, 3) // "1.111"
prettyFloat(1.111001, 4) // "1.111"
prettyFloat(1.1111001, 5) // "1.1111"
prettyFloat(1234.5678, 2) // "1234.57"
prettyFloat(1234.5678, 2, true) // "1,234.57" (en-us)

更新 - 2018年8月


所有现代浏览器现在都支持 ECMAScript 国际化 API,它提供了语言敏感的字符串比较、数字格式化以及日期和时间格式化。


const formatters = {
    default: new Intl.NumberFormat(),
    currency: new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', minimumFractionDigits: 0, maximumFractionDigits: 0 }),
    whole: new Intl.NumberFormat('en-US', { style: 'decimal', minimumFractionDigits: 0, maximumFractionDigits: 0 }),
    oneDecimal: new Intl.NumberFormat('en-US', { style: 'decimal', minimumFractionDigits: 1, maximumFractionDigits: 1 }),
    twoDecimal: new Intl.NumberFormat('en-US', { style: 'decimal', minimumFractionDigits: 2, maximumFractionDigits: 2 })
};

formatters.twoDecimal.format(1234.5678);  // result: "1,234.57"
formatters.currency.format(28761232.291); // result: "$28,761,232"

对于旧版浏览器,您可以使用这个填充程序:https://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.en


这就是我们要寻找的东西。你必须创建一个npm包。 - Enzo
所以我应该更新一下,因为现在可以通过国际化 API 实现这个功能。 - dperish
2
这非常有帮助,谢谢分享并感谢更新。 - jaggedsoft
1
请注意:maximumFractionDigits 的限制为20。 - Lonnie Best

16

纯正则表达式答案

n.replace(/(\.[0-9]*[1-9])0+$|\.0*$/,'$1');
我想知道为什么没有人给了一个!

我想知道为什么没有人给了一个!


它不能处理数字(数字在原问题中已经说明)。不过我喜欢字符串表示的解决方案! - BennyHilarious
1
n.replace(/([.,][0-9][1-9])0+$|[.,]0$/, '$1') 如果你想让它也适用于逗号。 - Simon

15

你可以尝试这个来减小浮点数的大小

var n = 0.0000;
n = parseFloat(n.toString()); 

//output n = 0; 
// n = 3.14000; --> n = 3.14;

9

如果你使用toFixed(n)其中n > 0,那么一个更简单、更稳定(不需要浮点数操作)的解决方案是:

(+n).toFixed(2).replace(/(\.0+|0+)$/, '')

// 0 => 0
// 0.1234 => 0.12
// 0.1001 => 0.1

// 1 => 1
// 1.1234 => 1.12
// 1.1001 => 1.1

// 100 => 100
// 100.1234 => 100.12
// 100.1001 => 100.1

备注:如果您使用 toFixed(0),则无需使用 replace


1
.replace(/(\.0+|0+)$/, '') 对于 toFixed() 方法的默认值 digits 参数存在缺陷,该参数的默认值为 0。例如,(+'10').toFixed().replace(/(\.0+|0+)$/, '')(+'10').toFixed(0).replace(/(\.0+|0+)$/, '') 返回的结果是 1 而不是 10。 - T.V.
如果您使用 toFixed(0),则根本不需要进行替换,也不会浪费 CPU。 - shawn
我不是指像这样硬编码零。 - T.V.
基本上您建议插入额外的 if else 来检查 n 是否为 0,以处理 n 不是硬编码的情况。 - T.V.
现在你在同一个答案中使用相同的“n”表示两个不同的含义,这会让人们感到困惑 :) 如果您不接受编辑,我将被迫将其发布为单独的答案,这对于SO来说并不是最佳实践,但我能做什么。 - T.V.
显示剩余3条评论

7
使用parseFloat()对我很有帮助。我在这里想了半天,不知道为什么要用那些复杂的解决方案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接