2017-11-04 16 views
2

私は2つの数値を比較したいと思います。次の例の数値は、2つの異なるシステムで計算された26^26の結果です。その一つが私のJavaScriptコードです。Javascriptの大きな数字を比較する

AssertionError [ERR_ASSERTION]: 4.0329146112660565e+26 == 4.0329146112661e+26 

彼らは明らかに等しくないだが、理論的には彼らがすべき:2つの数値を比較するとき

はしかし、私はこのようなものになってしまいます。

javascriptの大きな数字(たとえ近似値であっても)で平等を実行する適切な方法は何ですか?

+1

https://github.com/MikeMcl/bignumber。js/ – shotgunner

+0

数字を文字列に変換して比較することができます – guest271314

+1

**平等**とはどういう意味ですか?厳密に等しい?またはいくつかの桁で等しい?固定精度内で等しいか等しいか?お互いに丸めることができる数字ですか?指定してください –

答えて

1

var a = 4.0329146112660565e + 26;

var b = 4.0329146112661e + 26;

=恐らくMath.round(/ 10E + 20)* 10E + 20

B =恐らくMath.round(B/10E + 20)* 10E + 20

== B。

+0

@Daniel Lordありがとうございました! '10e + 20'はやや魔法のようです。あなたはそれの背後にある論理を説明してもらえますか?このソリューションは、@ GitaarLABの 'Number.MAX_SAFE_INTEGER'に関する提案と組み合わせることで、私のトリックになります。 'Math.round(4.0329146112661e + 26/Number.MAX_SAFE_INTEGER)* Number.MAX_SAFE_INTEGER; ' – Wazeem

+0

@Sam D.浮動小数点数が異なるので、精度が12未満であるように思えます。このソリューションは、26 - 20 + 1 = 7の精度に丸めます。浮動小数点の7つのロジックの精度で動作します。 20を変更して、比較の精度を上げたり下げたりします。 –

+0

なぜ '20'と' 26'を数値にキャストすれば、それはすでに数値です: '10e + 20 == 10e20' – dandavis

3

あなたがしようとしているのは、2つの数字が実質的に同等であるかどうかを判断する場合は、誤差の余裕がなければなりません。これを行う1つの方法は、数値の差を計算し、その差が重要かどうかを判断することです。

したがって、前回の数値から、これらの数値の差を減算して評価することができました。私たちはこの違いの兆候を本当に気にしないので、私は先に進んで違いの絶対的な価値を得るでしょう。

Math.abs(4.0329146112660565e+26 - 4.0329146112661e+26) === 4329327034368 

(追記:今、理由を説明する時間はありませんが、JavaScriptで==演算子は混乱とエラーが発生しやすい行動を持っている、あなたが値を比較したい場合===使用)

その差は大きい数字ですが、最初の数字がどれほど大きいかに関係なく、それは重要ではありません。直感的に、私はそうのような独自の番号の最小によって違いを分割するように誘惑しています:

4329327034368/4.0329146112660565e+26 === 1.0734983136696987e-14 

かなり少ないように見えます。一連の値で同じ操作を繰り返し、エラーのマージンをどのようにしたいかを判断できるはずです。そして、あなたがしなければならないことは、任意の数字で同じ操作を行い、その "差異比"があなたのために十分に小さいかどうかを見ることです。

function similar(a, b) { 
    let diff = Math.abs(a - b); 
    let smallest = Math.min(Math.abs(a), Math.abs(b)); 
    let ratio = diff/smallest; 
    return ratio < MARGIN_OF_ERROR; 
} 

ここで、2つの数字の違いの重要性を判断する方法を考え出しました。それを計算するのは非常に賢明な方法ではないかもしれませんが、状況によっては適切かもしれないし、他の状況では適切でないかもしれません。しかし、一般的な考え方は、2つの値が "close"という独自の定義で十分に近いかどうかを判断する関数を作る必要があることです。

JavaScriptは数学で扱える最悪の言語の1つです。Number.MAX_SAFE_INTを超えると整数は不正確になります(Chromeでは9007199254740991と思われますが、ブラウザやそれが標準化された定数の場合)。

+1

標準化定数! IEEE 754浮動小数点の自然な結果:マントラを覚えていて、最初の53ビットが格納されています(そして指数)。編集:SAFE intを必要とするため、最後に取り得る値は含まれません。 2 ** 53 + 1と2 **を区別できません** 53 – GitaarLAB

+0

これは実際に**相対**精度で**固定**ではありませんが、確かに助けになります –

+1

sidenote:javascriptの数学で何も問題ありませんそれはたくさんあります)。ちょうど1つの数値タイプがあることを理解してください:IEEE 747 64bit float。あなたはまだ私の+1を持っている!編集:表現したい値が53以上の重要なビットを必要としない限り、それ以上の数で信頼できる数学を行うことさえできます!ネイティブの数字を使用してかなり興味深いアルゴリズム(通常はバイナリ)を実装できることを理解したら – GitaarLAB

関連する問題