[英]Remove insignificant trailing zeros from a number?
我是否错过了一个标准的 API 调用,该调用从数字中删除了尾随无关紧要的零?
var x = 1.234000; // to become 1.234
var y = 1.234001; // stays 1.234001
Number.toFixed()
和Number.toPrecision()
并不是我想要的。
我有一个类似的实例,我想在必要时使用.toFixed()
,但我不想要填充。 所以我最终将 parseFloat 与 toFixed 结合使用。
toFixed 无填充
parseFloat(n.toFixed(4));
另一个几乎做同样事情的选择
这个答案可能有助于你的决定
Number(n.toFixed(4));
toFixed
会将数字toFixed
/填充到特定长度,但也会将其转换为字符串。 将其转换回数字类型不仅会使数字在算术上使用更安全,而且还会自动删除任何尾随 0。 例如:
var n = "1.234000";
n = parseFloat(n);
// n is 1.234 and in number form
因为即使您定义了一个带有尾随零的数字,它们也会被删除。
var n = 1.23000;
// n == 1.23;
如果将其转换为字符串,则不会显示任何尾随零,这些零一开始就没有存储在变量中,因为它是作为数字创建的,而不是字符串。
var n = 1.245000
var noZeroes = n.toString() // "1.245"
我首先结合使用了 matti-lyra 和 gary 的答案:
r=(+n).toFixed(4).replace(/\.0+$/,'')
结果:
有点问题的情况是 0.10001。 我最终使用了这个更长的版本:
r = (+n).toFixed(4);
if (r.match(/\./)) {
r = r.replace(/\.?0+$/, '');
}
更新:这是加里的新版本(见评论):
r=(+n).toFixed(4).replace(/([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/,'$1')
这给出了与上面相同的结果。
如有必要, toFixed
方法将进行适当的舍入。 它还会添加尾随零,这并不总是理想的。
(4.55555).toFixed(2);
//-> "4.56"
(4).toFixed(2);
//-> "4.00"
如果将返回值转换为数字,则将删除那些尾随零。 这是一种比自己进行四舍五入或截断数学运算更简单的方法。
+(4.55555).toFixed(2);
//-> 4.56
+(4).toFixed(2);
//-> 4
像这样乘以一怎么样?
var x = 1.234000*1; // becomes 1.234
var y = 1.234001*1; // stays as 1.234001
我有基本相同的要求,并发现此功能没有内置机制。
除了修剪尾随零之外,我还需要根据用户的当前语言环境(即 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 ,它提供语言敏感的字符串比较、数字格式以及日期和时间格式。
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
你可以试试这个来缩小浮点数
var n = 0.0000;
n = parseFloat(n.toString());
//output n = 0;
// n = 3.14000; --> n = 3.14;
纯正则表达式答案
n.replace(/(\.[0-9]*[1-9])0+$|\.0*$/,'$1');
我想知道为什么没有人给一个!
当 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;
}
这些解决方案都不适用于非常小的数字。 http://numeraljs.com/为我解决了这个问题。
parseFloat(0.00000001.toFixed(8));
// 1e-8
numeral(0.00000001).format('0[.][00000000]');
// "0.00000001"
如果你使用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)
,则不需要replace
。
如果您出于任何原因不能使用浮点数(例如涉及货币浮点数)并且已经从表示正确数字的字符串开始,您可以找到这个解决方案很方便。 它将表示数字的字符串转换为表示不带尾随零的数字的字符串。
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;
}
如果我们有一个数字的一些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()
使用的正则表达式解释如下:
|
正则表达式中的运算符,代表“OR”,因此, replace()
方法将从s
删除两种可能的子字符串,由(\\.0*)$
部分匹配或由((?<=(\\..*))0*)$
部分。(\\.0*)$
部分匹配一个点符号,后跟所有零,直到s
的末尾才匹配。 例如,这可能是0.0
(匹配并删除.0
)、 1.0
(匹配并删除.0
)、 0.000
(匹配并删除.000
)或点后全是零的任何类似字符串,因此,所有如果正则表达式的这部分匹配,则尾随零和点本身将被删除。((?<=(\\..*))0*)$
部分仅匹配尾随零(位于点符号之后,后跟连续尾随零开始之前的任意数量的任何符号)。 例如,这可能是0.100
(尾随00
匹配并删除)、 0.010
(最后一个0
匹配并删除,请注意,由于“Positive Lookbehind Assertion”, 0.01
部分根本不匹配,即(?<=(\\..*))
,在正则表达式的这一部分中位于0*
前面), 1.100010
(最后一个0
被匹配并删除)等。100
或100.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 错误,这也是一个很好的解决方法。 在某些情况下将数字更改为字符串的错误。
所以你要
var x = 1.234000; // to become 1.234
var y = 1.234001; // stays 1.234001
没有附加string
,只需尝试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_);
在阅读了所有答案 - 和评论 - 我最终得到了这个:
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;
就是这样。
我需要删除任何尾随零,但至少保留 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
逻辑:
如果字符串最后一个字符为零,则运行循环函数。
删除最后一个字符并更新字符串变量。
如果更新后的字符串最后一个字符不是零,则结束循环。
如果更新后的字符串倒数第三个字符是浮点数,则结束循环。
我的解决方案如下:
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", " 0000000000000010000.10000000000000000000000 "]; ary = ary.map((str)=> { str = str.replace(rxInsignificant,''); return str; }); console.log(ary);
不幸的是,Safari 仍然不支持2018 年规范,该规范在正则表达式中为我们提供了后视。 自 2017 年 7 月 28 日以来,已针对此问题提供了一个公开的错误报告。
好消息是,lookbehinds 确实适用于 Firefox 和所有 Chromium 衍生产品。 希望 Safari 将收到更多关于此合规性的请求并尽快实施此标准。
如果您还想处理数字错误,可以使用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"
使用 parseFloat() 对我有用。 对于为什么这些复杂的解决方案,我在这里摸不着头脑。
这是一个可能的解决方案:
var x = 1.234000 // to become 1.234;
var y = 1.234001; // stays 1.234001
eval(x) --> 1.234
eval(y) --> 1.234001
只是使用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) );
我认为下面的 function 可能接近你想要的。 我为我的应用程序编写了它。 它将始终采用标准符号 output,没有尾随零。 一些你可能不想要的东西,但如果你愿意,可以编辑掉。 它总是返回至少一位小数(例如 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;
}
尝试捕获是因为并非所有东西都支持 endWith 并且我很懒惰。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.