web-dev-qa-db-ja.com

JavaScriptで小数点以下2桁までの数値をフォーマットする

私は自分の数字を小数点第2位に四捨五入するこのコード行を持っています。しかし、私はこのような数字を得ます:10.8、2.4など。これらは小数点以下2桁の私の考えではないので、どうすれば次のように改善できますか?

Math.round(price*Math.pow(10,2))/Math.pow(10,2);

10.80、2.40などの数字が欲しいのですが、私にとってはjQueryの使用は問題ありません。

537
Abs

固定小数点表記を使用して数値をフォーマットするには、単純に toFixed メソッドを使用できます。

(10.8).toFixed(2); // "10.80"

var num = 2.4;
alert(num.toFixed(2)); // "2.40"

toFixed()は文字列を返すことに注意してください。

_ important _ :toFixedは実際には丸めず、90%の時間で丸められた値を返しますが、実際にはうまくいきません。コンソールでこれを試してください。

2.005.toFixed(2)

あなたは間違った答えを得るでしょう

JavaScriptで小数点以下を四捨五入するのは自然な方法ではありません、あなたはあなた自身のpolyfillを必要とするか、またはライブラリを使用するでしょう。あなたはこのためのmozillaのpolyfillを見ることができます https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round

932
CMS

これは古い話題ですが、それでもグーグルのトップランクの結果であり、提供される解決策は同じ浮動小数点小数の問題を共有しています。これは私が使っている(非常に一般的な)関数、 thanks MDN です。

function round(value, exp) {
  if (typeof exp === 'undefined' || +exp === 0)
    return Math.round(value);

  value = +value;
  exp = +exp;

  if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0))
    return NaN;

  // Shift
  value = value.toString().split('e');
  value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)));

  // Shift back
  value = value.toString().split('e');
  return +(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp));
}

ご覧のとおり、これらの問題は発生しません。

round(1.275, 2);   // Returns 1.28
round(1.27499, 2); // Returns 1.27

この一般性はまた、いくつかの素晴らしいものを提供します。

round(1234.5678, -2);   // Returns 1200
round(1.2345678e+2, 2); // Returns 123.46
round("123.45");        // Returns 123

さて、OPの質問に答えるには、次のように入力しなければなりません。

round(10.8034, 2).toFixed(2); // Returns "10.80"
round(10.8, 2).toFixed(2);    // Returns "10.80"

あるいは、より簡潔で汎用性の低い関数としては、

function round2Fixed(value) {
  value = +value;

  if (isNaN(value))
    return NaN;

  // Shift
  value = value.toString().split('e');
  value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + 2) : 2)));

  // Shift back
  value = value.toString().split('e');
  return (+(value[0] + 'e' + (value[1] ? (+value[1] - 2) : -2))).toFixed(2);
}

あなたはそれを呼び出すことができます:

round2Fixed(10.8034); // Returns "10.80"
round2Fixed(10.8);    // Returns "10.80"

さまざまな例とテスト( @ t-j-crowder !に感謝)

function round(value, exp) {
  if (typeof exp === 'undefined' || +exp === 0)
    return Math.round(value);

  value = +value;
  exp = +exp;

  if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0))
    return NaN;

  // Shift
  value = value.toString().split('e');
  value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)));

  // Shift back
  value = value.toString().split('e');
  return +(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp));
}
function naive(value, exp) {
  if (!exp) {
    return Math.round(value);
  }
  var pow = Math.pow(10, exp);
  return Math.round(value * pow) / pow;
}
function test(val, places) {
  subtest(val, places);
  val = typeof val === "string" ? "-" + val : -val;
  subtest(val, places);
}
function subtest(val, places) {
  var placesOrZero = places || 0;
  var naiveResult = naive(val, places);
  var roundResult = round(val, places);
  if (placesOrZero >= 0) {
    naiveResult = naiveResult.toFixed(placesOrZero);
    roundResult = roundResult.toFixed(placesOrZero);
  } else {
    naiveResult = naiveResult.toString();
    roundResult = roundResult.toString();
  }
  $("<tr>")
    .append($("<td>").text(JSON.stringify(val)))
    .append($("<td>").text(placesOrZero))
    .append($("<td>").text(naiveResult))
    .append($("<td>").text(roundResult))
    .appendTo("#results");
}
test(0.565, 2);
test(0.575, 2);
test(0.585, 2);
test(1.275, 2);
test(1.27499, 2);
test(1234.5678, -2);
test(1.2345678e+2, 2);
test("123.45");
test(10.8034, 2);
test(10.8, 2);
test(1.005, 2);
test(1.0005, 2);
table {
  border-collapse: collapse;
}
table, td, th {
  border: 1px solid #ddd;
}
td, th {
  padding: 4px;
}
th {
  font-weight: normal;
  font-family: sans-serif;
}
td {
  font-family: monospace;
}
<table>
  <thead>
    <tr>
      <th>Input</th>
      <th>Places</th>
      <th>Naive</th>
      <th>Thorough</th>
    </tr>
  </thead>
  <tbody id="results">
  </tbody>
</table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
90
astorije

私は通常これを私の個人的なライブラリに追加します、そしていくつかの提案と@TIMINeutronソリューションを使用し、そしてそれを10進数の長さに適応できるようにした後、これは最もよく合います:

function precise_round(num, decimals) {
   var t = Math.pow(10, decimals);   
   return (Math.round((num * t) + (decimals>0?1:0)*(Math.sign(num) * (10 / Math.pow(100, decimals)))) / t).toFixed(decimals);
}

報告された例外に対して機能します。

41
Miguel

なぜ私は以前の答えにコメントを付け加えることができないのかわからないが(おそらく私は失望している、恐るべき)、私は@ Miguelの答えを使った解決策を思いついた。

function precise_round(num,decimals) {
   return Math.round(num*Math.pow(10, decimals)) / Math.pow(10, decimals);
}

そしてその2つのコメント(@bighostkimと@Imreから):

  • precise_round(1.275,2)が1.28を返さない問題
  • precise_round(6,2)が6.00を返さないという問題(彼が望んでいたように)。

私の最終的な解決策は以下の通りです。

function precise_round(num,decimals) {
    var sign = num >= 0 ? 1 : -1;
    return (Math.round((num*Math.pow(10,decimals)) + (sign*0.001)) / Math.pow(10,decimals)).toFixed(decimals);
}

ご覧のとおり、私は少し「修正」を追加しなければなりませんでした(それは実際のものではありませんが、Math.roundはロッシーです - jsfiddle.netで確認できます - これが私が知っている唯一の方法です。 " それ)。すでに埋め込まれている数値に0.001を追加するので、10進数値の右側に10sを追加します。安全に使用できるはずです。

その後、私は.toFixed(decimal)を追加して、常に正しい形式で(正しい小数点以下の桁数で)数値を出力します。

だからそれはほとんどです。それを上手に使ってください;)

編集:負の数の「修正」に機能を追加しました。

16
tfrascaroli

あなたが2つの小数で数を得ることを100%確信させる1つの方法:

(Math.round(num*100)/100).toFixed(2)

これが丸め誤差を引き起こすならば、Jamesが彼のコメントで説明したように、あなたは以下を使うことができます:

(Math.round((num * 1000)/10)/100).toFixed(2)
13

toFixed(n)は、小数点以下n桁の長さを提供します。 toPrecision(x)は全長xを提供します。

下記のこの方法を使用してください

// Example: toPrecision(4) when the number has 7 digits (3 before, 4 after)
    // It will round to the tenths place
    num = 500.2349;
    result = num.toPrecision(4); // result will equal 500.2

また、番号を固定にしたい場合

result = num.toFixed(2);
12
Syed Umar Ahmed

私はこの問題に対する正確な解決策を見つけられなかったので、私は私自身のものを作成しました:

function inprecise_round(value, decPlaces) {
  return Math.round(value*Math.pow(10,decPlaces))/Math.pow(10,decPlaces);
}

function precise_round(value, decPlaces){
    var val = value * Math.pow(10, decPlaces);
    var fraction = (Math.round((val-parseInt(val))*10)/10);

    //this line is for consistency with .NET Decimal.Round behavior
    // -342.055 => -342.06
    if(fraction == -0.5) fraction = -0.6;

    val = Math.round(parseInt(val) + fraction) / Math.pow(10, decPlaces);
    return val;
}

例:

function inprecise_round(value, decPlaces) {
  return Math.round(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
}

function precise_round(value, decPlaces) {
  var val = value * Math.pow(10, decPlaces);
  var fraction = (Math.round((val - parseInt(val)) * 10) / 10);

  //this line is for consistency with .NET Decimal.Round behavior
  // -342.055 => -342.06
  if (fraction == -0.5) fraction = -0.6;

  val = Math.round(parseInt(val) + fraction) / Math.pow(10, decPlaces);
  return val;
}

// This may produce different results depending on the browser environment
console.log("342.055.toFixed(2)         :", 342.055.toFixed(2)); // 342.06 on Chrome & IE10

console.log("inprecise_round(342.055, 2):", inprecise_round(342.055, 2)); // 342.05
console.log("precise_round(342.055, 2)  :", precise_round(342.055, 2));   // 342.06
console.log("precise_round(-342.055, 2) :", precise_round(-342.055, 2));  // -342.06

console.log("inprecise_round(0.565, 2)  :", inprecise_round(0.565, 2));   // 0.56
console.log("precise_round(0.565, 2)    :", precise_round(0.565, 2));     // 0.57
5

これは簡単なものです

function roundFloat(num,dec){
    var d = 1;
    for (var i=0; i<dec; i++){
        d += "0";
    }
    return Math.round(num * d) / d;
}

alert(roundFloat(1.79209243929,4));のように使う

Jsfiddle

3
ow3n

@heridevと私はjQueryで小さな関数を作成しました。

あなたは次に試すことができます:

HTML

<input type="text" name="one" class="two-digits"><br>
<input type="text" name="two" class="two-digits">​

jQuery

// apply the two-digits behaviour to elements with 'two-digits' as their class
$( function() {
    $('.two-digits').keyup(function(){
        if($(this).val().indexOf('.')!=-1){         
            if($(this).val().split(".")[1].length > 2){                
                if( isNaN( parseFloat( this.value ) ) ) return;
                this.value = parseFloat(this.value).toFixed(2);
            }  
         }            
         return this; //for chaining
    });
});

デモオンライン:

http://jsfiddle.net/c4Wqn/ /

3
vicmaster
/**
 * MidpointRounding away from zero ('arithmetic' rounding)
 * Uses a half-epsilon for correction. (This offsets IEEE-754
 * half-to-even rounding that was applied at the Edge cases).
 */

function RoundCorrect(num, precision = 2) {
        // half epsilon to correct Edge cases.
        var c = 0.5 * Number.EPSILON * num;
//      var p = Math.pow(10, precision); //slow
        var p = 1; while (precision--> 0) p *= 10;
        if (num < 0)
                p *= -1;
        return Math.round((num + c) * p) / p;
}

// testing some +ve Edge cases
console.log(RoundCorrect(1.005, 2));  // 1.01 correct
console.log(RoundCorrect(2.175, 2));  // 2.18 correct
console.log(RoundCorrect(5.015, 2));  // 5.02 correct

// testing some -ve Edge cases
console.log(RoundCorrect(-1.005, 2));  // -1.01 correct
console.log(RoundCorrect(-2.175, 2));  // -2.18 correct
console.log(RoundCorrect(-5.015, 2));  // -5.02 correct
2
Amr Ali

浮動小数点値の問題は、固定量のビットで無限量の(連続的な)値を表現しようとしていることです。ですから、当然、遊びにいくらかの損失があるはずです。そして、あなたはいくつかの価値に噛まれるでしょう。

コンピューターが1.275を浮動小数点値として保存するとき、それが1.275か1.27499999999999993か、さらには1.27500000000000002であったかどうかを実際には覚えていません。これらの値は、小数点以下2桁に丸めた後は異なる結果になるはずですが、浮動小数点値として保存した後はコンピューターでとまったく同じに見えるため、そうなりません、失われたデータを復元する方法はありません。さらに計算を行うと、そのような不正確さが蓄積されるだけです。

したがって、精度が重要な場合は、最初から浮動小数点値を使用しないでください。最も簡単なオプションは

  • 専用ライブラリ を使用します
  • 文字列を使用して値を格納および渡す(文字列操作を伴う)
  • 整数を使用します(たとえば、実際の値の100分の1の量を渡すことができます。たとえば、金額をドルではなくセントで指定します)

たとえば、整数を使用して100分の1の数を格納する場合、実際の値を見つけるための関数は非常に簡単です。

function descale(num, decimals) {
    var hasMinus = num < 0;
    var numString = Math.abs(num).toString();
    var precedingZeroes = '';
    for (var i = numString.length; i <= decimals; i++) {
        precedingZeroes += '0';
    }
    numString = precedingZeroes + numString;
    return (hasMinus ? '-' : '') 
        + numString.substr(0, numString.length-decimals) 
        + '.' 
        + numString.substr(numString.length-decimals);
}

alert(descale(127, 2));

文字列では、丸めが必要になりますが、それでも管理は可能です。

function precise_round(num, decimals) {
    var parts = num.split('.');
    var hasMinus = parts.length > 0 && parts[0].length > 0 && parts[0].charAt(0) == '-';
    var integralPart = parts.length == 0 ? '0' : (hasMinus ? parts[0].substr(1) : parts[0]);
    var decimalPart = parts.length > 1 ? parts[1] : '';
    if (decimalPart.length > decimals) {
        var roundOffNumber = decimalPart.charAt(decimals);
        decimalPart = decimalPart.substr(0, decimals);
        if ('56789'.indexOf(roundOffNumber) > -1) {
            var numbers = integralPart + decimalPart;
            var i = numbers.length;
            var trailingZeroes = '';
            var justOneAndTrailingZeroes = true;
            do {
                i--;
                var roundedNumber = '1234567890'.charAt(parseInt(numbers.charAt(i)));
                if (roundedNumber === '0') {
                    trailingZeroes += '0';
                } else {
                    numbers = numbers.substr(0, i) + roundedNumber + trailingZeroes;
                    justOneAndTrailingZeroes = false;
                    break;
                }
            } while (i > 0);
            if (justOneAndTrailingZeroes) {
                numbers = '1' + trailingZeroes;
            }
            integralPart = numbers.substr(0, numbers.length - decimals);
            decimalPart = numbers.substr(numbers.length - decimals);
        }
    } else {
        for (var i = decimalPart.length; i < decimals; i++) {
            decimalPart += '0';
        }
    }
    return (hasMinus ? '-' : '') + integralPart + (decimals > 0 ? '.' + decimalPart : '');
}

alert(precise_round('1.275', 2));
alert(precise_round('1.27499999999999993', 2));

この関数は最も近い値に丸め、ゼロから離れたところに丸めますIEEE 754 は最も近い値に丸めることを推奨します偶数との関係は、浮動小数点演算のデフォルトの動作です。このような変更は、読者のための演習として残されています:)

2
Imre

10進数値を四捨五入してから、予想桁数にtoFixed(x)を使用します。

function parseDecimalRoundAndFixed(num,dec){
  var d =  Math.pow(10,dec);
  return (Math.round(num * d) / d).toFixed(dec);
}

コール

parseDecimalRoundAndFixed(10.800243929,4)=> 10.80 parseDecimalRoundAndFixed(10.807243929,2)=> 10.81

2
HATCHA

これが私の1行ソリューションです:Number((yourNumericValueHere).toFixed(2));

これが起こるのです:

1)最初に、小数点以下を四捨五入する数値に.toFixed(2)を適用します。これは数値を数値から文字列に変換することに注意してください。あなたがTypeScriptを使っているのであれば、それはこのようなエラーを投げます:

"型 'string'は型 'number'に代入できません"

2)数値を取り戻す、または文字列を数値に変換するには、そのいわゆる「文字列」値にNumber()関数を適用するだけです。

明確にするために、以下の例を見てください。

例: 小数点以下5桁までの金額があり、小数点以下2桁まで短くしたい。私はそう好きです:

var price = 0.26453;
var priceRounded = Number((price).toFixed(2));
console.log('Original Price: ' + price);
console.log('Price Rounded: ' + priceRounded);
2
Devner

切り捨て

function round_down(value, decPlaces) {
    return Math.floor(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
}

切り上げ

function round_up(value, decPlaces) {
    return Math.ceil(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
}

四捨五入

function round_nearest(value, decPlaces) {
    return Math.round(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
}

https://stackoverflow.com/a/7641824/1889449https://www.kirupa.com/html5/rounding_numbers_in_javascript.htm ありがとうございました。

1
MERT DOĞAN

以下を をあるグローバルスコープに入れる:

Number.prototype.getDecimals = function ( decDigCount ) {
   return this.toFixed(decDigCount);
}

そして それから試してください

var a = 56.23232323;
a.getDecimals(2); // will return 56.23

更新

toFixed()0-20の間の小数点以下の桁数でしか機能しないことに注意してください。つまり、a.getDecimals(25)はJavaScriptエラーを生成する可能性があります。

Number.prototype.getDecimals = function ( decDigCount ) {
   return ( decDigCount > 20 ) ? this : this.toFixed(decDigCount);
}
1
Kamran Ahmed

こんなにシンプル。

var rounded_value=Math.round(value * 100) / 100;
1
Gihan Gamage
Number(Math.round(1.005+'e2')+'e-2'); // 1.01

これは私のために働いた: JavaScriptで丸め小数点以下の桁数

1
Max G

この応答を参照して使用する: https://stackoverflow.com/a/21029698/454827

動的な小数部を取得する関数を作成します。

function toDec(num, dec)
{
        if(typeof dec=='undefined' || dec<0)
                dec = 2;

        var tmp = dec + 1;
        for(var i=1; i<=tmp; i++)
                num = num * 10;

        num = num / 10;
        num = Math.round(num);
        for(var i=1; i<=dec; i++)
                num = num / 10;

        num = num.toFixed(dec);

        return num;
}

ここで作業例: https://jsfiddle.net/wpxLduLc/

1
ZiTAL
parse = function (data) {
       data = Math.round(data*Math.pow(10,2))/Math.pow(10,2);
       if (data != null) {
            var lastone = data.toString().split('').pop();
            if (lastone != '.') {
                 data = parseFloat(data);
            }
       }
       return data;
  };

$('#result').html(parse(200)); // output 200
$('#result1').html(parse(200.1)); // output 200.1
$('#result2').html(parse(200.10)); // output 200.1
$('#result3').html(parse(200.109)); // output 200.11
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div id="result"></div>
<div id="result1"></div>
<div id="result2"></div>
<div id="result3"></div>
1
Vishnu T Asok

私は数ヶ月前にこの記事からいくつかのアイデアを得ましたが、ここでの答えも他の記事/ブログからの答えもすべてのシナリオを処理することができませんでした。結局、私達のテスターは下記のこの方法に関する問題を見つけることができませんでした。私のコードの断片を貼り付ける:

fixPrecision: function (value) {
    var me = this,
        nan = isNaN(value),
        precision = me.decimalPrecision;

    if (nan || !value) {
        return nan ? '' : value;
    } else if (!me.allowDecimals || precision <= 0) {
        precision = 0;
    }

    //[1]
    //return parseFloat(Ext.Number.toFixed(parseFloat(value), precision));
    precision = precision || 0;
    var negMultiplier = value < 0 ? -1 : 1;

    //[2]
    var numWithExp = parseFloat(value + "e" + precision);
    var roundedNum = parseFloat(Math.round(Math.abs(numWithExp)) + 'e-' + precision) * negMultiplier;
    return parseFloat(roundedNum.toFixed(precision));
},

私はまたコードコメントを持っています(すみません私はすべての詳細をすでに忘れていました)...私は将来の参考のためにここに私の答えを投稿しています:

9.995 * 100 = 999.4999999999999
Whereas 9.995e2 = 999.5
This discrepancy causes Math.round(9.995 * 100) = 999 instead of 1000.
Use e notation instead of multiplying /dividing by Math.Pow(10,precision).
1
remondo

これらの例では、数値1.005を四捨五入しようとするとエラーが発生します。解決策はMath.jsのようなライブラリかこの関数を使うことです。

function round(value: number, decimals: number) {
    return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals);
}
1
David Webster
Number(((Math.random() * 100) + 1).toFixed(2))

これは、小数点以下2桁に丸められた1から100までの乱数を返します。

1
Johnathan Ralls
(Math.round((10.2)*100)/100).toFixed(2)

10.20が生成されます。

(Math.round((.05)*100)/100).toFixed(2)

0.05が生成されます。

(Math.round((4.04)*100)/100).toFixed(2)

4.04が生成されます。

等.

0
Anthony Ruffino

私はこの問題を解決するための非常に簡単な方法を見つけ、それを使用したり適応させたりすることができます。

td[row].innerHTML = price.toPrecision(price.toFixed(decimals).length
0
IRENE G

私は問題を修正する。 2つの10進数のみをサポートします。

$(function(){
  //input number only.
  convertNumberFloatZero(22); // output : 22.00
  convertNumberFloatZero(22.5); // output : 22.50
  convertNumberFloatZero(22.55); // output : 22.55
  convertNumberFloatZero(22.556); // output : 22.56
  convertNumberFloatZero(22.555); // output : 22.55
  convertNumberFloatZero(22.5541); // output : 22.54
  convertNumberFloatZero(22222.5541); // output : 22,222.54

  function convertNumberFloatZero(number){
        if(!$.isNumeric(number)){
                return 'NaN';
        }
        var numberFloat = number.toFixed(3);
        var splitNumber = numberFloat.split(".");
        var cNumberFloat = number.toFixed(2);
        var cNsplitNumber = cNumberFloat.split(".");
        var lastChar = splitNumber[1].substr(splitNumber[1].length - 1);
        if(lastChar > 0 && lastChar < 5){
                cNsplitNumber[1]--;
        }
        return Number(splitNumber[0]).toLocaleString('en').concat('.').concat(cNsplitNumber[1]);
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
0
bamossza

.toPrecision()メソッドといくつかのカスタムコードを使用することもでき、int部分の長さに関係なく、常にn番目の10進数に切り上げます。

function glbfrmt (number, decimals, seperator) {
    return typeof number !== 'number' ? number : number.toPrecision( number.toString().split(seperator)[0].length + decimals);
}

あなたはそれをより良い使用のためのプラグインにすることもできます。

0
leo_lo
/*Due to all told stuff. You may do 2 things for different purposes:
When showing/printing stuff use this in your alert/innerHtml= contents:
YourRebelNumber.toFixed(2)*/

var aNumber=9242.16;
var YourRebelNumber=aNumber-9000;
alert(YourRebelNumber);
alert(YourRebelNumber.toFixed(2));

/*and when comparing use:
Number(YourRebelNumber.toFixed(2))*/

if(YourRebelNumber==242.16)alert("Not Rounded");
if(Number(YourRebelNumber.toFixed(2))==242.16)alert("Rounded");

/*Number will behave as you want in that moment. After that, it'll return to its defiance.
*/
0

これは非常に単純で、他のものと同じように機能します。

function parseNumber(val, decimalPlaces) {
    if (decimalPlaces == null) decimalPlaces = 0
    var ret = Number(val).toFixed(decimalPlaces)
    return Number(ret)
}

ToFixed()は数字でしか呼び出せず、残念ながら文字列を返すので、これは両方向のすべての解析を行います。あなたは文字列や数字を渡すことができ、あなたは毎回戻って数字を得る! parseNumber(1.49)を呼び出すと1が得られ、parseNumber(1.49,2)を呼び出すと1.50が得られます。最高のものと同じように!

0
Aaron Dake