JavaScriptで数値を丸めるにはどうすればよいですか?.toFixed()は文字列を返しますか?


176

ここで何か不足していますか?

var someNumber = 123.456;
someNumber = someNumber.toFixed(2);
alert(typeof(someNumber));
//alerts string

なぜない.toFixed()文字列を返しますか?

数値を2桁の10進数に丸めたい。


7
文字列を返すように設計されているからですか?
kennytm

2
私にはそれは奇妙に思えます。.toFixed()は数値に対してのみ機能します...
デレク・アデア

10
Math.round()が期待どおりに動作することを理解しています。数値を操作する関数が文字列を返す理由を尋ねていました...
Derek Adair

3
2017年に住んでいる人はlodash.com/docs/4.17.4#ceilの
Yves M.

1
_もそうです。カウント?まだ彼の仲間にアップグレードされていません。
Jenna Leaf 2017年

回答:


124

2進浮動小数点システムでは、0.1とその累乗(小数部を表示するために使用される)は(少なくとも完全な精度ではなく)表現できないため、文字列を返します。

たとえば、0.1は実際には0.1000000000000000055511151231257827021181583404541015625であり、0.01は実際には0.01000000000000000020816681711721685132943093776702880859375です。(BigDecimal私のポイントを証明してくれてありがとう。-P)

したがって(10進浮動小数点または有理数型がない場合)、それを文字列として出力することが、表示に必要な精度に正確にトリミングする唯一の方法です。


28
少なくとも、Javascriptを...ったく...私にいくつかの指の作業を保存し、バックナンバーにそれを変換することができ
デレク・アデール

10
@Derek:ええ、でも、それを数値に戻すと、同じ不正確な問題に再び遭遇します。:-P JSには、10進浮動小数点数や有理数はありません。
Chris Jester-Young

1
@DerekAdair最近、これについてさらに説明する投稿を作成しました。興味があるかもしれません。お楽しみください!stackoverflow.com/a/27030789/13
Chris Jester-Young、

7
実際、これが原因で私はこのテーマについてかなり重い研究をしました!あなたのすべての協力に感謝します!
Derek Adair

2
あなたの答えは少し誤解を招きます:toFixedは、数値を文字列に変換し、指定された小数点以下の桁数を使用してフォーマットすることを唯一の目的とするフォーマット関数です。文字列を返す理由は、文字列を返すことになっているためtoStringFixedです。代わりに名前が付けられていても、OPは結果に驚くことはありません。ここでの唯一の問題は、OPがMath.roundJSリファレンスに問い合わせることなく、のように機能することを期待していたことです。
Groo、2015

177

Number.prototype.toFixed印刷する前に数値フォーマットするように設計された関数です。これは、家族からだtoStringtoExponentialtoPrecision

数値を丸めるには、次のようにします。

someNumber = 42.008;
someNumber = Math.round( someNumber * 1e2 ) / 1e2;
someNumber === 42.01;

// if you need 3 digits, replace 1e2 with 1e3 etc.
// or just copypaste this function to your code:

function toFixedNumber(num, digits, base){
  var pow = Math.pow(base||10, digits);
  return Math.round(num*pow) / pow;
}

または、「ネイティブのような」関数が必要な場合は、プロトタイプを拡張できます。

Number.prototype.toFixedNumber = function(digits, base){
  var pow = Math.pow(base||10, digits);
  return Math.round(this*pow) / pow;
}
someNumber = 42.008;
someNumber = someNumber.toFixedNumber(2);
someNumber === 42.01;


//or even hexadecimal

someNumber = 0xAF309/256  //which is af3.09
someNumber = someNumber.toFixedNumber(1, 16);
someNumber.toString(16) === "af3.1";

ただし、モジュールには副作用がないため、モジュールを作成するときは、プロトタイプの汚染は悪いと見なされることに注意してください。したがって、モジュールの場合、最初の関数を使用します


12
これが最良の答えだと思います。型変換を回避します。素晴らしい醤油!
Phil

1
正解です。ただし... JavaScriptを20年ほど使用していますが、戻り値の周りで+(...)構文を使用している理由がわかりません。@samをこすってくれてありがとう:)私は
取り

1
@HammerNLサムの信念にもかかわらず、実際には何もしません:)これは単なる練習です。IDEにこの機能をとして認識させますtype Number。事は+(anyValue)常に数値を返すことです-例えば。+("45")を返し45、を+(new Number(42))返します42。これは、関数を厳密に入力するようなものです。それを習慣にすれば、多くのバグを回避できます:)
m93a 2017年

なぜこれがコアjavascript:sに組み込まれていないのですか
webmaster

2
resuitはsomeNumber = Math.round( 42.008 * 1e2 ) / 1e2;ないが42.01、それがあります~42.0099999999999980。理由:番号42.01は存在せず、最も近い既存の番号に丸められます。ところで、toPrecision(18)関連するすべての桁で数字を印刷することにより、数字を証明します。
Wiimm

118

私はこれを変更することでこの問題を解決しました:

someNumber = someNumber.toFixed(2)

...これに:

someNumber = +someNumber.toFixed(2);

ただし、これにより数値が文字列に変換されて再度解析されるため、パフォーマンスに大きな影響があります。パフォーマンスやタイプセーフが気になる場合は、他の回答も確認してください。


39
いやいやいやいやいや!やめろ!数値を文字列に変換するだけで丸めるのは非常に悪い習慣です!その代わりにsomeNumber = Math.round(someNumber * 1e2) / 1e2!より一般的な方法については、私の回答を参照してください。
m93a

@ m93a-なぜそれがそのような悪い習慣なのですか?
jczaplew 2016年

3
あなたは、このようにそれを行う場合は、32ビットのバイナリ番号は、すべての神のいまいましいの小数点のための16ビットを使用して、文字列に変換されているので@jczaplew !(ちなみに、UTF-16で数値を格納することは、あなたにとって最も便利なことではありません。)そして、文字列は32ビット浮動小数点数に変換されます。桁ごとの数字。(適切な構文解析アルゴリズムを選択するために事前に実行する必要があるすべてのテストを無視した場合。)そして、フロートで3つの高速操作を使用してそれを行うことができると考えると、すべてが無駄です。
m93a 16

2
@ m93aそれでそれはパフォーマンス上の理由のためですか?これは実際にパフォーマンスに顕著な影響を与えますか?
Sebastianb

2
@jczaplew、文字列が(1)実質的に遅い、(2)理論的に正しくないため
パセリエ2017


15

JavaScriptのNumber()関数を使用して数値に戻すことで解決しました

var x = 2.2873424;
x = Number(x.toFixed(2));

12

もちろん文字列を返します。数値変数を丸める場合は、代わりにMath.round()を使用します。toFixedのポイントは、ユーザーに表示するために、固定小数点数で数値をフォーマットすることです。


4

「+」を使用して、結果を数値に変換できます。

var x = 22.032423;
x = +x.toFixed(2); // x = 22.03

3

数値をフォーマットすることになっているときに、何が返されると思いますか?あなたが数を持っているなら、あなたはそれを使ってほとんど何もすることができません2 == 2.0 == 2.00


3

それが文字列でなければならない理由の例を提供するには:

1.toFixed(2)をフォーマットすると、「1.00」になります。

1は小数点以下2桁ではないため、これは1と同じではありません。


私はJavaScriptがパフォーマンス言語ではないことを知っていますが、次のようなものを使用すると、丸めのパフォーマンスが向上する可能性があります:roundedValue = Math.round(value * 100)* 0.01


2

その主な用途は数字を表示することですか?数値を丸める場合は、Math.round()適切な係数を使用してください。


しかし、NUMBERSを表示しているので、「数値」を返すべきではありませんか?
デレク・アデア

3
@Derek:'42'数字であるという意味でのみ...そうではありません。文字列がたまたま数字しか含まないからといって、それが数字になるわけではありません。これはPHPではありません。:-P
Chris Jester-Young

笑。数値を含む文字列ではありません...メソッドに渡されるのは数値です。このメソッドは数値を受け取り、文字列を返します。
Derek Adair

@DerekAdair正しいですが、ブラウザは数値を表示できません。文字列を表示するため、変換されます。
Nick M

1

これは、m93a提供された回答のもう少し機能的なバージョンです。

const toFixedNumber = (toFixTo = 2, base = 10) => num => {
  const pow = Math.pow(base, toFixTo)
  return +(Math.round(num * pow) / pow)
}

const oneNumber = 10.12323223

const result1 = toFixedNumber(2)(oneNumber) // 10.12
const result2 = toFixedNumber(3)(oneNumber) // 10.123

// or using pipeline-operator
const result3 = oneNumber |> toFixedNumber(2) // 10.12

これは便利な関数です。未定義の型では機能しません。この場合のコードを追加しました。if(num!== undefined){return +(Math.round(num * pow)/ pow)} else {return 0; }
Dino Liu
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.