[英]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.