I.背景
小数と最寄りのNビットに丸めを伴う最近dashboradチャート、計算します。発見JS計算された結果ではない、私は予想通り同じした後、簡単ではありませんようです......
二、JSと精度
1、精密加工
まず、2点をクリア:
- 1、小数精度の概念を伴います
- 2、小数(及び記憶)動作は、 JSを含みます
精度处理
実際には、我々は何の問題もなく、算術小数。しかし、JS(プログラミング言語)、そうではありません。
2、精度が失われます
例えば、JSの実装で:
0.1 + 0.2
0.30000000000000004
0.3 - 0.1
0.19999999999999998
0.1 * 0.1
0.010000000000000002
0.3 / 0.1
2.9999999999999996
図から分かるように、JS計算結果の小数点以下は、私たちが予想していたではないとして。これがある精度丢失
問題。
(1)Q:どのような問題は、精度の損失につながるのだろうか?
回答:
- 1、そう決意は(に等しい
===
)論理エラー。たとえば、みましょう0.1 + 0.2 === 0.3
にfalse
- 図2は、精度をもたらすことが予想されること小数長い桁特に後に、特に大きいです。このようなフロントエンドとして表示するために、それは特に醜いであろう。
(2)Q:なぜ、精度のあっ損失のですか?
A:とコンピュータ(バイナリストレージ)内の浮動小数点表示されている関連します。
使用JS IEEE 754
標準64ビットの倍精度浮動小数点表現を、この規格は、1980年代から、標準的な浮動小数点演算であり、最も広く用いられる浮動小数点演算ユニット、また、Javaのような多くの言語、Pythonの用途に多くのCPUのために使用。
この規格は、バイナリ浮動小数点が正確に(実際には、標準の浮動小数点数を正確に表現することができるものは何もありません)を表現することができない10進のほとんどになります。通常は、あなたが実際にコンピュータに保存されているのみで、小数点を入力すると、おおよそのバイナリ浮動小数点数を示します。
しかし、一定の誤差範囲(典型的には非常に小さい)内、処理時に多くの言語は、正しいターゲット番号に修正をもたらす最も近い分数出力にエラーの結果としてではなく実際のJSの存在よりも。
具体的な原理は見ることができます- 「ルアンYifeng浮動小数点バイナリ表現」ここでそれらを繰り返す、ではありません。
(3)Q:精度の損失を避けるためにどのように?
方法a:ハーフウェイ計算整数に
例えば、我々は、0.1 + 0.2を計算するために、それはまず、その後追加して、整数にそれを作るために数10によって乗算され、最終的に10で結果を分割したいです。
ので、整数精度が失われることはできません問題。(他に単にない整数精度)
実際には、多くのサードパーティライブラリは、この原理が使用されます。
方法2:使用するサードパーティ製のライブラリ
- Math.js
- decimal.js
- big.js
- bignumber.js
方法3:使用toFixed()関数(推奨)
console.log(parseFloat((0.3 + 0.1).toFixed(1))) // 0.4
注:toFixed()
と最高のparseFloat()
試合を使用します。toFixedはので、文字列を返します。
Q:toFixed()
なぜ、小数点の代わりに文字列を返す必要がありますか?[キー]
A:唯一のデジタルについては、JavaScriptのデータ型のためnumber
のタイプ、(C言語やデータベースとは異なりも二重整数、浮動小数点数を、分割されている)、および数タイプの先行ゼロと小数点を無視した後0に設定する(例えば、001 1であり; 1.1000 1.1)。
以下では、紹介していきます
toFixed()
と丸めに関しての特性を。
三、JSと計算方法
上記で:
- 精密計算
- 精密失われました
それはおそらく(小数点以下すなわち変更桁)精度の変更を行います。我々は統一精度が必要な場合は、それを使用する必要があります近似(计算)方法
。
1、丸め
(1)規則
丸めは、近似計算のための最も一般的な方法であり、定義により、特定のルールは、詳細には触れません。
(2)恐らくMath.round()
与えられた数の値は、最も近いに丸めた整数。
Math.Round(2.4) // 2
Math.Round(2.5) // 3
(3)_ラウンド() - 。lodash
与えられた数の値は最も近いに丸め数(分数であることができます)。
この方法のlodashは、私はあなたには、精度を丸め指定することができ、ちょうどそのような2番目のパラメータとして、いくつかの余分な機能を追加し、基礎となるが)恐らくMath.round(と呼ばれているソースコードを読みます。
const _ = require('lodash');
_.round(1.04, 1) //1
_.round(1.05, 1) //1.1
(4)は本当に公正丸め?[フォーカス]
そのため、学校での彼の非常に早い年齢で私は丸め、丸め学んだだけでは、実際に見つけることが、今までは慎重に考えて、公正であることが付与されている不公平。
たとえば、毎日自動的に関心をクリアし、あなたは宝のバランスをとるシナリオを想像しますが、(関心の規則に従って)算出した小数の値はアリペイのみコーナーにサポートすると仮定すると、ビットの多くを持っていること、そして、Alipayのシステムは、ときに簿記を支援します彼は丸めの方法を使用している場合は、間違いなく、あなたに近似計算を与えます:
const _ = require('lodash');
console.log(_.round(1.01, 1)) //1 (我亏了0.01)
console.log(_.round(1.02, 1)) //1 (我亏了0.02)
console.log(_.round(1.03, 1)) //1 (我亏了0.03)
console.log(_.round(1.04, 1)) //1 (我亏了0.04)
console.log(_.round(1.05, 1)) //1.1 (我赚了了0.05)
console.log(_.round(1.06, 1)) //1.1 (我赚了0.04)
console.log(_.round(1.07, 1)) //1.1 (我赚了0.03)
console.log(_.round(1.08, 1)) //1.1 (我赚了0.02)
console.log(_.round(1.09, 1)) //1.1 (我赚了0.01)
1.01 1.09 9つの数字の確率が一貫現れると仮定した場合まず、全体のドルや2ドル全体が、第二に、と考えることはできません。そして、最後のアリペイは確かだろう損失 1.1から1.05の部門は公平ではないので、。
また、描画できる数直線を反映します:
だから、どのようにそれがより公平な近似計算を行いますか?ここでは、バンカーの丸めを使用することができます。
2、バンカーの丸め
国際的に受け入れられている银行家舍入
(バンカーの丸め)アルゴリズム。
これは、IEEEによって設定された基準を丸めています。したがって、すべてのIEEE準拠の言語は、このルールを採用する必要があります。
(1)規則
知られているバンカーの丸め、丸みを帯びた銀行家でも取る(とも呼ばれるバンカーの丸め滞在ダブル)メソッドを。
ルールがあるので:丸みを帯びた銀行家が考慮すべき5つの非空に入った後、意外に入るために5の前に、さえあるべきに丸める前に5回の訪問、5後の空のパリティがあります。
キーは「奇偶5回の訪問は、空になった後、」それは場所を丸めている場合は、パリティが公正な確率分布であるので、その後、裁判官の前にパリティにそれを手渡し、円形またはない公正いずれかで、5であるからですA。
もちろん、唯一のアルゴリズムを丸めよりもアルゴリズムを丸め銀行家がいると言うことができ、より科学的であるこれらの結果は、生成された統計データに基づいているため、間違っているが、それは絶対的に正しくない、と丸め、前提はランダム分布を振っに沿って、これらのデータであり、要件。
(2)使用
あなたが使用したい場合はJSは現在、ネイティブにサポートしていません。
- 1、自分自身を達成するために
- 2、のようなNPMサードパーティ製のパッケージ、使用して銀行を、丸め
3、toFixed
toFixed()バンカーの丸めに沿ったセクションのルール。
(1)は、4つのオフ六
に沿って、
(2)5非空移行後
に沿って、
5でも意外に入るために5の前に、廃棄する前に、(3)5回の訪問パリティは、空であります
セクションの遵守
// //toFixed结果 //银行家舍入结果
console.log(1.05.toFixed(1)) //1.1(+0.05) 1.0(-0.05)
console.log(1.15.toFixed(1)) //1.1(-0.05) 1.2(+0.05)
console.log(1.25.toFixed(1)) //1.3(+0.05) 1.2(-0.05)
console.log(1.35.toFixed(1)) //1.4(+0.05) 1.4(+0.05)
console.log(1.45.toFixed(1)) //1.4(-0.05) 1.4(-0.05)
console.log(1.55.toFixed(1)) //1.6(+0.05) 1.6(+0.05)
console.log(1.65.toFixed(1)) //1.6(-0.05) 1.6(-0.05)
console.log(1.75.toFixed(1)) //1.8(+0.05) 1.8(+0.05)
console.log(1.85.toFixed(1)) //1.9(+0.05) 1.8(-0.05)
console.log(1.95.toFixed(1)) //1.9(-0.05) 2.0(+0.05)
// //总计(+0.1) //总计(0)
toFixedは確かにだけでなく、バンカーの丸めアルゴリズムで、丸い遵守差が見られます。(この特定の計算方法は、私は明確ではなかったのはなぜ、書き込まれます)
図4に示すように、別の近似関数
- Math.ceil():ラウンドアップ(丸いです)
- Math.floor():丸いダウン(丸いです)
- などなど......