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

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

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

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

262593 次浏览

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

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

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

固定无填充

parseFloat(n.toFixed(4));
< p > 另一个选项几乎做同样的事情 < br > 这个答案可能会帮助你做决定 < / em >

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"(所以没有运行时错误)

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

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"

对于旧的浏览器,你可以使用这个polyfill: 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在某种程度上是有害的,但这帮助了我很多。

所以:

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

逻辑:< br >

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

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

如果我们有一个数字的s字符串表示形式,例如我们可以使用.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()中使用的正则表达式是下面的解释:

  • 首先,请注意正则表达式中的|操作符,它代表"OR",因此,replace()方法将从s中删除两种可能的子字符串,由(\.0*)$部分或((?<=(\..*))0*)$部分匹配。
  • regex的(\.0*)$部分匹配一个点符号,后面跟着所有的0,直到s结束。例如,这可能是0.0 (.0是匹配的&1.0 (.0匹配&0.000 (.000匹配&(已删除)或任何类似的字符串,点号后面都是0,因此,如果regex的这部分匹配,那么所有尾随的0和点号本身都将被删除。
  • ((?<=(\..*))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'


要在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
}

我写这个正则表达式是为了从包含数字的字符串的beginning and end中删除无关紧要的:zeros, decimals, and spaces:

const rxInsignificant = /^[\s0]+|(?<=\..*)[\s0.]+$|\.0+$|\.$/gm;


let ary = [
"001.230",
"2.",
"3.00",
"1000",
" 0000000000000010000.10000000000000000000000  "];


ary.forEach((str)=>
{
console.log(`"${str}" becomes "${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.NumberFormatNumber.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

没有附带__abc0,只需尝试Number()

var x  = 1.234000, // to become 1.234
y  = 1.234001, // stays 1.234001
x_ = Number(x),
y_ = Number(y);


console.log(x_,y_);

我认为下面的函数可能接近你想要的。我是为我的一个应用程序写的。它总是以不带后面零的标准符号输出。有些东西你可能不想要,但如果你喜欢,可以删掉。它总是返回至少一个小数(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()实现了这个目的。我不明白为什么这些复杂的解。