javascriptの10進数を切り捨てる(四捨五入しない)


93

小数点以下の桁数を切り捨てようとしています。このようなもの:

5.467   -> 5.46  
985.943 -> 985.94

toFixed(2)ほぼ正しいことをしますが、値を四捨五入します。値を四捨五入する必要はありません。これがjavascriptで可能であることを願っています。


6
jQueryは単なるフレームワークであり、問​​題はjQueryに関連していません。それはJavaScriptでいくつかの基本的な計算を行うことについてです。jQuery以外のソリューションにも満足していただければ幸いです。
Felix Kling 2011

Javascriptを使用して計算で小数点以下2桁を返すには、手間がかかりすぎることがわかりました。代わりに、データベースビューで簡単に行うことができました。この方法はすべての状況に適合するわけではないことはわかっていますが、誰かの時間を大幅に節約できる可能性があるため、ここに示したいと思います。
msTapp 2016年

回答:


51

upd

したがって、結局のところ、丸めるバグは、それを補おうとしても、常にあなたを悩ませます。したがって、問題は、数値を10進表記で正確に表すことによって攻撃する必要があります。

Number.prototype.toFixedDown = function(digits) {
    var re = new RegExp("(\\d+\\.\\d{" + digits + "})(\\d)"),
        m = this.toString().match(re);
    return m ? parseFloat(m[1]) : this.valueOf();
};

[   5.467.toFixedDown(2),
    985.943.toFixedDown(2),
    17.56.toFixedDown(2),
    (0).toFixedDown(1),
    1.11.toFixedDown(1) + 22];

// [5.46, 985.94, 17.56, 0, 23.1]

他の人のコンパイルに基づく古いエラーが発生しやすいソリューション ':

Number.prototype.toFixedDown = function(digits) {
  var n = this - Math.pow(10, -digits)/2;
  n += n / Math.pow(2, 53); // added 1360765523: 17.56.toFixedDown(2) === "17.56"
  return n.toFixed(digits);
}

4
ええ、プロトタイプはクロスブラウザで確実に機能しません。型システムを介してこの(目的が限定された)関数を定義する代わりに、確実に機能しない方法で、ライブラリに配置してみませんか。
トーマスW

3
これは例外として機能しません。数値17.56と数字= 2を試してください。17.56である必要がありますが、この関数は17.55を返します。
shendz 2013

2
この関数との2つの矛盾:この関数は文字列を返すため1.11.toFixedDown(1) + 22、の1.122代わりになり23.1ます。また、0.toFixedDown(1)生成する必要0がありますが、代わりにを生成し-0.1ます。
Nick Knowlson 2014年

5
この関数は負の符号を削除することに注意してください。例:(-10.2131).toFixedDown(2) // ==> 10.21
rgajrawala 2014

4
また、(1e-7).toFixedDown(0) // ==> 1e-7。以下のためにそれを行います1e-(>=7)(例:1e-81e-9、...)。
rgajrawala 2014

60

Dogbertの答えは良いですが、コードが負の数を処理する必要がある場合、Math.floorそれ自体で予期しない結果が生じる可能性があります。

例:Math.floor(4.3) = 4しかしMath.floor(-4.3) = -5

一貫した結果を得るには、代わりにこのようなヘルパー関数を使用してください。

truncateDecimals = function (number) {
    return Math[number < 0 ? 'ceil' : 'floor'](number);
};

// Applied to Dogbert's answer:
var a = 5.467;
var truncated = truncateDecimals(a * 100) / 100; // = 5.46

この関数のより便利なバージョンは次のとおりです。

truncateDecimals = function (number, digits) {
    var multiplier = Math.pow(10, digits),
        adjustedNum = number * multiplier,
        truncatedNum = Math[adjustedNum < 0 ? 'ceil' : 'floor'](adjustedNum);

    return truncatedNum / multiplier;
};

// Usage:
var a = 5.467;
var truncated = truncateDecimals(a, 2); // = 5.46

// Negative digits:
var b = 4235.24;
var truncated = truncateDecimals(b, -2); // = 4200

それが望ましくない動作である場合はMath.abs、最初の行にへの呼び出しを挿入します。

var multiplier = Math.pow(10, Math.abs(digits)),

編集: shendzは、このソリューションをで使用するa = 17.56と誤ってが生成されることを正しく指摘してい17.55ます。これが発生する理由の詳細については、すべてのコンピューター科学者が浮動小数点演算について知っておくべきことをお読みください。。残念ながら、浮動小数点エラーのすべての原因を排除するソリューションを作成することは、javascriptではかなり注意が必要です。別の言語では、整数型または10進型を使用しますが、JavaScriptを使用します...

このソリューション100%正確である必要がありますが、速度も遅くなります。

function truncateDecimals (num, digits) {
    var numS = num.toString(),
        decPos = numS.indexOf('.'),
        substrLength = decPos == -1 ? numS.length : 1 + decPos + digits,
        trimmedResult = numS.substr(0, substrLength),
        finalResult = isNaN(trimmedResult) ? 0 : trimmedResult;

    return parseFloat(finalResult);
}

速度が必要であるが浮動小数点エラーを回避したい場合は、BigDecimal.jsのようなものを試してください。このSOの質問で他のjavascriptBigDecimalライブラリを見つけることができます:「良いJavascriptBigDecimalライブラリはありますか?」これがJavascriptの数学ライブラリに関する良いブログ投稿です


なぜ予期しないのですか?0未満になったときに丸めの方向を変更すると、あらゆる種類の算術アーティファクトとくだらない数学が発生します。たとえば、他の整数の2倍の数が0に丸められます。グラフィックス、会計、その他の多くの用途では、ひどい結果が得られます。実を言うと、あなたの提案が何に適しているかを言うのは、そうでないことを言うのと同じくらい難しいでしょう。
トーマスW

四捨五入ではなく小数を切り捨てたい場合は、まさにその内容に適しています。
Nick Knowlson 2012年

1
ブラウザが1756ではなく17.56 * 100 = 1755.9999999999998を提供するため、17.56では機能しません
shendz 2013

良い点シェンズ。私はそれを必要とする人々のためにすべての浮動小数点エラーを排除する解決策で私の答えを更新しました。
Nick Knowlson 2013年

1
これは、小数を必要としない場合、1未満の数値では機能しません。truncateDecimals(.12345、0)は、チェックを追加しない限りNaNに if(isNAN(result) result = 0; なります。必要な動作によって異なります。
Jeremy Witmer 2013

35
var a = 5.467;
var truncated = Math.floor(a * 100) / 100; // = 5.46

5
これはうまく機能しますが、彼(または後でこの答えを見る誰か)が負の数を処理しなければならない場合、おそらく望ましくない結果が得られます。stackoverflow.com/a/9232092/224354
Nick Knowlson 2012

3
なぜ望ましくないのですか?0未満になったときに丸めの方向を変更すると、あらゆる種類の算術アーティファクトが発生します。
トーマスW

8
丸めと切り捨てには違いがあります。切り捨ては、明らかにこの質問が求めている動作です。私が電話して返事truncate(-3.14)をもらっ-4たら、それは間違いなく望ましくないと思います。
Nick Knowlson 2013

トーマスに同意します。パースペクティブの違いは、通常、表示のために切り捨てているのか、計算のために切り捨てているのかによって生じる場合があります。計算の観点から、これは「算術アーティファクト」を回避します

3
var a = 65.1 var truncated = Math.floor(a * 100) / 100; // = 65.09 したがって、これは正しい解決策ではありません
Sanyam Jain 2017

22

toFixedの0.5を引くことで、丸めを修正できます。

(f - 0.005).toFixed(2)

1
注意:これは、非常に小さい数、小数点以下3桁を超える数、または負の数では機能しません。.0045、5.4678、および-5.467を試してください
Nick Knowlson 2013年

これは、減算する値が必要な長さと一致する限り機能します。toFixed()に渡すものはすべて、小数点以下の0の数である必要があります。
dmarra 2018

18

ダブルチルダを利用することを~~検討しください。

番号を取ります。を使用してゼロ桁に切り捨てられるように、小数点以下の有効数字を乗算します~~。その乗数を分割して戻します。利益。

function truncator(numToTruncate, intDecimalPlaces) {    
    var numPower = Math.pow(10, intDecimalPlaces); // "numPowerConverter" might be better
    return ~~(numToTruncate * numPower)/numPower;
}

私は~~親で呼び出しをラップすることに抵抗しようとしています。操作の順序によって、それが正しく機能するはずだと私は信じています。

alert(truncator(5.1231231, 1)); // is 5.1

alert(truncator(-5.73, 1)); // is -5.7

alert(truncator(-5.73, 0)); // is -5

JSFiddleリンク

編集:振り返ってみると、私は意図せずに小数点の左側を四捨五入するケースも処理しました。

alert(truncator(4343.123, -2)); // gives 4300.

ロジックはその使用法を探すのが少し風変わりで、迅速なリファクタリングの恩恵を受ける可能性があります。しかし、それでも機能します。幸運より幸運。


これが最良の答えです。これでMathプロトタイプを拡張し、実行する前にNaN-sをチェックすると、完璧になります。
パルトロミエザレウスキー

truncator((10 * 2.9) / 100, 2)0.29ではなく0.28を返す... jsfiddle.net/25tgrzq1
Alex

14

素敵なワンラインソリューション:

function truncate (num, places) {
  return Math.trunc(num * Math.pow(10, places)) / Math.pow(10, places);
}

次に、次のように呼び出します。

truncate(3.5636232, 2); // returns 3.56
truncate(5.4332312, 3); // returns 5.433
truncate(25.463214, 4); // returns 25.4632

2
私はこのソリューションが好きですが、すべてのブラウザで完全にサポートされているわけではないことに注意してください。(developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
ジーンParcellano

11

|シンプルで上手くいくので、使って答えを出すと思いました。

truncate = function(number, places) {
  var shift = Math.pow(10, places);

  return ((number * shift) | 0) / shift;
};

1
よろしくお願いします。ビット演算子を使用すると、値がintに強制変換され、or0を指定すると、「既に取得したものを保持する」ことを意味します。私の~~答えが行うことを行いますが、1つのビット演算を使用します。書かれているのと同じ制限がありますが、2 ^ 31を超えることはできません
ラフィン2015年

1
正しくない場合truncate((10 * 2.9) / 100);、このコードのリターン0.28の代わりに0.29 jsfiddle.net/9pf0732d
アレックス

@Alexご存知のとおり... JavaScriptへようこそ!。修正があります。おそらくあなたはそれを共有したいですか?:D
ラフィン

@ruffin私はこの問題について知っています=)私はこの答えがこの問題の解決策だと思いました。残念ながら、私はまだ正確な解決策を見つけていません、どこでもそのような問題があります。
アレックス


7

@Dogbertの回答はMath.trunc、丸めの代わりに切り捨てられるで改善できます。

丸めと切り捨てには違いがあります。切り捨ては、明らかにこの質問が求めている動作です。truncate(-3.14)を呼び出して、-4を受け取った場合、それは間違いなく望ましくないと思います。– @nickKnowlson

var a = 5.467;
var truncated = Math.trunc(a * 100) / 100; // = 5.46
var a = -5.467;
var truncated = Math.trunc(a * 100) / 100; // = -5.46

1
これはすべての場合に機能するわけではありません。つまり、console.log(Math.trunc(9.28 * 100)/ 100); // 9.27
Mike Makuch

@MikeMakuchそれはとの問題ではないMath.truncが、むしろよりも9.28 * 100ある927.9999のではなく928浮動小数点の危険
zurfyx 2018

5

私はもっ​​と短い方法で答えを書きました。これが私が思いついたものです

function truncate(value, precision) {
    var step = Math.pow(10, precision || 0);
    var temp = Math.trunc(step * value);

    return temp / step;
}

この方法は次のように使用できます

truncate(132456.25456789, 5)); // Output: 132456.25456
truncate(132456.25456789, 3)); // Output: 132456.254
truncate(132456.25456789, 1)); // Output: 132456.2   
truncate(132456.25456789));    // Output: 132456

または、より短い構文が必要な場合は、ここに移動します

function truncate(v, p) {
    var s = Math.pow(10, p || 0);
    return Math.trunc(s * v) / s;
}

これは私が使用することを期待していた方法です
タクシー運転手

4
Number.prototype.trim = function(decimals) {
    var s = this.toString();
    var d = s.split(".");
    d[1] = d[1].substring(0, decimals);
    return parseFloat(d.join("."));
}

console.log((5.676).trim(2)); //logs 5.67

これが文字列で機能するので、浮動小数点数のニュアンスがなくなるのが好きです。ありがとう!
iCode

4

この関数は簡単な解決策になると思います。

function trunc(decimal,n=2){
  let x = decimal + ''; // string 
  return x.lastIndexOf('.')>=0?parseFloat(x.substr(0,x.lastIndexOf('.')+(n+1))):decimal; // You can use indexOf() instead of lastIndexOf()
}

console.log(trunc(-241.31234,2));
console.log(trunc(241.312,5));
console.log(trunc(-241.233));
console.log(trunc(241.2,0));  
console.log(trunc(241));


これが投稿されてから2年後、Math.trunc、正規表現などを使用して最善の方法を見つけようとしていたときに、これに遭遇しました。私はこのソリューションが本当に好きです。非常にシンプルですが、完全に機能します(とにかく私のユースケースでは)。
giles123 2018

ただし、n = 0を考慮することを忘れないでください。
giles123 2018

3

私は問題を見つけました:次の状況を考慮して:2.1または1.2または-6.4

常に小数点以下3桁、2桁、またはwhareverが必要な場合はどうなるので、右側の先行ゼロを完成させる必要があります。

// 3 decimals numbers
0.5 => 0.500

// 6 decimals
0.1 => 0.10000

// 4 decimales
-2.1 => -2.1000

// truncate to 3 decimals
3.11568 => 3.115

これはNickKnowlsonの固定機能です

function truncateDecimals (num, digits) 
{
    var numS = num.toString();
    var decPos = numS.indexOf('.');
    var substrLength = decPos == -1 ? numS.length : 1 + decPos + digits;
    var trimmedResult = numS.substr(0, substrLength);
    var finalResult = isNaN(trimmedResult) ? 0 : trimmedResult;

    // adds leading zeros to the right
    if (decPos != -1){
        var s = trimmedResult+"";
        decPos = s.indexOf('.');
        var decLength = s.length - decPos;

            while (decLength <= digits){
                s = s + "0";
                decPos = s.indexOf('.');
                decLength = s.length - decPos;
                substrLength = decPos == -1 ? s.length : 1 + decPos + digits;
            };
        finalResult = s;
    }
    return finalResult;
};

https://jsfiddle.net/huttn155/7/


x = 0.0000テストはtruncateDecimals (x, 2)失敗します。を返します0。予想外0.00
Ling Loeng 2018年

3
function toFixed(number, digits) {
    var reg_ex = new RegExp("(\\d+\\.\\d{" + digits + "})(\\d)")
    var array = number.toString().match(reg_ex);
    return array ? parseFloat(array[1]) : number.valueOf()
}

var test = 10.123456789
var __fixed = toFixed(test, 6)
console.log(__fixed)
// => 10.123456

3

@kirilloidによる答えは正解のようですが、メインコードを更新する必要があります。彼のソリューションは負の数を処理しません(誰かがコメントセクションで言及しましたが、メインコードでは更新されていません)。

それを完全な最終テスト済みソリューションに更新します。

Number.prototype.toFixedDown = function(digits) {
    var re = new RegExp("([-]*\\d+\\.\\d{" + digits + "})(\\d)"),
    m = this.toString().match(re);
    return m ? parseFloat(m[1]) : this.valueOf();
};

使用例:

var x = 3.1415629;
Logger.log(x.toFixedDown(2)); //or use whatever you use to log

フィドル:JS番号の切り捨て

PS:そのソリューションについてコメントするのに十分なリポジトリがありません。


2

これは単純ですが、小数点以下2桁までの数値を切り捨てるための機能です。

           function truncateNumber(num) {
                var num1 = "";
                var num2 = "";
                var num1 = num.split('.')[0];
                num2 = num.split('.')[1];
                var decimalNum = num2.substring(0, 2);
                var strNum = num1 +"."+ decimalNum;
                var finalNum = parseFloat(strNum);
                return finalNum;
            }

2

結果のタイプは数値のままです...

/* Return the truncation of n wrt base */
var trunc = function(n, base) {
    n = (n / base) | 0;
    return base * n;
};
var t = trunc(5.467, 0.01);

2

Lodashには、roundfloorceilを実行できるMathユーティリティメソッドがいくつかあります。所与小数精度の番号。これにより、後続のゼロが省略されます。

彼らは、数の指数を使用して、興味深いアプローチを取ります。どうやらこれは丸めの問題を回避します。

(注:funcあるMath.roundか、ceilまたはfloor以下のコードで)

// Shift with exponential notation to avoid floating-point issues.
var pair = (toString(number) + 'e').split('e'),
    value = func(pair[0] + 'e' + (+pair[1] + precision));

pair = (toString(value) + 'e').split('e');
return +(pair[0] + 'e' + (+pair[1] - precision));

ソースコードへのリンク


1

ここで私の主題に関する見解:

convert.truncate = function(value, decimals) {
  decimals = (decimals === undefined ? 0 : decimals);
  return parseFloat((value-(0.5/Math.pow(10, decimals))).toFixed(decimals),10);
};

少し手の込んだバージョンです

(f - 0.005).toFixed(2)

1

解決策としてマークされているものは、今日まで私が見つけたより良い解決策ですが、0で深刻な問題があります(たとえば、0.toFixedDown(2)は-0.01を与えます)。だから私はこれを使用することをお勧めします:

Number.prototype.toFixedDown = function(digits) {
  if(this == 0) {
    return 0;
  }
  var n = this - Math.pow(10, -digits)/2;
  n += n / Math.pow(2, 53); // added 1360765523: 17.56.toFixedDown(2) === "17.56"
  return n.toFixed(digits);
}

1

これが私が使用するものです:

var t = 1;
for (var i = 0; i < decimalPrecision; i++)
    t = t * 10;

var f = parseFloat(value);
return (Math.floor(f * t)) / t;

1
const TO_FIXED_MAX = 100;

function truncate(number, decimalsPrecison) {
  // make it a string with precision 1e-100
  number = number.toFixed(TO_FIXED_MAX);

  // chop off uneccessary digits
  const dotIndex = number.indexOf('.');
  number = number.substring(0, dotIndex + decimalsPrecison + 1);

  // back to a number data type (app specific)
  return Number.parseFloat(number);
}

// example
truncate(0.00000001999, 8);
0.00000001

で動作します:

  • 負の数
  • 非常に小さい数(Number.EPSILON精度)

0

私のために働いた簡単な解決策を指摘するだけです

文字列に変換してから正規表現します...

var number = 123.45678;
var number_s = '' + number;
var number_truncated_s = number_s.match(/\d*\.\d{4}/)[0]
var number_truncated = parseFloat(number_truncated_s)

と省略できます

var number_truncated = parseFloat(('' + 123.4568908).match(/\d*\.\d{4}/)[0])

0

これがあなたが望むことをするES6コードです

const truncateTo = (unRouned, nrOfDecimals = 2) => {
      const parts = String(unRouned).split(".");

      if (parts.length !== 2) {
          // without any decimal part
        return unRouned;
      }

      const newDecimals = parts[1].slice(0, nrOfDecimals),
        newString = `${parts[0]}.${newDecimals}`;

      return Number(newString);
    };

// your examples 

 console.log(truncateTo(5.467)); // ---> 5.46

 console.log(truncateTo(985.943)); // ---> 985.94

// other examples 

 console.log(truncateTo(5)); // ---> 5

 console.log(truncateTo(-5)); // ---> -5

 console.log(truncateTo(-985.943)); // ---> -985.94


0
Number.prototype.truncate = function(places) {
  var shift = Math.pow(10, places);

  return Math.trunc(this * shift) / shift;
};

0

文字列を操作できます。'。'かどうかをチェックします 存在し、文字列の一部を削除します。

切り捨て(7.88、1)-> 7.8

切り捨て(7.889、2)-> 7.89

切り捨て(-7.88、1)-> -7.88

function  truncate(number, decimals) {
    const tmp = number + '';
    if (tmp.indexOf('.') > -1) {
        return +tmp.substr(0 , tmp.indexOf('.') + decimals+1 );
    } else {
        return +number
    }
 }

0

このような根本的に単純な質問に対して、なぜこれほど多くの異なる答えがあるのか​​について、私は少し混乱しています。私が見たアプローチは2つだけで、一見の価値があるように思われました。https://jsbench.me/を使用して、速度の違いを確認するための簡単なベンチマークを実行しました。

これは、現在(2020年9月26日)回答としてフラグが立てられているソリューションです。

function truncate(n, digits) {
    var re = new RegExp("(\\d+\\.\\d{" + digits + "})(\\d)"),
        m = n.toString().match(re);
    return m ? parseFloat(m[1]) : n.valueOf();
};

[   truncate(5.467,2),
    truncate(985.943,2),
    truncate(17.56,2),
    truncate(0, 1),
    truncate(1.11, 1) + 22];

ただし、これは文字列や正規表現の処理を行っており、通常はあまり効率的ではありません。また、小数点なしでOPが要求することを正確に実行するMath.trunc関数があります。したがって、これに加えて少し余分な算術を簡単に使用して、同じことを得ることができます。

これが私がこのスレッドで見つけた別の解決策です、それは私が使うものです:

function truncate(n, digits) {
    var step = Math.pow(10, digits || 0);
    var temp = Math.trunc(step * n);

    return temp / step;
}

[   truncate(5.467,2),
    truncate(985.943,2),
    truncate(17.56,2),
    truncate(0, 1),
    truncate(1.11, 1) + 22];
    

最初の方法は2番目の方法よりも「99.92%遅い」ので、2番目の方法は間違いなく私が使用することをお勧めする方法です。

さて、仕事を避けるための他の方法を見つけることに戻ります...

ベンチマークのスクリーンショット

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