数値から重要でない後続ゼロを削除しますか?


157

数値から後続の重要でないゼロを削除する標準のAPI呼び出しを見逃しましたか?

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

Number.toFixed()とNumber.toPrecision()は、私が探しているものではありません。


6
うーん、1.234000 === 1.234
ガンボ2010

5
そう、alert(x)を実行すると、後続ゼロなしでポップアップします
JKirchartz

50
いくつかのクライアントを操作した後、1.234000 === 1.234であるにもかかわらず、クライアントは、必要がない場合は余分なゼロを表示したくないことを証明できます。
contactmatt 2013年

16
使用しparseFloat(n)ますか?
エイリアン氏2016

これは、すべてのエッジケースをカバーする最も簡単なソリューションでした。@ Mr.Alienに感謝します。
James Perih

回答:


140

文字列に変換した場合、後続のゼロは表示されません。これは、文字列ではなく数値として作成されたため、そもそも変数に格納されていません。

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

6
私はゼロを取り除くためにいくつかのコードを投稿しようとしていましたが、ダニエルのソリューションは機能しているようです。「1.2345000」などの文字列でも機能します。( "1.2345000" * 1).toString(); // 1.2345になります
Steven

7
もちろん、varが既に文字列である場合は、最初に数値に変換してから再び戻す必要があります
derekcohen

これはうまくいきました。同じ問題があり、floatをstringに変換してから、parseFloatで正しい形式に戻しましたが、末尾のゼロはありませんでした。
マットウエスト

10
これは完全なソリューションではありません。あなたは、いくつかのような浮動小数点表現の誤りを持つ変数を、持っているとき、それは仕事をしません。var n = 1.245000000000001(ユーザに提示することが軽微であると仮定)
オーガー

7
1231111111111111111111111111111222222222222222222222222222222222222222222222222222.00などの数値に対して予期しない結果が生じる可能性があります。文字列表現は指数形式になります:1.231111111111111e + 81
Stas Makutin

227

私が使用したかったのと同じようなインスタンスがありました .toFixed()必要に応じありましたが、そうでないときにパディングはしたくありませんでした。そのため、toFixedと組み合わせてparseFloatを使用することになりました。

パディングなしで修正

parseFloat(n.toFixed(4));

ほぼ同じことを行う別のオプション
この回答はあなたの決定を助けるかもしれません

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;

これは、関連する小数点以下の桁数がtoFixed引数以上である場合にのみ機能することに注意してください。数値がたとえば1.200000の場合、toFixed(3)の結果は1.200になるため、後続のゼロはすべて削除されません。
Leopoldo Sanczyk 2015年

@LeopoldoSanczykいいえ、これは、toFixedを使用している場合にのみ当てはまります。これは、文字列を返すためです。数値型は自動的に後続ゼロを失います。そのため、この2つを組み合わせて使用​​しました。
Gary、

@ゲイリー、私は私のコメントを取り下げ、parseFloat(n).toFixed(4);あなたの実際の答えの代わりに見ました。申し訳ありません。
Leopoldo Sanczyk 2015年

2
なんで+(n.toFixed(4))
КонстантинВан

3
賛成です!回答の1つの問題のみ0.00000005が5e-8に変換されます。この問題なしで重要でないゼロを削除するにはどうすればよいですか?最後にゼロを削除する必要がある0.000058000などの小さな数値で作業しています
PirateApp

29

私は最初に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')

これにより、上記と同じ結果が得られます。


1
私はうまくいくと信じている純粋な正規表現ソリューションを持っていますtoFixed(4).replace(/([0-9]+(\.[1-9]+)?)(\.?0+$)/,"$1")
Gary

1
ガ!どうやら私は自分のRegExesを他の人よりも破るのが得意ではありません。これは私を打たせません!私はこれをすべてのテストケースと考えられるすべての(有効な)ケースに対して実行しました([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)
Gary

1
正規表現は貪欲であり、整数部分から「0」を削除することがあります!:-(なぜだけではないのreplace(/[,.][1-9]+(0+)/,'')ですか?
Sebastian Sebald '26

1
これは過小評価されています。
チャーリー

1
@ w00tああ、すみません、今はわかりました。私は私が私を作ったときに私がテストした方法でした(上のリンクを参照)。toFixedを使用しても、数値にはドットが含まれることが保証されているため、問題はありませんが、ドットのない整数を含む任意の数値に対して正規表現を機能させたいため、テストでは失敗しました。toFixedがないと、最後にゼロを食べます。私の悪い。
geekley

22

toFixed必要であれば、この方法は適切な丸めを行います。また、後続ゼロが追加されますが、これは常に理想的ではありません。

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

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

戻り値を数値にキャストすると、後続のゼロは削除されます。これは、独自の丸めや切り捨ての計算を行うよりも簡単な方法です。

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

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

1
トリッキーですが、まさに私が探していたものです。重要な後続ゼロを削除します(もちろん、toFixed呼び出しによって重要にしました)。奇妙なUXエッジケースです。
2018年

12

基本的に同じ要件があり、この機能には組み込みのメカニズムがないことがわかりました。

末尾のゼロを削除することに加えて、ユーザーの現在のロケール(つまり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"

古いブラウザでは、このポリフィルを使用できます:https ://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.en


これが探していたものです。npmパッケージを作成する必要があります。
EnZo

これは国際化APIを介して可能になったので、おそらくこれを更新する必要があります。
18

2
これは非常に役立ちます。共有とアップデートにも感謝します。
jaggedsoft 2018

11

このようなものを掛けるのはどうですか?

var x = 1.234000*1; // becomes 1.234

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

9

これを試して浮動小数点数を小さくすることができます

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

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

7

純粋な正規表現の答え

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

なんで誰もくれなかったのかしら!


数字では機能しません(数字は元の質問に記載されています)。文字列表現のソリューションは大好きです!
BennyHilarious

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

これは機能しますが、実行ごとに複数の文字列が作成されるため、非常に非効率的です。これをテーブルのすべてのセルで実行すると想像してください。より適切なオプションは、後続のゼロの数を決定し、スライスを一度に実行することです。文字が何であるかを決定することは、大部分が効率的であり、文字列を分割することはそれほどではありません。
Derek Nigel Bartram

:私はあなたの提案デレクのようなものでしたgithub.com/rek/remove-trailing-zeros/blob/master/...
rekarnar

Perfテストはここにあります:jsperf.com/remove-trailing-zeros/1、あなたは正しかった、ゼロを見つけてそれらを削除することはずっと速いです!
rekarnar

4

これらの解決策のどれも、非常に少数の場合、私にとってうまくいきませんでした。 http://numeraljs.com/がこれを解決してくれました。

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

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

6を超える精度は処理できません。このライブラリは、少数を対象とする場合は役に立たないと言えます。絶対にお勧めしません。
Daniel Kmak

2

何らかの理由(関連するmoney-floatsなど)で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;
}

0

答えとコメントをすべて読んだ後、私はこれで終わりました:

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;

それでおしまい。


0

後続のゼロを削除する必要がありましたが、ゼロを含めて少なくとも2つの小数点を保持しました。
私が扱っている数値は、.toFixed(6)によって生成された6つの10進数文字列です。

期待される結果:

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

論理:

文字列の最後の文字がゼロの場合、ループ関数を実行します。
最後の文字を削除して、文字列変数を更新します。
更新された文字列の最後の文字がゼロでない場合、ループを終了します。
最後から3番目の文字の更新された文字列が浮動小数点の場合、ループを終了します。


-1

これが可能な解決策です:

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

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

4
この単純なタスクにはevalは必要ありません。parseFloat()はるかに適切です。
ハッチバット2014年

6
eval == evil。使用しないでください
eagor
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.