我是否错过了一个标准的API调用,可以将数字末尾无关的零去掉?
var x = 1.234000; // to become 1.234
var y = 1.234001; // stays 1.234001
Number.toFixed()
和Number.toPrecision()
并不完全符合我的需求。
我是否错过了一个标准的API调用,可以将数字末尾无关的零去掉?
var x = 1.234000; // to become 1.234
var y = 1.234001; // stays 1.234001
Number.toFixed()
和Number.toPrecision()
并不完全符合我的需求。
当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;
}
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
*/
replace()
中使用的正则表达式如下所解释:
|
运算符,表示“或”,因此replace()
方法将从s
中移除两种可能的子字符串,分别由(\.0*)$
部分或((?<=(\..*))0*)$
部分匹配。(\.0*)$
部分匹配点符号后面的所有零和其他字符,直到s
字符串的末尾。例如,这可能是0.0
(匹配并移除.0
)、1.0
(匹配并移除.0
)、0.000
(匹配并移除.000
)或任何类似的字符串,因此如果此部分正则表达式匹配,则所有结尾的零以及点号本身都将被删除。((?<=(\..*))0*)$
部分仅匹配尾随的零(这些零位于点符号后面,其前面有任意数量的任何字符,直到连续尾随零的开头)。例如,这可能是0.100
(尾随的00
被匹配并删除)、0.010
(最后一个0
被匹配并删除,注意(?<=(\..*))
,“正向后查找断言”在0*
的前面,这部分正则表达式根本不会被匹配),1.100010
等。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
这些解决方案对于非常小的数字并不适用。 http://numeraljs.com/ 为我解决了这个问题。
parseFloat(0.00000001.toFixed(8));
// 1e-8
numeral(0.00000001).format('0[.][00000000]');
// "0.00000001"
我需要去除所有的尾随零,但至少保留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
逻辑:
如果字符串的最后一个字符是零,则运行循环函数。
删除最后一个字符并更新字符串变量。
如果更新后的字符串的最后一个字符不是零,则结束循环。
如果更新后的字符串倒数第三个字符是浮点数,则结束循环。
parseFloat(number.toString());
这也是解决TypeScript bug的好方法。该bug在某些情况下会将数字更改为字符串。
如果由于涉及货币浮点数等原因无法使用浮点数,并且您已经从表示正确数字的字符串开始,那么您可能会发现这个解决方案很方便。它将表示数字的字符串转换为表示无尾随零的数字的字符串。
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;
}
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, // to become 1.234
y = 1.234001, // stays 1.234001
x_ = Number(x),
y_ = Number(y);
console.log(x_,y_);
0.000001
,而是针对 Number(0.0000001)
,你会得到 1e-7
,这是完全正常的 JS 术语,也与本问题无关。然而,如果你仍然想将其转换为十进制字符串,那么只需捕获科学计数法中的最后一位数字(在本例中为 7),并执行 1e-7.toFixed(7)
。 - Redu零、小数点和空格
。
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年正则表达式中的后顾断言规范。自2017年7月28日以来,已经有一个开放的错误报告。
好消息是,后顾断言在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)}"`);
});
当我有更多时间时,我想弄清楚如何用一个不带回顾的正则表达式来完成这个任务。欢迎在下面的评论中超越我。
我认为下面的函数可能接近您想要的。我为我的一个应用程序编写了它。它总是以标准表示法输出,没有尾随零。有一些您可能不需要但可以编辑删除。它始终返回至少一个小数位(例如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,而我懒得去处理。
1.234000 === 1.234
的意思是“1.234000等于1.234”。 - GumboparseFloat(n)
? - Mr. Alien