JavaScriptでフロートをフォーマットする方法は?


427

JavaScriptで、浮動小数点から文字列に変換するときに、小数点以下2桁を取得するにはどうすればよいですか?たとえば、0.3445434ではなく0.34です。


16
最初の2桁を除いてすべて切り捨てますか、それとも2桁に丸めますか?
xtofl 2009年

回答:


232
var result = Math.round(original*100)/100;

コードが自明ではない場合の詳細

編集:...または単に使用します。TimBüthetoFixedによって提案されました。忘れてしまいました、リマインダーに感謝(そして賛成投票):)


1
これを文字列値を受け入れないライブラリ「Highchart」で使用していたため、toFixedは機能しませんでした
。Math.roundは

4
toFixed()何かのように何を模倣しますprintf()がC.に行い、toFixed()かつMath.round()、異なる丸め処理します。この場合、toFixed()と同じ種類の効果Math.floor()があります(元の値に10 ^ nを掛けてtoFixed()、n桁で呼び出すことを前提としています)。答えの「正しさ」は、OPがここで何を望んでいるかに大きく依存し、両方とも独自の方法で「正解」です。
DDPWNAGE

838

数値を丸める関数があります。例えば:

var x = 5.0364342423;
print(x.toFixed(2));

5.04を印刷します。

編集: フィドル


7
ブラウザーでprint()を使用しないことをお勧めします
cobbal

70
これに注意してください。toFixed()は文字列を返します:var x = 5.036432346; var y = x.toFixed(2) + 100; y等しくなります"5.03100"
Vlad

5
(1e100).toFixed(2)=== "1e + 100"
qbolec

7
また、一貫性のない丸めにも注意してください:(0.335).toFixed(2) == 0.34 == (0.345).toFixed(2)
Skippy le Grand Gourou

3
toFixedと同等のものを検索するが、丸めが一貫している場合は、toLocaleString:(0.345).toLocaleString( 'en-EN'、{minimumFractionDigits:2、maximumFractionDigits:2})
fred727

185

使用するときは注意してくださいtoFixed()

まず、数値の丸めは数値のバイナリ表現を使用して行われるため、予期しない動作が発生する可能性があります。例えば

(0.595).toFixed(2) === '0.59'

の代わりに'0.6'

次に、IEにのバグがありtoFixed()ます。IEでは(少なくともバージョン7まではIE8をチェックしませんでした)、次のことが当てはまります。

(0.9).toFixed(0) === '0'

kkyyの提案に従うか、カスタムtoFixed()関数を使用することをお勧めします。例:

function toFixed(value, precision) {
    var power = Math.pow(10, precision || 0);
    return String(Math.round(value * power) / power);
}

はい、これは価格を予測するコードを作成するときに非常に重要になる可能性があります。ありがとう!+1
ファビオミルヘイロ

10
.toFixed()戻り値にネイティブメソッドを追加することをお勧めします。これにより、必要な精度が追加さreturn (Math.round(value * power) / power).toFixed(precision);れます。例:: また、値を文字列として返します。それ以外の場合、小数点以下の桁数の場合、精度20は無視されます
William Joss Crowcroft '22

3
に関する注意事項toFixed:精度を上げると予期しない結果が生じる可能性があることに注意してください:(1.2).toFixed(16) === "1.2000000000000000"一方、(1.2).toFixed(17) === "1.19999999999999996"(Firefox / ChromeではIE8ではIE8が内部で提供できる精度が低いため後者は成り立たない)。
jakub.g 2013年

2
(0.598).toFixed(2)生産もしておりませんのでご了承ください0.6。これは、生産0.60:)
qbolec

1
また、一貫性のない丸めにも注意してください(0.335).toFixed(2) == 0.34 == (0.345).toFixed(2)
Skippy le Grand Gourou 2015

36

注意すべきもう1つの問題toFixed()は、数値の最後に不要なゼロが生成される可能性があることです。例えば:

var x=(23-7.37)
x
15.629999999999999
x.toFixed(6)
"15.630000"

アイデアは、RegExp以下を使用して出力をクリーンアップすることです:

function humanize(x){
  return x.toFixed(6).replace(/\.?0*$/,'');
}

RegExp、末尾のゼロ(およびオプションで小数点)を照合して、整数でも適切に見えるようにします。

humanize(23-7.37)
"15.63"
humanize(1200)
"1200"
humanize(1200.03)
"1200.03"
humanize(3/4)
"0.75"
humanize(4/3)
"1.333333"

Number.prototype.minFixed = function(decimals){return this.toFixed(decimals).replace(/ \。?0 * $ /、 ""); }
Luc Bloom

これは受け入れられるべきであり、末尾のゼロは厄介です。私はこの解決策を正確に探していました、gj。
exoslav

1
末尾のゼロは煩わしいかもしれませんが、これは「toFixed」というメソッド名が実行することを約束するものとまったく同じです;)
ksadowski

11
var x = 0.3445434
x = Math.round (x*100) / 100 // this will make nice rounding

Math.round(1.015 * 100)/ 100は1.01を与えますが、1.02であると期待しますか?
gaurav5430

6

乗数を使用してこれらすべてのソリューションが浮かんでいる問題があります。残念ながら、kkyyとChristophのソリューションはどちらも間違っています。

小数点以下2桁で551.175のコードをテストしてください-551.18になるはずの551.17に丸められます!しかし、あなたが元をテストする場合。451.175は問題ありません-451.18。したがって、このエラーを一目で特定することは困難です。

問題は乗算にあります:551.175 * 100 = 55117.49999999999を試してください(ups!)

だから私の考えは、Math.round()を使用する前にtoFixed()で処理することです。

function roundFix(number, precision)
{
    var multi = Math.pow(10, precision);
    return Math.round( (number * multi).toFixed(precision + 1) ) / multi;
}

1
これはjsの算術の問題です:(551.175 * 10 * 10)!==(551.175 * 100)。非実数の10進数の結果を得るには、10進数の増分を使用してコンマを移動する必要があります。
カノスキール2014年

ただし、これに気付く+1 toFixedは影響を受けます— (0.335).toFixed(2) == 0.34 == (0.345).toFixed(2)…どちらの方法を使用する場合でも、丸める前にイプシロンを追加することをお勧めします。
Skippy le Grand Gourou 2015

5

ここで重要なのは、最初に正しく切り上げてから、それを文字列に変換することです。

function roundOf(n, p) {
    const n1 = n * Math.pow(10, p + 1);
    const n2 = Math.floor(n1 / 10);
    if (n1 >= (n2 * 10 + 5)) {
        return (n2 + 1) / Math.pow(10, p);
    }
    return n2 / Math.pow(10, p);
}

// All edge cases listed in this thread
roundOf(95.345, 2); // 95.35
roundOf(95.344, 2); // 95.34
roundOf(5.0364342423, 2); // 5.04
roundOf(0.595, 2); // 0.60
roundOf(0.335, 2); // 0.34
roundOf(0.345, 2); // 0.35
roundOf(551.175, 2); // 551.18
roundOf(0.3445434, 2); // 0.34

これで、toFixed(p)を使用してこの値を安全にフォーマットできます。だからあなたの特定のケースでは:

roundOf(0.3445434, 2).toFixed(2); // 0.34


1
function trimNumber(num, len) {
  const modulu_one = 1;
  const start_numbers_float=2;
  var int_part = Math.trunc(num);
  var float_part = String(num % modulu_one);
      float_part = float_part.slice(start_numbers_float, start_numbers_float+len);
  return int_part+'.'+float_part;
}

セミコロンがないことを除いて素晴らしい答えです(いいえ、es6ではセミコロンは廃止されておらず、場合によっては使用する必要があります)。最後の行も編集する必要がありました。return float_part ? int_part+'.'+float_part : int_part;それ以外の場合、整数を渡した場合、末尾にドットが付いた数値が返されます(入力例:2100、出力:2100.
KubaŠimonovskýOct

0

たぶん、あなたも小数点区切り文字が必要でしょうか?これが私が作ったばかりの関数です:

function formatFloat(num,casasDec,sepDecimal,sepMilhar) {
    if (num < 0)
    {
        num = -num;
        sinal = -1;
    } else
        sinal = 1;
    var resposta = "";
    var part = "";
    if (num != Math.floor(num)) // decimal values present
    {
        part = Math.round((num-Math.floor(num))*Math.pow(10,casasDec)).toString(); // transforms decimal part into integer (rounded)
        while (part.length < casasDec)
            part = '0'+part;
        if (casasDec > 0)
        {
            resposta = sepDecimal+part;
            num = Math.floor(num);
        } else
            num = Math.round(num);
    } // end of decimal part
    while (num > 0) // integer part
    {
        part = (num - Math.floor(num/1000)*1000).toString(); // part = three less significant digits
        num = Math.floor(num/1000);
        if (num > 0)
            while (part.length < 3) // 123.023.123  if sepMilhar = '.'
                part = '0'+part; // 023
        resposta = part+resposta;
        if (num > 0)
            resposta = sepMilhar+resposta;
    }
    if (sinal < 0)
        resposta = '-'+resposta;
    return resposta;
}

0

乗算または除算のいずれかを使用して、x.xx5を実際の値として価格の丸めに矛盾を回避する方法はありません。クライアント側で正しい価格を計算する必要がある場合は、すべての金額をセントで維持する必要があります。これは、JavaScriptの数値の内部表現の性質によるものです。Excelにも同じ問題があり、ほとんどの人はこの現象によって引き起こされる小さなエラーに気付かないことに注意してください。ただし、多くの計算値を合計すると常にエラーが蓄積する可能性があるため、最終的な結果のエラーを最小限に抑えるために、計算の順序やその他の方法を含む全体的な理論があります。10進数値の問題を強調するために、0.1 + 0.2はJavaScriptの0.3と正確に同じではなく、1 + 2は3に等しいことに注意してください。


解決策は、全体と小数部を分離し、浮動小数点数を使用する代わりに、10進数で整数として表すことです。ここでは、prettyPrintでは問題なく機能しますが、一般に、ベースと別の表現のどちらかを選択する必要があります。実数ともう1
つには

「Excelも同じ問題に悩まされている」。ソース?
gaurav5430

0
/** don't spend 5 minutes, use my code **/
function prettyFloat(x,nbDec) { 
    if (!nbDec) nbDec = 100;
    var a = Math.abs(x);
    var e = Math.floor(a);
    var d = Math.round((a-e)*nbDec); if (d == nbDec) { d=0; e++; }
    var signStr = (x<0) ? "-" : " ";
    var decStr = d.toString(); var tmp = 10; while(tmp<nbDec && d*tmp < nbDec) {decStr = "0"+decStr; tmp*=10;}
    var eStr = e.toString();
    return signStr+eStr+"."+decStr;
}

prettyFloat(0);      //  "0.00"
prettyFloat(-1);     // "-1.00"
prettyFloat(-0.999); // "-1.00"
prettyFloat(0.5);    //  "0.50"

0

このコードを使用して、フロートをフォーマットします。に基づいてtoPrecision()いますが、不要なゼロを取り除きます。正規表現を単純化する方法についての提案を歓迎します。

function round(x, n) {
    var exp = Math.pow(10, n);
    return Math.floor(x*exp + 0.5)/exp;
}

使用例:

function test(x, n, d) {
    var rounded = rnd(x, d);
    var result = rounded.toPrecision(n);
    result = result.replace(/\.?0*$/, '');
    result = result.replace(/\.?0*e/, 'e');
    result = result.replace('e+', 'e');
    return result;  
}

document.write(test(1.2000e45, 3, 2) + '=' + '1.2e45' + '<br>');
document.write(test(1.2000e+45, 3, 2) + '=' + '1.2e45' + '<br>');
document.write(test(1.2340e45, 3, 2) + '=' + '1.23e45' + '<br>');
document.write(test(1.2350e45, 3, 2) + '=' + '1.24e45' + '<br>');
document.write(test(1.0000, 3, 2) + '=' + '1' + '<br>');
document.write(test(1.0100, 3, 2) + '=' + '1.01' + '<br>');
document.write(test(1.2340, 4, 2) + '=' + '1.23' + '<br>');
document.write(test(1.2350, 4, 2) + '=' + '1.24' + '<br>');
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.