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

时间:2010-08-31 20:01:00

标签: javascript regex math numbers

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

实施例

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

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

18 个答案:

答案 0 :(得分:179)

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

toFixed without padding

parseFloat(n.toFixed(4));

另一种做同样事情的选择
This answer may help your decision

Number(n.toFixed(4));

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

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

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

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

答案 1 :(得分:109)

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

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

答案 2 :(得分: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”(所以没有运行时错误)

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

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

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

答案 3 :(得分:11)

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

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

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

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

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

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

答案 4 :(得分: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;
}

答案 5 :(得分:5)

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

除了修剪尾随零之外,我还需要对用户当前语言环境(即123,456.789)的输出进行舍入和格式化。

我对此的所有工作都已作为prettyFloat.js(MIT许可)包含在GitHub上: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 Internationalization 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"

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

答案 6 :(得分:5)

正则表达式纯答案

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

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

答案 7 :(得分:3)

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

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

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

答案 8 :(得分:2)

这些解决方案对我来说都不是很有用。 http://numeraljs.com/为我解决了这个问题。

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

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

答案 9 :(得分:2)

如何才能像这样乘以?

var x = 1.234000*1; // becomes 1.234

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

答案 10 :(得分:2)

如果在n> 0的情况下使用toFixed(n),则可以使用以下更简单和稳定的解决方案(不再进行浮点运算):

(+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),则不需要replace

答案 11 :(得分:1)

如果由于任何原因(例如涉及的资金浮动)而无法使用浮动货币,并且已经从代表正确数字的字符串开始,则可以轻松找到此解决方案。它将代表数字的字符串转换为代表无尾随数字的数字的字符串。

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

答案 12 :(得分:0)

我是这样做的:

parseFloat(number.toString());

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

答案 13 :(得分:0)

如果我们有一个数字的s字符串表示形式(例如,可以使用.toFixed(digits) method of 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
 */

上面在{{1}中使用的

正则表达式在下面解释

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

使用100.11的更多示例(以下示例中使用字母值“ 1000.1010”,但我们可以采用变量):

.toFixed(digits)

要使用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' 中使用的上述正则表达式,我们可以访问:https://regex101.com/r/owj9fz/1

答案 14 :(得分:0)

我需要删除所有结尾的零,但至少保留2个小数,包括任何零。
我正在使用的数字是.toFixed(6)生成的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

逻辑:

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

答案 15 :(得分:0)

阅读所有答案和评论后,我得出了以下结论:

   If Me.ExpName And Me.ExpAmount <> "" Then
      MsgBox "there is data in the fields"
   End If

我知道使用function isFloat(n) { let number = (Number(n) === n && n % 1 !== 0) ? eval(parseFloat(n)) : n; return number; } 可能有害,但这对我很有帮助。

所以:

eval

如果要限制小数位数,请使用isFloat(1.234000); // = 1.234; isFloat(1.234001); // = 1.234001 isFloat(1.2340010000); // = 1.234001 ,如其他人指出的那样。

toFixed()

就是这样。

答案 16 :(得分:-1)

只是使用toFixed

的简单数学替代方法

function truncateNumber( num, precision ){
    let c = Math.pow(10,precision);
    return Math.trunc( num*c )/c;
}
    
console.log( truncateNumber(1234.5678, 4) );
console.log( truncateNumber(1234.56, 4) );

答案 17 :(得分:-1)

这是一个可能的解决方案:

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

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