JavaScript四捨五入の穴


前言


JavaScriptを使用して数値を処理するプログラマーは、JavaScriptのNumber.toFixedをよく知っています.この関数は、数値をフォーマットするときに、自動的に四捨五入されます.たとえば、次のようにします.
10.125.toFixed(2) ---> "10.13"

しかし、場合によっては、その四捨五入の結果は、往々にして望ましくないことがあります.例えば、
10.145.toFixed(2) ---> "10.14"

では、なぜこのような状況が発生したのか、進数から話す必要があります.

進数の謎


周知のように、コンピュータは設計の初め、各方面の角度から考慮して、最終的にバイナリのフォーマットを採用してデータを格納します.私たちが普段数字に慣用している進数は10進数です.10進数のデータをバイナリ形式で格納すると、必然的に進数の変換に直面し、進数の変換は精度の損失に直面します.
例えば、⅓の場合、3進数では0.1、10進数では0.333(3サイクル)である.それは3つの⅓を加算する場合、3進法では1(3進1に会う)であり、10進法では0.999(9サイクル)である.
同様の場合、10進数と2進数の変換にも現れます.コンピュータでは、変数が10.145であることを宣言しますが、実際には、この数字はバイナリとしてコンピュータに保存されており、本当に10.145ではありません.Number.prototype.toPrecisionの方法で意外を探究することができる.Number.prototype.toPrecisionメソッドは、指定された精度でその数値オブジェクトの文字列表現を返す.
10.145.toPrecision(21) ---> "10.1449999999999995737"

したがって、toFixed()メソッドが返す四捨五入の値が、場合によっては予想に合致しない理由を説明することができる.
同様に、浮動小数点数のすべての計算についても、加減乗除には例外がなく、場合によっては予想に合わない場合があり、最も一般的なのは0.1+0.2などです.

ソリューション


上記の状況に対して、私は簡単なライブラリを書いて、数字の四捨五入の需要を満たすことができます.round-js

探索浮動小数点数基準


ほとんどの言語とは異なり、JavaScriptは現在、数字の表現について、64ビットの二重精度浮動小数点数を用いて1つの数を表すタイプしかなく、その基準は多くの言語と同様にIEEE-754標準を採用している.IEEE-754の64ビットの二重精度浮動小数点数の基準は、以下のように1枚の図で表すことができる.
  • sign:シンボルを表し、1ビットで表される、すなわち正数負数、1は正数、0は負数を表す.
  • exponent:指数を表し、底数は2で、11ビットで表される.
  • fraction:本当の有効数字は52ビットで表されます.

  • 最終的に、任意の数は、この基準に対して、次の式を使用して表されます.
    次のようになります.
  • V:結果
  • S:上のsign
  • M:有効デジタルfraction
  • E:上のexponent
  • この表現方法は,十進法の科学的カウント法に似ていることがわかる.これらの概念については、IEEE−754規格には、<1M<2などの多くの規定があり、詳細は展開されない.
    終わります.