小数点以下の桁数を切り捨てようとしています。このようなもの:
5.467 -> 5.46
985.943 -> 985.94
toFixed(2)
ほぼ正しいことをしますが、値を四捨五入します。値を四捨五入する必要はありません。これがjavascriptで可能であることを願っています。
小数点以下の桁数を切り捨てようとしています。このようなもの:
5.467 -> 5.46
985.943 -> 985.94
toFixed(2)
ほぼ正しいことをしますが、値を四捨五入します。値を四捨五入する必要はありません。これがjavascriptで可能であることを願っています。
回答:
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);
}
1.11.toFixedDown(1) + 22
、の1.122
代わりになり23.1
ます。また、0.toFixedDown(1)
生成する必要0
がありますが、代わりにを生成し-0.1
ます。
(-10.2131).toFixedDown(2) // ==> 10.21
。
(1e-7).toFixedDown(0) // ==> 1e-7
。以下のためにそれを行います1e-(>=7)
(例:1e-8
、1e-9
、...)。
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の数学ライブラリに関する良いブログ投稿です
if(isNAN(result) result = 0;
なります。必要な動作によって異なります。
var a = 5.467;
var truncated = Math.floor(a * 100) / 100; // = 5.46
truncate(-3.14)
をもらっ-4
たら、それは間違いなく望ましくないと思います。
var a = 65.1
var truncated = Math.floor(a * 100) / 100; // = 65.09
したがって、これは正しい解決策ではありません
toFixedの0.5を引くことで、丸めを修正できます。
(f - 0.005).toFixed(2)
ダブルチルダを利用することを~~
検討してください。
番号を取ります。を使用してゼロ桁に切り捨てられるように、小数点以下の有効数字を乗算します~~
。その乗数を分割して戻します。利益。
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
編集:振り返ってみると、私は意図せずに小数点の左側を四捨五入するケースも処理しました。
alert(truncator(4343.123, -2)); // gives 4300.
ロジックはその使用法を探すのが少し風変わりで、迅速なリファクタリングの恩恵を受ける可能性があります。しかし、それでも機能します。幸運より幸運。
Math
プロトタイプを拡張し、実行する前にNaN-sをチェックすると、完璧になります。
truncator((10 * 2.9) / 100, 2)
0.29ではなく0.28を返す... jsfiddle.net/25tgrzq1
素敵なワンラインソリューション:
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
|
シンプルで上手くいくので、使って答えを出すと思いました。
truncate = function(number, places) {
var shift = Math.pow(10, places);
return ((number * shift) | 0) / shift;
};
or
0を指定すると、「既に取得したものを保持する」ことを意味します。私の~~
答えが行うことを行いますが、1つのビット演算を使用します。書かれているのと同じ制限がありますが、2 ^ 31を超えることはできません。
truncate((10 * 2.9) / 100);
、このコードのリターン0.28の代わりに0.29 jsfiddle.net/9pf0732d
ビット演算子を使用して切り捨てます。
~~0.5 === 0
~~(-0.5) === 0
~~14.32794823 === 14
~~(-439.93) === -439
@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
私はもっと短い方法で答えを書きました。これが私が思いついたものです
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;
}
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
この関数は簡単な解決策になると思います。
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.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;
};
x = 0.0000
テストはtruncateDecimals (x, 2)
失敗します。を返します0
。予想外0.00
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
@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:そのソリューションについてコメントするのに十分なリポジトリがありません。
Lodashには、round、floor、ceilを実行できる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));
解決策としてマークされているものは、今日まで私が見つけたより良い解決策ですが、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);
}
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
で動作します:
私のために働いた簡単な解決策を指摘するだけです
文字列に変換してから正規表現します...
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])
これがあなたが望むことをする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
文字列を操作できます。'。'かどうかをチェックします 存在し、文字列の一部を削除します。
切り捨て(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
}
}
このような根本的に単純な質問に対して、なぜこれほど多くの異なる答えがあるのかについて、私は少し混乱しています。私が見たアプローチは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番目の方法は間違いなく私が使用することをお勧めする方法です。
さて、仕事を避けるための他の方法を見つけることに戻ります...