从数字中删除无关紧要的尾随零?

Ste*_*ven 139 javascript regex math numbers

我是否错过了一个标准的API调用,可以从一个数字中删除尾随无效的零?

防爆.

var x = 1.234000 // to become 1.234;
var y = 1.234001; // stays 1.234001
Run Code Online (Sandbox Code Playgroud)

Number.toFixed()和Number.toPrecision()并不是我想要的.

Gar*_*ary 202

我有一个类似的实例,我想.toFixed()在必要时使用,但我不想要填充它不是.所以我最终将parseFloat与toFixed结合使用.

toFixed没有填充

parseFloat(n.toFixed(4));
Run Code Online (Sandbox Code Playgroud)

另一个做同样事情的选择
这个答案可能有助于你的决定

Number(n.toFixed(4));
Run Code Online (Sandbox Code Playgroud)

toFixed将数字舍入/填充到特定长度,但也将其转换为字符串.将其转换回数字类型不仅可以使数字更安全地使用算术,还可以自动删除任何尾随0.例如:

var n = "1.234000";
    n = parseFloat(n);
 // n is 1.234 and in number form
Run Code Online (Sandbox Code Playgroud)

因为即使你定义一个尾随零的数字,它们也会被删除.

var n = 1.23000;
 // n == 1.23;
Run Code Online (Sandbox Code Playgroud)

  • **为什么不是`+(n.toFixed(4))`?** (4认同)
  • 赞!您的答案只有一个问题0.00000005被转换为5e-8,如何在不出现此问题的情况下删除不重要的零,我正在处理小数,例如0.000058000,其中需要删除最后的零 (3认同)
  • 请注意,仅当相关小数位数等于或大于 toFixed 参数时,此方法才有效。例如,如果数字为 1.200000,则 toFixed(3) 的结果将为 1.200,因此不会删除所有尾随零。 (2认同)

Cri*_*hez 125

如果将它转换为字符串,它将不会显示任何尾随的零,因为它是作为数字而不是字符串创建的,所以它们不会首先存储在变量中.

var n = 1.245000
var noZeroes = n.toString() // "1.245" 
Run Code Online (Sandbox Code Playgroud)

  • 当然,如果你的var已经是一个字符串,你必须先将它转换为数字然后再转换回来 (7认同)
  • 这不是完整的解决方案.当你有一些浮点表示错误的变量时,它不起作用,如:`var n = 1.245000000000001`(假设它无法表示给用户) (7认同)
  • 我准备发布一些代码来删除零,但丹尼尔的解决方案似乎有效.它甚至适用于诸如"1.2345000"之类的字符串.("1.2345000"*1).toString(); //变成1.2345 (6认同)
  • 可能会产生意外的结果,如:1231111111111111111111111111111222222222222222222222222222222222222222222222222222.00.字符串表示形式为指数格式:1.231111111111111e + 81 (5认同)
  • 我自己不得不再次重新审视这个问题,并在下面偶然发现了我自己的答案。这个答案是一个很好的快速修复,但没有解决OP给出的第二种情况,其中`(1.234001).toString()`仍然产生`"1.234001"`。单行代码为: `(new Intl.NumberFormat('en-US', { style: 'decimal',minimumFractionDigits: 2, MaximumFractionDigits: 2 })).format(1.234001)` (3认同)

w00*_*00t 25

我首先使用了matti-lyra和gary的答案组合:

r=(+n).toFixed(4).replace(/\.0+$/,'')
Run Code Online (Sandbox Code Playgroud)

结果:

  • 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+$/, '');
    }
Run Code Online (Sandbox Code Playgroud)
  • 1234870.98762341:"1234870.9876"
  • 1230009100:"1230009100"
  • 0.0012234:"0.0012"
  • 0.1200234:"0.12"
  • 0.000001231:"0"
  • 0.10001:"0.1"
  • "asdf":"NaN"(所以没有运行时错误)

更新:这是加里的新版本(见评论):

r=(+n).toFixed(4).replace(/([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/,'$1')
Run Code Online (Sandbox Code Playgroud)

这给出了与上面相同的结果.

  • @w00t Gary 的正则表达式对于 1230009100 失败,请使用 `replace(/\.0*$|(\.\d*[1-9])0+$/, '$1')` 或来自 João Costa 的正则表达式。请参阅 https://regex101.com/r/KmsEFd/1 (4认同)
  • 正则表达式过于贪婪,有时会从整数部分删除“0”!:-( 为什么不直接替换(/[,.][1-9]+(0+)/,'')`? (2认同)
  • 被低估的回答这个。 (2认同)

小智 16

toFixed如有必要,该方法将进行适当的舍入.它还会添加尾随零,这并不总是理想的.

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

(4).toFixed(2);
//-> "4.00"
Run Code Online (Sandbox Code Playgroud)

如果将返回值强制转换为数字,那么将删除那些尾随零.这比进行自己的舍入或截断数学更简单.

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

+(4).toFixed(2);
//-> 4
Run Code Online (Sandbox Code Playgroud)


sha*_*awn 9

如果您使用toFixed(n)where 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
Run Code Online (Sandbox Code Playgroud)

PS:如果使用toFixed(0),则replace不需要。


dpe*_*ish 8

我有基本相同的要求,并且发现此功能没有内置的机制。

除了修整尾随的零,我还需要四舍五入并格式化用户当前语言环境的输出(即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)
Run Code Online (Sandbox Code Playgroud)

更新-2018年8月


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

let 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"
Run Code Online (Sandbox Code Playgroud)

对于较旧的浏览器,您可以使用以下polyfill:https ://cdn.polyfill.io/v2/polyfill.min.js ? features = Intl.~locale.en

  • 这非常有帮助,感谢您的分享,也感谢您的更新。 (2认同)

Cle*_*ria 8

使用 parseFloat() 为我解决了这个问题。我很困惑为什么要使用这些复杂的解决方案。


meg*_*ort 6

当Django在文本字段中显示Decimal类型值时,我也需要解决这个问题.例如,当'1'是值时.它会显示'1.00000000'.如果'1.23'是值,它将显示'1.23000000'(在'decimal_places'设置为8的情况下)

使用parseFloat对我来说不是一个选项,因为它可能不会返回完全相同的值.toFixed不是一个选项,因为我不想舍入任何东西,所以我创建了一个函数:

function removeTrailingZeros(value) {
    value = value.toString();

    # if not containing a dot, we do not need to do anything
    if (value.indexOf('.') === -1) {
        return value;
    }

    # as long as the last character is a 0 or a dot, remove it
    while((value.slice(-1) === '0' || value.slice(-1) === '.') && value.indexOf('.') !== -1) {
        value = value.substr(0, value.length - 1);
    }
    return value;
}
Run Code Online (Sandbox Code Playgroud)


小智 6

纯正则表达式答案

n.replace(/(\.[0-9]*[1-9])0+$|\.0*$/,'$1');
Run Code Online (Sandbox Code Playgroud)

我不知道为什么没人给!


小智 5

这样乘以一个怎么样?

var x = 1.234000*1; // becomes 1.234

var y = 1.234001*1; // stays as 1.234001
Run Code Online (Sandbox Code Playgroud)

  • 天才之举.... (2认同)

小智 5

您可以尝试使用此方法来最小化浮点数

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

//output n = 0; 
// n = 3.14000; --> n = 3.14;
Run Code Online (Sandbox Code Playgroud)


T.V*_*.V. 5

如果我们有s数字的某种字符串表示形式,例如可以使用.toFixed(digits) Number 方法(或通过任何其他方式)获得,那么为了从字符串中删除无关紧要的尾随零,s我们可以使用:

s.replace(/(\.0*|(?<=(\..*))0*)$/, '')

/**********************************
 * Results for various values of s:
 **********************************
 *
 * "0" => 0
 * "0.000" => 0
 * 
 * "10" => 10
 * "100" => 100
 * 
 * "0.100" => 0.1
 * "0.010" => 0.01
 * 
 * "1.101" => 1.101
 * "1.100" => 1.1
 * "1.100010" => 1.10001
 * 
 * "100.11" => 100.11
 * "100.10" => 100.1
 */

Run Code Online (Sandbox Code Playgroud)

上面使用的正则表达式replace()解释如下

  • 首先请注意正则|表达式中的运算符,它代表“OR”,因此,该方法将从两种可能的子字符串replace()中删除,要么由部分匹配,要么由部分匹配。s(\.0*)$((?<=(\..*))0*)$
  • 正则表达式的部分(\.0*)$匹配一个点符号,后跟所有零,直到s. 例如,这可能是0.0(.0匹配并删除)、1.0(.0匹配并删除)、0.000(.000匹配并删除) 或点后带有所有零的任何类似字符串,因此,所有尾随零和点本身都将被删除如果正则表达式的这一部分匹配。
  • ((?<=(\..*))0*)$部分仅匹配尾随零(位于点符号之后,后跟连续尾随零开始之前的任意数量的任何符号)。例如,这可能是0.100(尾随00被匹配并删除),0.010(最后一个0被匹配和删除,请注意,0.01由于“正向后行断言”,该部分根本没有匹配,即(?<=(\..*)),它位于正0*则表达式这一部分的前面)、1.100010(最后一个0被匹配并删除)等。
  • 如果表达式的两个部分都不匹配,则不会删除任何内容。例如,这可能是100100.11等。因此,如果输入没有任何尾随零,则它保持不变。

更多使用示例.toFixed(digits)(下面的示例中使用了文字值“1000.1010”,但我们可以假设变量):

let digits = 0; // Get `digits` from somewhere, for example: user input, some sort of config, etc.

(+"1000.1010").toFixed(digits).replace(/(\.0*|(?<=(\..*))0*)$/, '');
// Result: '1000'

(+"1000.1010").toFixed(digits = 1).replace(/(\.0*|(?<=(\..*))0*)$/, '');
// Result: '1000.1'


(+"1000.1010").toFixed(digits = 2).replace(/(\.0*|(?<=(\..*))0*)$/, '');
// Result: '1000.1'


(+"1000.1010").toFixed(digits = 3).replace(/(\.0*|(?<=(\..*))0*)$/, '');
// Result: '1000.101'


(+"1000.1010").toFixed(digits = 4).replace(/(\.0*|(?<=(\..*))0*)$/, '');
// Result: '1000.101'


(+"1000.1010").toFixed(digits = 5).replace(/(\.0*|(?<=(\..*))0*)$/, '');
// Result: '1000.101'

(+"1000.1010").toFixed(digits = 10).replace(/(\.0*|(?<=(\..*))0*)$/, '');
// Result: '1000.101'

Run Code Online (Sandbox Code Playgroud)

要使用上面使用的正则表达式,replace()我们可以访问: https: //regex101.com/r/owj9fz/1