小数点以下2桁まで丸めたいのですが、必要な場合のみです。
入力:
10
1.7777777
9.1
出力:
10
1.78
9.1
JavaScriptでこれを行うにはどうすればよいですか?
Number.EPSILON
。を使用しMath.round( num * 100 + Number.EPSILON ) / 100
ます。
Number.EPSILON
ここで使用する理由を説明できますか?
小数点以下2桁まで丸めたいのですが、必要な場合のみです。
入力:
10
1.7777777
9.1
出力:
10
1.78
9.1
JavaScriptでこれを行うにはどうすればよいですか?
Number.EPSILON
。を使用しMath.round( num * 100 + Number.EPSILON ) / 100
ます。
Number.EPSILON
ここで使用する理由を説明できますか?
回答:
使用する Math.round(num * 100) / 100
編集: 1.005のようなものを正しく丸めるために、
Math.round((num + Number.EPSILON) * 100) / 100
Math.round((num + 0.00001) * 100) / 100
。試してみてくださいMath.round((1.005 + 0.00001) * 100) / 100
とMath.round((1.0049 + 0.00001) * 100) / 100
値がテキストタイプの場合:
parseFloat("123.456").toFixed(2);
値が数値の場合:
var numb = 123.23454;
numb = numb.toFixed(2);
1.5のような値は、出力として「1.50」を与えるという欠点があります。@minitechによって提案された修正:
var numb = 1.5;
numb = +numb.toFixed(2);
// Note the plus sign that drops any "extra" zeroes at the end.
// It changes the result (which is a string) into a number again (think "0 + foo"),
// which means that it uses only as many digits as necessary.
それMath.round
はより良い解決策のようです。そうではありません!場合によっては、正しく丸められないことがあります。
Math.round(1.005 * 1000)/1000 // Returns 1 instead of expected 1.01!
toFixed()もなりませラウンド正しくいくつかのケースでは(クロームv.55.0.2883.87でテスト)!
例:
parseFloat("1.555").toFixed(2); // Returns 1.55 instead of 1.56.
parseFloat("1.5550").toFixed(2); // Returns 1.55 instead of 1.56.
// However, it will return correct result if you round 1.5551.
parseFloat("1.5551").toFixed(2); // Returns 1.56 as expected.
1.3555.toFixed(3) // Returns 1.355 instead of expected 1.356.
// However, it will return correct result if you round 1.35551.
1.35551.toFixed(2); // Returns 1.36 as expected.
おそらく、これは1.555が実際には裏側のフロート1.55499994のようなものだからです。
解決策1は、必要な丸めアルゴリズムを備えたスクリプトを使用することです。次に例を示します。
function roundNumber(num, scale) {
if(!("" + num).includes("e")) {
return +(Math.round(num + "e+" + scale) + "e-" + scale);
} else {
var arr = ("" + num).split("e");
var sig = ""
if(+arr[1] + scale > 0) {
sig = "+";
}
return +(Math.round(+arr[0] + "e" + sig + (+arr[1] + scale)) + "e-" + scale);
}
}
https://plnkr.co/edit/uau8BlS1cqbvWPCHJeOy?p=preview
注:これは万人向けの一般的なソリューションではありません。いくつかの異なる丸めアルゴリズムがあり、実装は異なる場合があり、要件によって異なります。https://en.wikipedia.org/wiki/Rounding
解決策2は、フロントエンドの計算を回避し、丸められた値をバックエンドサーバーから取得することです。
parseFloat(number.toFixed(decimalPlaces));
@PerLundberg
parseFloat("55.555").toFixed(2)
"55.55"
Chrome開発コンソールに戻ります。
使用できます
function roundToTwo(num) {
return +(Math.round(num + "e+2") + "e-2");
}
MDNでこれを見つけました。彼らの方法は、言及された 1.005の問題を回避します。
roundToTwo(1.005)
1.01
roundToTwo(10)
10
roundToTwo(1.7777777)
1.78
roundToTwo(9.1)
9.1
roundToTwo(1234.5678)
1234.57
+(val)
は、を使用することと同等の強制型Number(val)
です。"e-2"を数値に連結すると、文字列を数値に戻す必要が生じました。
roundToTwo(1.0049999999999999)
は、1.01として表示されます(必然的に、以来1.0049999999999999 == 1.005
)。num = 1.005
numの正確な値が1.005未満であるため、「明らかに」と入力するとフロートが1.00に丸められるはずです。もちろん、文字列「1.005」「明らかに」「すべき」は1.01に丸められるようにも思えます。実際の正しい振る舞いがここにあるかについて、人によって直観が異なるように見えるという事実は、複雑な理由の一部です。
1.0049999999999999
と1.005
そう定義することによって、それらが同じ数です。これはdedekindカットと呼ばれます。
1.00499 < 1.005
、IS true
、1.0049999999999999 < 1.005
と評価されましたfalse
。
MarkGの答えは正しいものです。小数点以下の桁数を任意に指定できる一般的な拡張を以下に示します。
Number.prototype.round = function(places) {
return +(Math.round(this + "e+" + places) + "e-" + places);
}
使用法:
var n = 1.7777;
n.round(2); // 1.78
単体テスト:
it.only('should round floats to 2 places', function() {
var cases = [
{ n: 10, e: 10, p:2 },
{ n: 1.7777, e: 1.78, p:2 },
{ n: 1.005, e: 1.01, p:2 },
{ n: 1.005, e: 1, p:0 },
{ n: 1.77777, e: 1.8, p:1 }
]
cases.forEach(function(testCase) {
var r = testCase.n.round(testCase.p);
assert.equal(r, testCase.e, 'didn\'t get right number');
});
})
function round(number, decimals) { return +(Math.round(number + "e+" + decimals) + "e-" + decimals); }
(-1.005).round(2) === -1
あなたは使うべきです:
Math.round( num * 100 + Number.EPSILON ) / 100
誰も気づいていないようですNumber.EPSILON
。
また、これは一部の人々が述べたようなJavaScriptの奇妙さではないことにも注意する価値があります。
これは、浮動小数点数がコンピュータで機能する方法です。99%のプログラミング言語と同様に、JavaScriptには自家製の浮動小数点数がありません。それはCPU / FPUに依存しています。コンピュータはバイナリを使用し、バイナリでは0.1
、のような数値はありませんが、そのための単なるバイナリ近似です。どうして?同じ理由で、1/3を10進数で書くことはできません。その値は0.33333333 ...であり、3の無限大です。
来るよNumber.EPSILON
。その数は、1と倍精度浮動小数点数に存在する次の数の差です。それだけです:1
と1 +の間に数字はありませんNumber.EPSILON
。
編集:
コメントで尋ねられたように、1つ明確にしましょう:Number.EPSILON
丸めの値が算術演算の結果である場合にのみ関連があります。これは、浮動小数点エラーデルタを飲み込む可能性があるためです。
値が直接のソース(リテラル、ユーザー入力、センサーなど)からのものである場合は、役に立ちません。
編集(2019):
@maganapや一部の人々が指摘したように、Number.EPSILON
乗算する前に追加するのが最善です。
Math.round( ( num + Number.EPSILON ) * 100 ) / 100
編集(2019年12月):
最近、イプシロンに対応した数値を比較するために、次のような関数を使用しています。
const ESPILON_RATE = 1 + Number.EPSILON ;
const ESPILON_ZERO = Number.MIN_VALUE ;
function epsilonEquals( a , b ) {
if ( Number.isNaN( a ) || Number.isNaN( b ) ) {
return false ;
}
if ( a === 0 || b === 0 ) {
return a <= b + EPSILON_ZERO && b <= a + EPSILON_ZERO ;
}
return a <= b * EPSILON_RATE && b <= a * EPSILON_RATE ;
}
私のユースケースは、私が長年開発しているアサーション+データ検証ライブラリです。
実際、私が使用しているコードではESPILON_RATE = 1 + 4 * Number.EPSILON
、EPSILON_ZERO = 4 * Number.MIN_VALUE
(イプシロンの4倍)、浮動小数点エラーを累積するために十分に緩い等価チェッカーが必要です。
これまでのところ、それは私にとって完璧に見えます。お役に立てば幸いです。
Math.round( (num + Number.EPSILON) * 100) / 100
。また、これは正しく丸めるための適切な方法です(ただし、この質問で尋ねられたとおりではありません)。
0.004999999999999999
複合浮動小数点エラーの結果としてのみ可能であり、数学的に正しい結果はおそらく0.005でした。センサーからの読み取り値の場合はどうなりますか?それほどではありません。
Math.round(1.5)
= 2、ただしMath.round(-1.5)
= -1。したがって、これは完全に一貫しています。ここで、-1は-2より大きく、ちょうど-1000が-1000.01より大きいようにです。より大きな絶対数と混同しないでください。
使用できます.toFixed(NumberOfDecimalPlaces)
。
var str = 10.234.toFixed(2); // => '10.23'
var number = Number(str); // => 10.23
Number(9).toFixed(2).replace(/0+$/, '')
=> "9"。
この質問は複雑です。
roundTo2DP(num)
floatを引数として取り、小数点以下2桁に丸めた値を返す関数があるとします。これらの各式は何を評価する必要がありますか?
roundTo2DP(0.014999999999999999)
roundTo2DP(0.0150000000000000001)
roundTo2DP(0.015)
「明白な」答えは、最初の例は0.01に丸める必要がある(0.02に比べて0.01に近いため)が、他の2つは0.02に丸める必要がある(0.0150000000000000001は0.01に比べて0.02に近いため)。それらとそのような数が切り上げられる数学的規則があります)。
あなたが推測したかもしれないキャッチは、それらに渡される3つの数値がすべて同じ数値であるため、それらの明白な答えを与えるためにroundTo2DP
おそらく実装することができないということです。IEEE 754 2進浮動小数点数(JavaScriptで使用される種類)は、ほとんどの非整数値を正確に表すことができないため、上記の3つの数値リテラルはすべて、近くの有効な浮動小数点数に丸められます。この数は、実際のところ、正確に
0.01499999999999999944488848768742172978818416595458984375
これは0.02よりも0.01に近い値です。
ブラウザーコンソール、ノードシェル、またはその他のJavaScriptインタープリターでは、3つの数値がすべて同じであることがわかります。それらを比較するだけです:
> 0.014999999999999999 === 0.0150000000000000001
true
だから私が書いたとき、私が最終的に得m = 0.0150000000000000001
た正確な値はm
0.01
、それがそうであるよりも近い0.02
です。それでも、m
文字列に変換すると...
> var m = 0.0150000000000000001;
> console.log(String(m));
0.015
> var m = 0.014999999999999999;
> console.log(String(m));
0.015
...私は0.015を取得します。これは0.02に丸める必要があります。これは、これらの数値のすべてが正確に等しいと以前に言った56桁の数値ではありません。これは何のダークマジックですか?
答えはECMAScript仕様のセクション7.1.12.1:Numberタイプに適用されるToStringにあります。ここで、いくつかの数値mを文字列に変換するためのルールを説明します。重要な部分はポイント5で、整数sが生成され、その桁はmの文字列表現で使用されます。
させる 、N、K、およびsのような整数であるK ≥1、10 K -1 ≤ S <10 K、の番号値S ×10 N - Kあり、M、およびkはできるだけ小さいようです。kは、小数の表現の桁数であることに注意S、Sが 10で割り切れない、との最下位桁ことSは必ずしも一意にこれらの基準によって決定されません。
ここで重要なのは、「kができるだけ小さい」という要件です。その要件が意味するのはm
、数値が与えられた場合、の値が可能な限り最小の桁数でString(m)
なければならず、その要件を満たしているという要件ですNumber(String(m)) === m
。私たちはすでにそれを知っているので0.015 === 0.0150000000000000001
、なぜ今は明らかですString(0.0150000000000000001) === '0.015'
真実でなければならはです。
もちろん、この議論のどれも、何roundTo2DP(m)
を返すべきか直接答えていません。場合m
「の正確な値は0.01499999999999999944488848768742172978818416595458984375ですが、その文字列表現は'0.015、その後、何が正しいです、我々は2桁までそれを丸めるとき-数学的、現実的、哲学的、または何でも-答えは?
これに対する単一の正解はありません。ユースケースによって異なります。次のような場合は、おそらくString表現を尊重し、上方に丸める必要があります。
一方、値が本質的に連続的なスケールからのものである場合、たとえば、それがセンサーからの読み取り値である場合は、おそらく2進浮動小数点値を尊重し、丸めたいと思うでしょう。
これらの2つのアプローチには異なるコードが必要です。数字の文字列表現を尊重するために、私たちは(かなり微妙なコードをかなり使用して)学校で使用したのと同じアルゴリズムを使用して、数字ごとに文字列表現に直接作用する独自の丸めを実装できます。数値を丸める方法を教えられました。以下は、小数点以下のゼロを削除して「必要な場合のみ」小数点以下2桁まで数値を表すというOPの要件を尊重する例です。もちろん、正確なニーズに合わせて調整する必要があるかもしれません。
/**
* Converts num to a decimal string (if it isn't one already) and then rounds it
* to at most dp decimal places.
*
* For explanation of why you'd want to perform rounding operations on a String
* rather than a Number, see http://stackoverflow.com/a/38676273/1709587
*
* @param {(number|string)} num
* @param {number} dp
* @return {string}
*/
function roundStringNumberWithoutTrailingZeroes (num, dp) {
if (arguments.length != 2) throw new Error("2 arguments required");
num = String(num);
if (num.indexOf('e+') != -1) {
// Can't round numbers this large because their string representation
// contains an exponent, like 9.99e+37
throw new Error("num too large");
}
if (num.indexOf('.') == -1) {
// Nothing to do
return num;
}
var parts = num.split('.'),
beforePoint = parts[0],
afterPoint = parts[1],
shouldRoundUp = afterPoint[dp] >= 5,
finalNumber;
afterPoint = afterPoint.slice(0, dp);
if (!shouldRoundUp) {
finalNumber = beforePoint + '.' + afterPoint;
} else if (/^9+$/.test(afterPoint)) {
// If we need to round up a number like 1.9999, increment the integer
// before the decimal point and discard the fractional part.
finalNumber = Number(beforePoint)+1;
} else {
// Starting from the last digit, increment digits until we find one
// that is not 9, then stop
var i = dp-1;
while (true) {
if (afterPoint[i] == '9') {
afterPoint = afterPoint.substr(0, i) +
'0' +
afterPoint.substr(i+1);
i--;
} else {
afterPoint = afterPoint.substr(0, i) +
(Number(afterPoint[i]) + 1) +
afterPoint.substr(i+1);
break;
}
}
finalNumber = beforePoint + '.' + afterPoint;
}
// Remove trailing zeroes from fractional part before returning
return finalNumber.replace(/0+$/, '')
}
使用例:
> roundStringNumberWithoutTrailingZeroes(1.6, 2)
'1.6'
> roundStringNumberWithoutTrailingZeroes(10000, 2)
'10000'
> roundStringNumberWithoutTrailingZeroes(0.015, 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes('0.015000', 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes(1, 1)
'1'
> roundStringNumberWithoutTrailingZeroes('0.015', 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes(0.01499999999999999944488848768742172978818416595458984375, 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes('0.01499999999999999944488848768742172978818416595458984375', 2)
'0.01'
上記の関数は おそらくあなたは、彼らがビーイングが誤って丸め入力されていることを数字を目の当たりにし、ユーザーを避けるために使用したいもの。
(別の方法として、 ラウンド10を異なる実装で同様に動作する関数を提供するライブラリを。)
しかし、第2の種類の数値-小数点以下の桁数が少ない近似の10進数表現が、小数点以下の桁数が多いものよりも正確であると考える理由がない、連続スケールから取得した値がある場合はどうなりますか?その場合、(仕様で説明されているように)文字列表現は既に丸められているため、文字列表現を尊重したくありません。「0.014999999 ... 375は0.012に切り上げられる0.015に切り上げられるため、0.014999999 ... 375は0.02に切り上げられる」という誤った言い方をしたくありません。
ここでは、組み込みtoFixed
メソッドを簡単に使用できます。によってNumber()
返された文字列を呼び出すと、文字toFixed
列表現の末尾にゼロがないNumberが取得されることに注意してください(JavaScriptが数値の文字列表現を計算する方法のおかげで、この回答で前述しました)。
/**
* Takes a float and rounds it to at most dp decimal places. For example
*
* roundFloatNumberWithoutTrailingZeroes(1.2345, 3)
*
* returns 1.234
*
* Note that since this treats the value passed to it as a floating point
* number, it will have counterintuitive results in some cases. For instance,
*
* roundFloatNumberWithoutTrailingZeroes(0.015, 2)
*
* gives 0.01 where 0.02 might be expected. For an explanation of why, see
* http://stackoverflow.com/a/38676273/1709587. You may want to consider using the
* roundStringNumberWithoutTrailingZeroes function there instead.
*
* @param {number} num
* @param {number} dp
* @return {number}
*/
function roundFloatNumberWithoutTrailingZeroes (num, dp) {
var numToFixedDp = Number(num).toFixed(dp);
return Number(numToFixedDp);
}
roundStringNumberWithoutTrailingZeroes(362.42499999999995, 2)
。(PHPのような結果を期待echo round(362.42499999999995, 2)
): 362.43
。実際の結果:362.42
round
が362.43を与える理由がわかりません。362.42499999999995は362.425より小さいため(算術およびコード362.42499999999995 < 362.425
では-JSとPHPの両方で当てはまります)、直感的には間違っているように見えます。また、PHPの答えは、元の浮動小数点数と丸められた浮動小数点数の間の距離を最小化しません362.43 - 362.42499999999995 > 362.42499999999995 - 362.42
。php.net/manual/en/function.round.phpによると、PHP round
はC99標準に準拠しています。何が起こっているのかを理解するために、Cの土地に足を踏み入れる必要があります。
検討する .toFixed()
、.toPrecision()
:
正確な丸め方法。出典:Mozilla
(function(){
/**
* Decimal adjustment of a number.
*
* @param {String} type The type of adjustment.
* @param {Number} value The number.
* @param {Integer} exp The exponent (the 10 logarithm of the adjustment base).
* @returns {Number} The adjusted value.
*/
function decimalAdjust(type, value, exp) {
// If the exp is undefined or zero...
if (typeof exp === 'undefined' || +exp === 0) {
return Math[type](value);
}
value = +value;
exp = +exp;
// If the value is not a number or the exp is not an integer...
if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {
return NaN;
}
// Shift
value = value.toString().split('e');
value = Math[type](+(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));
}
// Decimal round
if (!Math.round10) {
Math.round10 = function(value, exp) {
return decimalAdjust('round', value, exp);
};
}
// Decimal floor
if (!Math.floor10) {
Math.floor10 = function(value, exp) {
return decimalAdjust('floor', value, exp);
};
}
// Decimal ceil
if (!Math.ceil10) {
Math.ceil10 = function(value, exp) {
return decimalAdjust('ceil', value, exp);
};
}
})();
例:
// Round
Math.round10(55.55, -1); // 55.6
Math.round10(55.549, -1); // 55.5
Math.round10(55, 1); // 60
Math.round10(54.9, 1); // 50
Math.round10(-55.55, -1); // -55.5
Math.round10(-55.551, -1); // -55.6
Math.round10(-55, 1); // -50
Math.round10(-55.1, 1); // -60
Math.round10(1.005, -2); // 1.01 -- compare this with Math.round(1.005*100)/100 above
// Floor
Math.floor10(55.59, -1); // 55.5
Math.floor10(59, 1); // 50
Math.floor10(-55.51, -1); // -55.6
Math.floor10(-51, 1); // -60
// Ceil
Math.ceil10(55.51, -1); // 55.6
Math.ceil10(51, 1); // 60
Math.ceil10(-55.59, -1); // -55.5
Math.ceil10(-59, 1); // -50
Math.round10(3544.5249, -2)
代わりに戻り3544.52 3544.53
3544.5249
小数点第2位までの近似値は3544.52
(エラー= 0.0049)です。の場合3544.53
、エラーは0.0051になります。連続する丸め、つまりMath.round10(Math.round10(3544.5249、-3)、-2)を実行しているため、丸め誤差が大きくなり、望ましくありません。
number += 0.00011
Math.round10( Math.round10(3544.5249, -3) , -2)
ここで見つかった答えはどれも正しくありません。@stinkycheesemanはに尋ねラウンドまで、あなたのすべての番号を丸め。
切り上げるには、次のようにします。
Math.ceil(num * 100)/100;
Math.ceil(1.1 * 100)/100;
-1.1 1.11
* 100は110.00000000000001
最新の最新ブラウザであるFirefox、Chrome、Safari、Operaに準拠しているため、IEは昔と変わらず考えてい1.1*100=1100
ます。
Math.ceil(num.toFixed(4) * 100) / 100
Math.ceil((1.1).toFixed(4) * 100) / 100
は1.11
Firefoxにも戻ります。最近のブラウザーの問題/バグは乗算に関するものであり、人々はそれについて知っている必要があります(たとえば、私は当時の宝くじゲームに取り組みました)。
これを行う簡単な方法を次に示します。
Math.round(value * 100) / 100
しかし、先に進み、それを行うための別の関数を作成することもできます。
function roundToTwo(value) {
return(Math.round(value * 100) / 100);
}
次に、単に値を渡します。
2番目のパラメーターを追加することにより、任意の小数点以下の桁数に丸めるように拡張できます。
function myRound(value, places) {
var multiplier = Math.pow(10, places);
return (Math.round(value * multiplier) / multiplier);
}
+(10).toFixed(2); // = 10
+(10.12345).toFixed(2); // = 10.12
(10).toFixed(2); // = 10.00
(10.12345).toFixed(2); // = 10.12
+(0.015).toFixed(2) == 0.01
。
私にとってMath.round()は正しい答えを与えていませんでした。toFixed(2)の方がうまくいくことがわかりました。以下は両方の例です。
console.log(Math.round(43000 / 80000) * 100); // wrong answer
console.log(((43000 / 80000) * 100).toFixed(2)); // correct answer
1.005
。(1.005).toFixed(2)
まだ結果になり1.00
ます。
この機能を使用 Number(x).toFixed(2);
Number
呼び出しは、必要ありませんx.toFixed(2)
動作します。
(1).toFixed(2)
が返されます1.00
が1
、この場合は質問者が必要です。
1.005.toFixed(2)
収量を"1"
、それがあるべきとき"1.01"
。
2017
ネイティブコードを使用する.toFixed()
number = 1.2345;
number.toFixed(2) // "1.23"
厳密にする必要がある場合は、必要に応じて数字を追加して使用できます replace
number = 1; // "1"
number.toFixed(5).replace(/\.?0*$/g,'');
toFixed
年も前に複数の回答から提案されただけでなく、質問の「必要な場合のみ」の条件を満たしていません。質問者が望む場所(1).toFixed(2)
を与える。"1.00"
"1"
この軽量ソリューションを試してください:
function round(x, digits){
return parseFloat(x.toFixed(digits))
}
round(1.222, 2) ;
// 1.22
round(1.222, 10) ;
// 1.222
.toFixed()
とにかく数値しか許可されていないので、私が見る限り、違いはないはずです。
round(1.005, 2)
の1
代わりにの結果を試してみてください1.01
。
round(0.995, 2) => 0.99
; round(1.006, 2) => 1.01
; round(1.005, 2) => 1
これを行うにはいくつかの方法があります。私のような人のために、ロダッシュの変種
function round(number, precision) {
var pair = (number + 'e').split('e')
var value = Math.round(pair[0] + 'e' + (+pair[1] + precision))
pair = (value + 'e').split('e')
return +(pair[0] + 'e' + (+pair[1] - precision))
}
使用法:
round(0.015, 2) // 0.02
round(1.005, 2) // 1.01
プロジェクトでjQueryまたはlodashを使用している場合round
は、ライブラリで適切なメソッドを見つけることもできます。
n.toFixed(2)
正しくないため、バリアントを削除しました。ありがとう@ avalanche1
Number.toFixed()
は文字列を返しますが、その前にプラス記号を付けると、JSインタープリターが文字列を数値に変換します。これは構文糖衣です。
alert((+1234).toFixed(2))
「1234.00」と表示されます。
alert(+1234.toFixed(2))
スローしSyntaxError: identifier starts immediately after numeric literal
ます。私は最初のオプションを使います。
362.42499999999995
。(PHPのような結果を期待echo round(362.42499999999995, 2)
): 362.43
。実際の結果:362.42
lodashライブラリを使用している場合は、次のようにlodashのroundメソッドを使用できます。
_.round(number, precision)
例えば:
_.round(1.7777777, 2) = 1.78
ES6以降は、toPrecisionを使用してこれを行う「適切な」方法があります(静的をオーバーライドして回避策を作成する必要はありません)。
var x = 1.49999999999;
console.log(x.toPrecision(4));
console.log(x.toPrecision(3));
console.log(x.toPrecision(2));
var y = Math.PI;
console.log(y.toPrecision(6));
console.log(y.toPrecision(5));
console.log(y.toPrecision(4));
var z = 222.987654
console.log(z.toPrecision(6));
console.log(z.toPrecision(5));
console.log(z.toPrecision(4));
そうすれば、ちょうどparseFloat
ゼロがゼロになります。
console.log(parseFloat((1.4999).toPrecision(3)));
console.log(parseFloat((1.005).toPrecision(3)));
console.log(parseFloat((1.0051).toPrecision(3)));
ただし、「1.005丸めの問題」は解決されません。浮動小数点数の処理方法に固有であるためです。
console.log(1.005 - 0.005);
ライブラリを利用できる場合は、bignumber.jsを使用できます
console.log(1.005 - 0.005);
console.log(new BigNumber(1.005).minus(0.005));
console.log(new BigNumber(1.005).round(4));
console.log(new BigNumber(1.005).round(3));
console.log(new BigNumber(1.005).round(2));
console.log(new BigNumber(1.005).round(1));
<script src="https://cdnjs.cloudflare.com/ajax/libs/bignumber.js/2.3.0/bignumber.min.js"></script>
(1.005).toPrecision(3)
実際の1.00
代わりにまだ戻ります1.01
。
toPrecision
目的の出力タイプを変更する文字列を返します。
.toPrecision
メソッドの欠陥ではありません。浮動小数点数(JS のどの数値か)の特殊性です—試行すると1.005 - 0.005
、が返され0.9999999999999999
ます。
(1).toPrecision(3)
「1.00」を返しますが1
、この場合、質問者が持っていたかったのです。
toPrecision
後者ではなくフォーマットを実行し、OPの質問への回答ではありませんが、最初は適切と思われるかもしれませんが、かなり間違っています。en.wikipedia.org/wiki/Significant_figuresを参照してください。たとえば、をNumber(123.4).toPrecision(2)
返し"1.2e+2"
、をNumber(12.345).toPrecision(2)
返します"12"
。また、@ adamdurenが望ましくない文字列を返す(大きな問題ではないが望ましくない)文字列を返すという点にも同意します。
MarkGとLavamantisは、受け入れられているソリューションよりもはるかに優れたソリューションを提供しました。彼らがこれ以上賛成票を得られないのは残念です!
MDNにも基づいて浮動小数点の10進数の問題を解決するために使用する関数は次のとおりです。これは、Lavamantisのソリューションよりもさらに一般的です(ただし簡潔ではありません)。
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(10.8034, 2); // Returns 10.8
round(1.275, 2); // Returns 1.28
round(1.27499, 2); // Returns 1.27
round(1.2345678e+2, 2); // Returns 123.46
Lavamantisのソリューションと比較して、次のことができます...
round(1234.5678, -2); // Returns 1200
round("123.45"); // Returns 123
これはあなたを助けるかもしれません:
var result = Math.round(input*100)/100;
詳細については、このリンクをご覧ください。
最も簡単な方法は、toFixedを使用してから、Number関数を使用して末尾のゼロを取り除くことです。
const number = 15.5;
Number(number.toFixed(2)); // 15.5
const number = 1.7777777;
Number(number.toFixed(2)); // 1.78
15.00
ますか?JSの数値は小数点以下の桁数を格納せず、どの表示でも自動的に余分な小数点以下(末尾のゼロ)を切り捨てます。
var roundUpto = function(number, upto){
return Number(number.toFixed(upto));
}
roundUpto(0.1464676, 2);
toFixed(2)
ここで2は、この数値を四捨五入する桁数です。
それはあなたのために働くかもしれません、
Math.round(num * 100)/100;
toFixedとroundの違いを知る。あなたは見て持つことができますnum.toFixed(0)と、ブラウザの不整合対恐らくMath.round(NUM)を。
このような「parseFloat(parseFloat(value).toFixed(2))」のようなものを使用してください
parseFloat(parseFloat("1.7777777").toFixed(2))-->1.78
parseFloat(parseFloat("10").toFixed(2))-->10
parseFloat(parseFloat("9.1").toFixed(2))-->9.1
必要な場合にのみこのような丸めを実現する1つの方法は、Number.prototype.toLocaleString()を使用することです。
myNumber.toLocaleString('en', {maximumFractionDigits:2, useGrouping:false})
これにより、期待どおりの出力が文字列として提供されます。それが期待するデータ型でない場合でも、それらを数値に戻すことができます。
toLocaleString
いません。
真の正確な小数丸め精度を実現するために考えられるすべての方法のさまざまな反復を実行した後、最も正確で効率的なソリューションはNumber.EPSILONを使用することであることは明らかです。これは、浮動小数点演算の精度の問題に対する真の数学的解決策を提供します。次のように簡単にポリフィルできます:https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON多分、再び私たちを最後に残ったIEユーザー(のすべてをサポートするために、それをやめるべきです)。
ここに提供されているソリューションから適応: https //stackoverflow.com/a/48850944/6910392
ライブラリ全体を追加せずに、オプションの精度変数を使用して、正確な小数丸め、フローリング、および天井を提供するソリューションの簡単なドロップ。
更新:Sergeyがコメントで述べたように、指摘する価値があるこの(または任意の)メソッドには制限があります。0.014999999999999999のような数値の場合でも、浮動小数点値のストレージの精度制限の絶対的な限界に達した結果として生じる不正確さが依然として発生します。値自体はすぐに0.015と評価されるため、それを説明するために適用できる数学やその他のソリューションはありません。これは、コンソールでその値を呼び出すだけで確認できます。この制限により、文字列表現は単に「0.015」なので、文字列操作を使用してこの値を減らすことはできません。これを説明するソリューションは、スクリプトに値を受け入れる前に、データのソースで論理的に適用する必要があります。
var DecimalPrecision = (function(){
if (Number.EPSILON === undefined) {
Number.EPSILON = Math.pow(2, -52);
}
this.round = function(n, p=2){
let r = 0.5 * Number.EPSILON * n;
let o = 1; while(p-- > 0) o *= 10;
if(n < 0)
o *= -1;
return Math.round((n + r) * o) / o;
}
this.ceil = function(n, p=2){
let r = 0.5 * Number.EPSILON * n;
let o = 1; while(p-- > 0) o *= 10;
if(n < 0)
o *= -1;
return Math.ceil((n + r) * o) / o;
}
this.floor = function(n, p=2){
let r = 0.5 * Number.EPSILON * n;
let o = 1; while(p-- > 0) o *= 10;
if(n < 0)
o *= -1;
return Math.floor((n + r) * o) / o;
}
return this;
})();
console.log(DecimalPrecision.round(1.005));
console.log(DecimalPrecision.ceil(1.005));
console.log(DecimalPrecision.floor(1.005));
console.log(DecimalPrecision.round(1.0049999));
console.log(DecimalPrecision.ceil(1.0049999));
console.log(DecimalPrecision.floor(1.0049999));
console.log(DecimalPrecision.round(2.175495134384,7));
console.log(DecimalPrecision.round(2.1753543549,8));
console.log(DecimalPrecision.round(2.1755465135353,4));
これは最もシンプルでエレガントなソリューションです(そして私は世界一です;):
function roundToX(num, X) {
return +(Math.round(num + "e+"+X) + "e-"+X);
}
//roundToX(66.66666666,2) => 66.67
//roundToX(10,2) => 10
//roundToX(10.904,2) => 10.9
E
表記法を使用して引数を受け入れるように受け入れられた回答を書き直すのに良い方法です。
roundToX(362.42499999999995, 2)
。(PHPのような結果を期待echo round(362.42499999999995, 2)
): 362.43
。実際の結果:362.42