我是否错过了一个标准API调用,该调用从一个数字中移除尾随的不重要的零?

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

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


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

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

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

固定无填充

parseFloat(n.toFixed(4));

另一个选项几乎做同样的事情 这个答案可能会帮助你做决定

Number(n.toFixed(4));

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

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

因为即使你定义了一个后面带0的数字,它们也会被省略。

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

我首先使用了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"(所以没有运行时错误)

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

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

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


这里有一个可能的解决方案:

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

eval(x) --> 1.234
eval(y) --> 1.234001

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

除了去掉后面的0之外,我还需要为用户的当前语言环境(即123,456.789)对输出进行四舍五入和格式化。

我在这方面的所有工作都包括在GitHub: https://github.com/dperish/prettyFloat.js上的prettyFloat.js (MIT许可)


使用例子:

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


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

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

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

如果将返回值转换为数字,则后面的零将被删除。这是一种比自己进行舍入或截断计算更简单的方法。

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

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

对于非常小的数,这些解都不适用。http://numeraljs.com/为我解决了这个问题。

parseFloat(0.00000001.toFixed(8));
// 1e-8

numeral(0.00000001).format('0[.][00000000]');
// "0.00000001"

当Django在文本字段中显示十进制类型的值时,我也需要解决这个问题。例如,当'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;
}

像这样乘以1怎么样?

var x = 1.234000*1; // becomes 1.234

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

纯正则表达式的答案

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

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


如果由于任何原因(比如涉及到金钱浮动)不能使用float,并且已经从表示正确数字的字符串开始,您可以发现这个解决方案很方便。它将表示数字的字符串转换为表示数字的字符串,后面不带零。

function removeTrailingZeroes( strAmount ) {
    // remove all trailing zeroes in the decimal part
    var strDecSepCd = '.'; // decimal separator
    var iDSPosition = strAmount.indexOf( strDecSepCd ); // decimal separator positions
    if ( iDSPosition !== -1 ) {
        var strDecPart = strAmount.substr( iDSPosition ); // including the decimal separator

        var i = strDecPart.length - 1;
        for ( ; i >= 0 ; i-- ) {
            if ( strDecPart.charAt(i) !== '0') {
                break;
            }
        }

        if ( i=== 0 ) {
            return strAmount.substring(0, iDSPosition);
        } else {
            // return INTPART and DS + DECPART including the rightmost significant number
            return strAmount.substring(0, iDSPosition) + strDecPart.substring(0,i + 1);
        }
    }

    return strAmount;
}

在阅读了所有的答案和评论后,我得出了这样的结论:

function isFloat(n) {
    let number = (Number(n) === n && n % 1 !== 0) ? eval(parseFloat(n)) : n;
    return number;
}

我知道使用eval在某种程度上是有害的,但这帮助了我很多。

So:

isFloat(1.234000);     // = 1.234;
isFloat(1.234001);     // = 1.234001
isFloat(1.2340010000); // = 1.234001

如果你想限制小数点后的位置,可以使用toFixed()。

let number = (Number(n) === n && n % 1 !== 0) ? eval(parseFloat(n).toFixed(3)) : n;

就是这样。


你可以试试这个来缩小浮点数

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

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

我需要删除任何尾随零,但至少保留2个小数,包括任何零。我正在使用的数字是6个十进制数字字符串,由. tofixed(6)生成。

预期结果:

var numstra = 12345.000010 // should return 12345.00001
var numstrb = 12345.100000 // should return 12345.10
var numstrc = 12345.000000 // should return 12345.00
var numstrd = 12345.123000 // should return 12345.123

解决方案:

var numstr = 12345.100000

while (numstr[numstr.length-1] === "0") {           
    numstr = numstr.slice(0, -1)
    if (numstr[numstr.length-1] !== "0") {break;}
    if (numstr[numstr.length-3] === ".") {break;}
}

console.log(numstr) // 12345.10

逻辑:

如果字符串的最后一个字符为零,则运行循环函数。 删除最后一个字符并更新字符串变量。 如果更新后的字符串最后一个字符不是零,则结束循环。 如果更新的字符串倒数第三个字符是浮点数,则结束循环。


如果你使用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

PS:如果你使用toFixed(0),那么不需要更换。


如果我们有一个数字的s字符串表示形式,例如我们可以使用number的.toFixed(digits)方法(或任何其他方法)来获得,那么为了从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
 */

replace()中使用的正则表达式解释如下:

In the first place please pay the attention to the | operator inside the regular expression, which stands for "OR", so, the replace() method will remove from s two possible kinds of substring, matched either by the (\.0*)$ part OR by the ((?<=(\..*))0*)$ part. The (\.0*)$ part of regex matches a dot symbol followed by all the zeros and nothing else till to the end of the s. This might be for example 0.0 (.0 is matched & removed), 1.0 (.0 is matched & removed), 0.000 (.000 is matched & removed) or any similar string with all the zeros after the dot, so, all the trailing zeros and the dot itself will be removed if this part of regex will match. The ((?<=(\..*))0*)$ part matches only the trailing zeros (which are located after a dot symbol followed by any number of any symbol before start of the consecutive trailing zeros). This might be for example 0.100 (trailing 00 is matched & removed), 0.010 (last 0 is matched & removed, note that 0.01 part do NOT get matched at all thanks to the "Positive Lookbehind Assertion", i.e. (?<=(\..*)), which is in front of 0* in this part of regex), 1.100010 (last 0 is matched & removed), etc. If neither of the two parts of expression will match, nothing gets removed. This might be for example 100 or 100.11, etc. So, if an input does not have any trailing zeros then it stays unchanged.

更多使用.toFixed(数字)的例子(在下面的例子中使用了字面值“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'

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


我是这样做的:

parseFloat(number.toString());

这也是一个很好的解决TypeScript bug的方法。在某些情况下将数字更改为字符串的错误。


我的解决方案如下:

export const floatToStr = (f, ndigit = 2) => {
    const str = f.toFixed(ndigit)
    return ndigit
        ? str
            .replace(/0*$/g, '')
            .replace(/\.$/, '')
        : str
}

我写这个正则表达式是为了从包含数字的字符串的开头和结尾删除无关紧要的0、小数和空格:

const rxInsignificant = /^[\s0]+|(?<=\..*)[\s0.]+$|\.0+$|\.$/gm; 设 ary = [ "001.230", "2.", "3.00", "1000", " 0000000000000010000.10000000000000000000000 "]; ary.forEach((str)=> { console.log('“${str}” 变为 “${str.replace(rxInsignificant ,'')}”'); });

不幸的是,Safari仍然不支持2018年的规范,该规范为我们提供了正则表达式的回溯。自07-28-2017以来,此问题一直有一个开放的错误报告。

好消息是,在Firefox和所有Chromium衍生产品中,向后查找功能确实有效。希望Safari能收到更多的要求,并尽快实现这个标准。

与此同时,我写了这个函数来完成同样的任务,而不需要回顾:

function createRemoveInsignificantFunction() { const rxLeadingZeros = /^[\s0]+/; const rxEndingZeros = /[\s0]+$/; function removeInsignificant(str) { str = str.replace(rxLeadingZeros,''); let ary = str.split('.'); if (ary.length > 1) { ary[1] = ary[1].replace(rxEndingZeros,''); if (ary[1].length === 0) { return ary[0]; } else { return ary[0] + '.' + ary[1]; } } return str; } return removeInsignificant; } let removeInsignificant = createRemoveInsignificantFunction(); let ary = [ "001.230", "2.", "3.00", "1000", " 0000000000000010000.10000000000000000000000 "]; ary.forEach((str)=> { console.log(`"${str}" becomes "${removeInsignificant(str)}"`); });

当我有更多的时间时,我想弄清楚如何用一个正则表达式来完成这个任务,而不需要在其中查找。欢迎你在下面的评论中打败我。


如果还想处理数字错误,可以使用Intl。NumberFormat或Number.toLocaleString()

new Intl.NumberFormat().format(0.0100) // "0.01"
new Intl.NumberFormat().format(0.010000000000001) // "0.01"
new Intl.NumberFormat().format(0.009999999999999) // "0.01"
console.log((0.0100).toLocaleString()) // "0.01"
console.log((0.010000000000001).toLocaleString()) // "0.01"
console.log((0.009999999999999).toLocaleString()) // "0.01"

所以你想

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

没有附加条件,只需尝试Number()。

Var x = 1.234000, //变成1.234 Y = 1.234001, //保持1.234001 x_ =数字(x), y_ =数字(y); y_ console.log(间);


我认为下面的函数可能接近你想要的。我是为我的一个应用程序写的。它总是以不带后面零的标准符号输出。有些东西你可能不想要,但如果你喜欢,可以删掉。它总是返回至少一个小数(e.x。5 = >“5.0”)。它也被限制为10个小数。把它作为一个指南。

const toDecimalStr(value)=>{
  let str=value.toFixed(10).replace(/([0]+)$/,"");
  try {
    if (str.endsWith(".")) str+='0';
  } catch (e) {
    str+='0';
  }
  return str;
}

try catch是因为不是所有东西都支持endsWith,我太懒了。


使用parseFloat()实现了这个目的。我不明白为什么这些复杂的解。