四捨五入せずに数値を小数点以下2桁に切り捨てます


194

15.7784514という値があるとすると、丸めなしで15.77を表示したいとします。

var num = parseFloat(15.7784514);
document.write(num.toFixed(1)+"<br />");
document.write(num.toFixed(2)+"<br />");
document.write(num.toFixed(3)+"<br />");
document.write(num.toFixed(10));

結果-

15.8
15.78
15.778
15.7784514000 

15.77を表示するにはどうすればよいですか?


3
どうして丸めたくないのですか?それはどこにいても正しくないようです...
カミロマーティン

38
通貨を表示するときに便利です。
Richard Ye

@ mik01aj-通貨を表示する場合、計算値を四捨五入するのではなく、切り捨てる方が一般的です。たとえば、米国のほとんどの税務フォームは、計算された小数セントを丸めるのではなく切り捨てます。その場合、切り捨てられた値は正しい値です。
Steven Byks 2017

4
@CamiloMartinは、14.9億ドルの借金と10億ドルの借金の間に大きな違いがあります。
Broda Noel、

3
14.9億ドルと15.0億ドルの間にも大きな違いがあります。それは1億ドルです。
リガ

回答:


226

数値を文字列に変換し、小数点以下第2位までの数値に一致させます。

function calc(theform) {
    var num = theform.original.value, rounded = theform.rounded
    var with2Decimals = num.toString().match(/^-?\d+(?:\.\d{0,2})?/)[0]
    rounded.value = with2Decimals
}
<form onsubmit="return calc(this)">
Original number: <input name="original" type="text" onkeyup="calc(form)" onchange="calc(form)" />
<br />"Rounded" number: <input name="rounded" type="text" placeholder="readonly" readonly>
</form>

toFixedとは異なりtoString、このメソッドは失敗する場合がありますので、十分に注意してください。


22
+1これで丸めの問題が解決されます。toFixedただし、上記の結果はを使用して出力します(Math.floor(value * 100) / 100).toFixed(2)。おそらくご存じのとおり、浮動小数点値では奇妙な精度の問題が発生する可能性があります(スペクトルの反対側では、数値が偶然である場合15、OPが望むように聞こえます15.00)。
TJクラウダー、

1
hehe、または両方を組み合わせた場合:Number((15.7784514000*100).toString().match(/^\d+/)/100);
skobaljic 2013年

27
Math.floor(value * 100)/ 100は、value = 4.27を真剣に使用すると機能しません。試してください。
Dark Hippo 2014年

3
@DarkHippoそれは、4.27が実際には4.26999999999であるため、元の質問に対する答えではありませんが、Math.roundの方が一般に優れたソリューションです。現実的には出力が文字列である場合、これはすべての浮動小数点の可能性のある数値解の代わりに文字列操作を使用して行う必要があります。
BJury 2014

3
...それは正しく聞こえません。どんな状況下でも型間の変換は迂回的で安全ではないようです。本当に上級のプログラマーが「すべての型は単なるストリームである」とか何かと主張しない限り。
JackHasaKeyboard 2017

66

2016年11月5日更新

新しい答え、常に正確

function toFixed(num, fixed) {
    var re = new RegExp('^-?\\d+(?:\.\\d{0,' + (fixed || -1) + '})?');
    return num.toString().match(re)[0];
}

JavaScriptで浮動小数点演算をすることは常にエッジケースを持っています、以前のソリューションは良い十分ではありませんほとんどの時間を正確になります。BigDecimal.jsaccounting.jsなどnum.toPrecision、これに対するいくつかの解決策があります。それでも、文字列を解析するだけが最も単純で常に正確であると私は信じています。

@Gumboが受け入れた回答からのよく書かれた正規表現に基づいて更新を行うと、この新しいtoFixed関数は常に期待どおりに機能します。


古い答え、必ずしも正確ではありません。

独自のtoFixed関数をロールします。

function toFixed(num, fixed) {
    fixed = fixed || 0;
    fixed = Math.pow(10, fixed);
    return Math.floor(num * fixed) / fixed;
}

7
toFixed(4.56、2)= 4.55
2016年

2
これらの答えの多くは、Math.floor()関数内で乗算を持っています。これはいくつかの数字では失敗します!浮動小数点演算は正確ではないため、さまざまな方法を使用する必要があります。
Nico Westerdale、2016年

1
function toFixedCustom(num、fixed){var re = new RegExp( '^-?\\ d +(?:\。\\ d {0、' +(fixed || -1)+ '})?'); if(num.toString()。match(re)){return num.toString()。match(re)[0]; }}
ライアンオーガスティン

1
更新された回答は、javascriptが科学的表記法で表すのに十分な大きさまたは数の場合、失敗します。toFixed(0.0000000052, 2)'5.2'を返します。これはreturn num.toFixed(fixed+1).match(re)[0];、丸めを回避するためにターゲットの小数点以下1桁でtoFixedを使用していることに注意してから修正できます。次に、正規表現一致を実行します
Netherdan

32

代わりに文字列を使用して残りを手動で削除するためにこれを書くことを選択したので、数値に付随する数学の問題に対処する必要はありません。

num = num.toString(); //If it's not already a String
num = num.slice(0, (num.indexOf("."))+3); //With 3 exposing the hundredths place
Number(num); //If you need it back as a Number

これにより、num = 15.7784514で「15.77」が得られます。


5
小数を強制しない場合は、整数に遭遇した場合に備えて条件を追加することができます。このように:num = num.toString(); if(num.indexOf( "。")> 0){num = num.slice(0、(num.indexOf( "。"))+ 3)}; Number(num);
ベンノスケ

1
小数がある場合はいいですが、整数の場合は失敗します
RuslanLópezJun

numが0.00000052の場合、5.2eを取得するのは誤りです
Vasanth

1
@Vasanth数値が0.00000052の場合、「0.00」を返します。多分答えは以来編集されました
ドレナイ

ええ、それはエッジケースで失敗します
VPaul

18

2017年10月

数値をn番目の10進数に切り捨て(丸めなし)、nが0以上の場合は、n桁のn桁の文字列に変換する一般的なソリューション。

function toFixedTrunc(x, n) {
  const v = (typeof x === 'string' ? x : x.toString()).split('.');
  if (n <= 0) return v[0];
  let f = v[1] || '';
  if (f.length > n) return `${v[0]}.${f.substr(0,n)}`;
  while (f.length < n) f += '0';
  return `${v[0]}.${f}`
}

ここで、xは数値(文字列に変換される)または文字列のいずれかです。

以下は、n = 2(OPによって要求されたものを含む)のいくつかのテストです。

0           => 0.00
0.01        => 0.01
0.5839      => 0.58
0.999       => 0.99
1.01        => 1.01
2           => 2.00
2.551       => 2.55
2.99999     => 2.99
4.27        => 4.27
15.7784514  => 15.77
123.5999    => 123.59
0.000000199 => 1.99 *

*ノートで述べたように、これは「1.99e-7」およびnの他のいくつかの値について、JavaScriptが指数関数に暗黙的に変換するためです。

15.001097   => 15.0010 (n=4)
0.000003298 => 0.0000032 (n=7)
0.000003298257899 => 0.000003298257 (n=12)

2
toFixedTrunc(0.000000199, 2) // 1.99
マハラモフ

1
@ShamkhalMaharramov:開発コンソールを開いて0.000000199と入力すると、何が表示されますか?1.99e-7になります。また、0.000000199.toString()と入力すると、何が得られますか?「1.99e-7」を取得するので、関数に0.000000199を渡すと、「0.000000199」ではなく「1.99e-7」で動作し、「正しく」「1.99」を返します。ecma-international.org/ecma-262/6.0/…を
SC1000

13

parseIntはMath.floorより高速です

function floorFigure(figure, decimals){
    if (!decimals) decimals = 2;
    var d = Math.pow(10,decimals);
    return (parseInt(figure*d)/d).toFixed(decimals);
};

floorFigure(123.5999)    =>   "123.59"
floorFigure(123.5999, 3) =>   "123.599"

2
それは1234567.89で失敗
ルスラン・ロペス

ロペスを詳しく説明していただけませんか?
zardilior

3
floorFigure(4.56、2)= 4.55
2016年


6
num = 19.66752
f = num.toFixed(3).slice(0,-1)
alert(f)

これは19.66を返します


5
(4.9999).toFixed(3).slice(0、-1)は5.00を返します。期待される結果は4.99です。
Bruno Lemos

1
代わりに.toFixed(6).slice(0、-4)のようなものを使用することをお勧めします。
Bruno Lemos

それは完璧です、私の場合は大丈夫です。たとえば、10進数を1つにしたい場合は、num.toFixed(2).slice(0、-1)を使用します(numが1.2356の場合、1.2を返します)
Esteban Perez

5

これらのソリューションは機能しますが、私には不必要に複雑に見えます。個人的には、剰余演算子を使用して残りの除算演算を取得し、それを削除するのが好きです。num = 15.7784514と仮定すると、

num-=num%.01;

これは、num = num-(num%.01)と同じです。


それは興味深いNijkokunです。指摘してくれてありがとう。私はこのテクニックを使用して問題に遭遇したことはありませんが、このようなインスタンスを詳しく調べる必要があることは明らかです。別の方法として、この問題を解決する((num * = 100)-(num%1))/ 100を使用できます。私の場合の優先順位は、これを適用する計算量が多いため実行速度です。これは、これを実現するための最も速い方法です。
jtrick 2015

1
ポイントは、提供される他のソリューションで必要なオブジェクトと関数のルックアップと変換を回避することでした。フィードバックをお寄せいただきありがとうございます!
jtrick 2015

1
ネガティブ-5でも失敗
RuslanLópez

また、高速な丸めにも興味があります。このコードで10進数で1を実行するにはどうすればよいですか。
thednp 2016

5

ここでの答えは私を助けませんでした、それは切り上げ続けるか、間違った小数を私に与え続けました。

私の解決策は、10進数を文字列に変換し、文字を抽出して、全体を数値として返します。

function Dec2(num) {
  num = String(num);
  if(num.indexOf('.') !== -1) {
    var numarr = num.split(".");
    if (numarr.length == 1) {
      return Number(num);
    }
    else {
      return Number(numarr[0]+"."+numarr[1].charAt(0)+numarr[1].charAt(1));
    }
  }
  else {
    return Number(num);
  }  
}

Dec2(99); // 99
Dec2(99.9999999); // 99.99
Dec2(99.35154); // 99.35
Dec2(99.8); // 99.8
Dec2(10265.985475); // 10265.98

Dec2(99)は99.00を返します
VPaul

5

正の数の私のバージョン:

function toFixed_norounding(n,p)
{
    var result = n.toFixed(p);
    return result <= n ? result: (result - Math.pow(0.1,p)).toFixed(p);
}

高速、かなり、明白です。(正数のバージョン)


小数が1つだけの浮動小数点値(マネーなど)の非丸めが必要でした。上記の関数は、このトピックの「答え」である必要があります。それは優れており、魅力のように機能します。作者を乾杯&感謝します。:)))
エイドリアン棚瀬

負の値のために失敗しました。-0.7752。代わりにtoFixed_norounding(-0.7752,2)戻るテスト -0.78-0.77
Ling Loeng 2018年

4

次のコードは私にとって非常にうまくいきます:

num.toString().match(/.\*\\..{0,2}|.\*/)[0];

私はそれを完璧にするために、オプションのマイナス記号が追加されます-?。)
ルスラン・ロペスに

3

私は次の簡単な方法を使用して修正しました-

var num = 15.7784514;
Math.floor(num*100)/100;

結果は15.77になります


:それは負の値では動作しません-15.7784514リターン-15.78
クレマンBaconnier

3

数字を切り捨てるだけです:

function truncDigits(inputNumber, digits) {
  const fact = 10 ** digits;
  return Math.floor(inputNumber * fact) / fact;
}

3

別の単一行ソリューション:

number = Math.trunc(number*100)/100

2桁目まで切り捨てたいので100を使用しましたが、より柔軟な解決策は次のようになります。

number = Math.trunc(number*Math.pow(10, digits))/Math.pow(10, digits)

ここで、digitsは保持する10進数の桁数です。

参照してくださいMath.truncの仕様詳細やブラウザの互換性のために。


1
これは、IE11をサポートする必要がない場合の最良の答えです。
TJ。

2

はい、どうぞ。問題を解決するさらに別の方法を示す答え:

// For the sake of simplicity, here is a complete function:
function truncate(numToBeTruncated, numOfDecimals) {
    var theNumber = numToBeTruncated.toString();
    var pointIndex = theNumber.indexOf('.');
    return +(theNumber.slice(0, pointIndex > -1 ? ++numOfDecimals + pointIndex : undefined));
}

最後の式の前に+を使用していることに注意してください。これは、切り捨てられスライスされた文字列を数値型に戻すことです。

それが役に立てば幸い!


1
私はこのアプローチの単純さを気に入っており、数学の使用を回避するすべてのソリューションがこの問題を解決するのにより適切であると感じています。したがって、slice()などを使用するのが正しい方法です。私のメソッドの唯一の利点は、渡された数値が文字列である[引用符で囲まれた[シングル/ダブル]]を処理することです。なんらかの理由で、上記の関数がFFでエラーをスローしました。
Charles Robertson 2017年

2

ゼロなしで切り捨て

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

または

function toTrunc(value,n){
    x=(value.toString()+".0").split(".");
    return parseFloat(x[0]+"."+x[1].substr(0,n));
}

テスト:

toTrunc(17.4532,2)  //17.45
toTrunc(177.4532,1) //177.4
toTrunc(1.4532,1)   //1.4
toTrunc(.4,2)       //0.4

ゼロで切り捨て

function toTruncFixed(value,n){
    return toTrunc(value,n).toFixed(n);
}

テスト:

toTrunc(17.4532,2)  //17.45
toTrunc(177.4532,1) //177.4
toTrunc(1.4532,1)   //1.4
toTrunc(.4,2)       //0.40

2

これは私にはうまくいきました。私もそれがあなたの問題を解決することを願っています。

function toFixedNumber(number) {
    const spitedValues = String(number.toLocaleString()).split('.');
    let decimalValue = spitedValues.length > 1 ? spitedValues[1] : '';
    decimalValue = decimalValue.concat('00').substr(0,2);

    return '$'+spitedValues[0] + '.' + decimalValue;
}

// 5.56789      ---->  $5.56
// 0.342        ---->  $0.34
// -10.3484534  ---->  $-10.34 
// 600          ---->  $600.00

function convertNumber(){
  var result = toFixedNumber(document.getElementById("valueText").value);
  document.getElementById("resultText").value = result;
}


function toFixedNumber(number) {
        const spitedValues = String(number.toLocaleString()).split('.');
        let decimalValue = spitedValues.length > 1 ? spitedValues[1] : '';
        decimalValue = decimalValue.concat('00').substr(0,2);

        return '$'+spitedValues[0] + '.' + decimalValue;
}
<div>
  <input type="text" id="valueText" placeholder="Input value here..">
  <br>
  <button onclick="convertNumber()" >Convert</button>
  <br><hr>
  <input type="text" id="resultText" placeholder="result" readonly="true">
</div>


2

これを行う簡単な方法は次ですが、amountパラメータが文字列として指定されていることを確認する必要があります。

function truncate(amountAsString, decimals = 2){
  var dotIndex = amountAsString.indexOf('.');
  var toTruncate = dotIndex !== -1  && ( amountAsString.length > dotIndex + decimals + 1);
  var approach = Math.pow(10, decimals);
  var amountToTruncate = toTruncate ? amountAsString.slice(0, dotIndex + decimals +1) : amountAsString;  
  return toTruncate
    ?  Math.floor(parseFloat(amountToTruncate) * approach ) / approach
    :  parseFloat(amountAsString);

}

console.log(truncate("7.99999")); //OUTPUT ==> 7.99
console.log(truncate("7.99999", 3)); //OUTPUT ==> 7.999
console.log(truncate("12.799999999999999")); //OUTPUT ==> 7.99

2

function formatLimitDecimals(value, decimals) {
  value = value.toString().split('.')

  if (value.length === 2) {
    return Number([value[0], value[1].slice(0, decimals)].join('.'))
  } else {
    return Number(value[0]);
  }
}

console.log(formatLimitDecimals(4.156, 2)); // 4.15
console.log(formatLimitDecimals(4.156, 8)); // 4.156
console.log(formatLimitDecimals(4.156, 0)); // 4


1

(num-0.05).toFixed(1)は、2番目の10進数の床を使用していた。


1

typescriptでの私の解決策(JSに簡単に移植できます):

/**
 * Returns the price with correct precision as a string
 *
 * @param   price The price in decimal to be formatted.
 * @param   decimalPlaces The number of decimal places to use
 * @return  string The price in Decimal formatting.
 */
type toDecimal = (price: number, decimalPlaces?: number) => string;
const toDecimalOdds: toDecimal = (
  price: number,
  decimalPlaces: number = 2,
): string => {
  const priceString: string = price.toString();
  const pointIndex: number = priceString.indexOf('.');

  // Return the integer part if decimalPlaces is 0
  if (decimalPlaces === 0) {
    return priceString.substr(0, pointIndex);
  }

  // Return value with 0s appended after decimal if the price is an integer
  if (pointIndex === -1) {
    const padZeroString: string = '0'.repeat(decimalPlaces);

    return `${priceString}.${padZeroString}`;
  }

  // If numbers after decimal are less than decimalPlaces, append with 0s
  const padZeroLen: number = priceString.length - pointIndex - 1;
  if (padZeroLen > 0 && padZeroLen < decimalPlaces) {
    const padZeroString: string = '0'.repeat(padZeroLen);

    return `${priceString}${padZeroString}`;
  }

  return priceString.substr(0, pointIndex + decimalPlaces + 1);
};

テストケース:

  expect(filters.toDecimalOdds(3.14159)).toBe('3.14');
  expect(filters.toDecimalOdds(3.14159, 2)).toBe('3.14');
  expect(filters.toDecimalOdds(3.14159, 0)).toBe('3');
  expect(filters.toDecimalOdds(3.14159, 10)).toBe('3.1415900000');
  expect(filters.toDecimalOdds(8.2)).toBe('8.20');

何か改善はありますか?


0

独自のtoFixed関数をロールしますMath.floor。正の値の場合は正常に機能します。

function toFixed(num, fixed) {
    fixed = fixed || 0;
    fixed = Math.pow(10, fixed);
    return Math.floor(num * fixed) / fixed;
}

負の値の場合、値Math.floorは丸められます。だからあなたは使うことができますMath.ceil代わりに。

例、

Math.ceil(-15.778665 * 10000) / 10000 = -15.7786
Math.floor(-15.778665 * 10000) / 10000 = -15.7787 // wrong.

5
これらの答えの多くは、Math.floor()関数内で乗算を持っています。これはいくつかの数字では失敗します!浮動小数点演算は正確ではないため、さまざまな方法を使用する必要があります。
Nico Westerdale、2016年

0

正規表現を使用するGumboの2番目のソリューションは機能しますが、正規表現のために遅くなります。Gumboの最初のソリューションは、浮動小数点数が不正確であるため、特定の状況で失敗します。デモとベンチマークについては、JSFiddleを参照してください。2番目のソリューションは、現在のシステムであるIntel Core i5-2500 CPU(3.30 GHz)で1コールあたり約1636ナノ秒かかります。

私が書いたソリューションには、浮動小数点の不正確さを処理するための小さな補正が含まれています。それは基本的に瞬時、すなわちナノ秒のオーダーです。呼び出しごとに2ナノ秒の時間を計測しましたが、JavaScriptタイマーの精度や精度はあまり高くありません。ここにJSフィドルとコードがあります。

function toFixedWithoutRounding (value, precision)
{
    var factorError = Math.pow(10, 14);
    var factorTruncate = Math.pow(10, 14 - precision);
    var factorDecimal = Math.pow(10, precision);
    return Math.floor(Math.floor(value * factorError + 1) / factorTruncate) / factorDecimal;
}

var values = [1.1299999999, 1.13, 1.139999999, 1.14, 1.14000000001, 1.13 * 100];

for (var i = 0; i < values.length; i++)
{
    var value = values[i];
    console.log(value + " --> " + toFixedWithoutRounding(value, 2));
}

for (var i = 0; i < values.length; i++)
{
    var value = values[i];
    console.log(value + " --> " + toFixedWithoutRounding(value, 4));
}

console.log("type of result is " + typeof toFixedWithoutRounding(1.13 * 100 / 100, 2));

// Benchmark
var value = 1.13 * 100;
var startTime = new Date();
var numRun = 1000000;
var nanosecondsPerMilliseconds = 1000000;

for (var run = 0; run < numRun; run++)
    toFixedWithoutRounding(value, 2);

var endTime = new Date();
var timeDiffNs = nanosecondsPerMilliseconds * (endTime - startTime);
var timePerCallNs = timeDiffNs / numRun;
console.log("Time per call (nanoseconds): " + timePerCallNs);

0

デビッドDの答えに基づいて:

function NumberFormat(num,n) {
  var num = (arguments[0] != null) ? arguments[0] : 0;
  var n = (arguments[1] != null) ? arguments[1] : 2;
  if(num > 0){
    num = String(num);
    if(num.indexOf('.') !== -1) {
      var numarr = num.split(".");
      if (numarr.length > 1) {
        if(n > 0){
          var temp = numarr[0] + ".";
          for(var i = 0; i < n; i++){
            if(i < numarr[1].length){
              temp += numarr[1].charAt(i);
            }
          }
          num = Number(temp);
        }
      }
    }
  }
  return Number(num);
}

console.log('NumberFormat(123.85,2)',NumberFormat(123.85,2));
console.log('NumberFormat(123.851,2)',NumberFormat(123.851,2));
console.log('NumberFormat(0.85,2)',NumberFormat(0.85,2));
console.log('NumberFormat(0.851,2)',NumberFormat(0.851,2));
console.log('NumberFormat(0.85156,2)',NumberFormat(0.85156,2));
console.log('NumberFormat(0.85156,4)',NumberFormat(0.85156,4));
console.log('NumberFormat(0.85156,8)',NumberFormat(0.85156,8));
console.log('NumberFormat(".85156",2)',NumberFormat(".85156",2));
console.log('NumberFormat("0.85156",2)',NumberFormat("0.85156",2));
console.log('NumberFormat("1005.85156",2)',NumberFormat("1005.85156",2));
console.log('NumberFormat("0",2)',NumberFormat("0",2));
console.log('NumberFormat("",2)',NumberFormat("",2));
console.log('NumberFormat(85156,8)',NumberFormat(85156,8));
console.log('NumberFormat("85156",2)',NumberFormat("85156",2));
console.log('NumberFormat("85156.",2)',NumberFormat("85156.",2));

// NumberFormat(123.85,2) 123.85
// NumberFormat(123.851,2) 123.85
// NumberFormat(0.85,2) 0.85
// NumberFormat(0.851,2) 0.85
// NumberFormat(0.85156,2) 0.85
// NumberFormat(0.85156,4) 0.8515
// NumberFormat(0.85156,8) 0.85156
// NumberFormat(".85156",2) 0.85
// NumberFormat("0.85156",2) 0.85
// NumberFormat("1005.85156",2) 1005.85
// NumberFormat("0",2) 0
// NumberFormat("",2) 0
// NumberFormat(85156,8) 85156
// NumberFormat("85156",2) 85156
// NumberFormat("85156.",2) 85156


0

すでに正規表現と算術計算でいくつかの適切な答えがあります、これを試すこともできます

function myFunction() {
    var str = 12.234556; 
    str = str.toString().split('.');
    var res = str[1].slice(0, 2);
    document.getElementById("demo").innerHTML = str[0]+'.'+res;
}

// output: 12.23

0

これは文字列で何をしたかです

export function withoutRange(number) {
  const str = String(number);
  const dotPosition = str.indexOf('.');
  if (dotPosition > 0) {
    const length = str.substring().length;
    const end = length > 3 ? 3 : length;
    return str.substring(0, dotPosition + end);
  }
  return str;
}

0

これらすべての答えは少し複雑に見えます。私はあなたの数から0.5を引いてtoFixed()を使うだけです。


あなたは0.005を意味しましたか?
Luan Nguyen

0

(2小数桁の場合)最も効率的な解決策は、呼び出す前に0.005を引くことです。 toFixed()

function toFixed2( num ) { return (num-0.005).toFixed(2) }

負の数も切り捨てられます(ゼロから離れて)。OPは負の数について何も伝えませんでした。


0

実用的な例はすでにいくつかあることは知っていますが、私のString.toFixedと同等のものを提案することは価値があると思います。

それが私のtoFixedの代替案であり、数値を丸めず、単に切り捨てるか、指定された精度に従ってゼロを追加します。非常に長い数値の場合、精度が長すぎる場合は、JSの組み込み丸めを使用します。スタックで見つけた問題のあるすべての番号で機能します。

function toFixedFixed(value, precision = 0) {
    let stringValue = isNaN(+value) ? '0' : String(+value);

    if (stringValue.indexOf('e') > -1 || stringValue === 'Infinity' || stringValue === '-Infinity') {
        throw new Error('To large number to be processed');
    }

    let [ beforePoint, afterPoint ] = stringValue.indexOf('.') > -1 ? stringValue.split('.') : [ stringValue, ''];

    // Force automatic rounding for some long real numbers that ends with 99X, by converting it to string, cutting off last digit, then adding extra nines and casting it on number again
    // e.g. 2.0199999999999996: +('2.019999999999999' + '9999') will give 2.02
    if (stringValue.length >= 17 && afterPoint.length > 2 && +afterPoint.substr(afterPoint.length - 3) > 995) {
        stringValue = String(+(stringValue.substr(0, afterPoint.length - 1) + '9'.repeat(stringValue.split('.').shift().length + 4)));
        [ beforePoint, afterPoint ] = String(stringValue).indexOf('.') > -1 ? stringValue.split('.') : [ stringValue, ''];
    }

    if (precision === 0) {
        return beforePoint;
    } else if (afterPoint.length > precision) {
        return `${beforePoint}.${afterPoint.substr(0, precision)}`;
    } else {
        return `${beforePoint}.${afterPoint}${'0'.repeat(precision - afterPoint.length)}`;
    }
}

長さが18以上の数値では精度が適切に処理されない場合があることに注意してください。たとえば、64ビットのChromeは四捨五入するか、「e +」/「e-」を追加して数値の長さを18に保ちます。

実数で演算を実行したい場合は、それを乗算する方が安全です Math.sqrt(10, precision)最初に、計算を行ってから、乗数の値で結果をダイビングする方がです。

例:

0.06 + 0.01is 0.06999999999999999であり、丸めではないすべてのフォーマット関数は、0.06精度のためにそれを切り捨てます2ます。

しかし、multiplied&divider:(0.06 * 100 + 0.01 * 100) / 100で同じ演算を実行すると、が得られ0.07ます。

そのため、JavaScriptで実数を処理する場合、特に金額を計算する場合は、このような乗数/除算器を使用することが非常に重要です...

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