js の桁数が大きすぎてパラメーターの精度が失われる例を共有します
最近、js 関数でパラメーターを渡すときに、渡される桁数が比較的大きいという奇妙な問題に遭遇しました。引数を出力すると、渡されたパラメータが変更されていることがわかります。
そこで調べてみたところ、確かにjsの精度の低下が原因であることが分かりました。私の解決策は、精度を失わないように、数値型を文字型の送信に変更することです。以下に示すように:
コンピューターのバイナリ実装と桁数の制限 数値の中には有限に表現できないものがあります。 pi 3.1415926...、1.3333... など、一部の無理数を有限に表現できないのと同じです。 JSはIEEEに準拠しています 754 仕様では、64 ビットを占有する倍精度ストレージ (倍精度) を使用します。図に示すように
意味
符号ビットを表すために 1 ビットが使用されます
指数を表すために 11 ビットが使用されます
52 ビットが仮数を表します
フローティングこのとき
0.1 >> 0.0001 1001 1001 1001…(1001无限循环) 0.2 >> 0.0011 0011 0011 0011…(0011无限循环)
などのポイント数 四捨五入は10進法しか真似できませんが、2進法は0と1しかないので四捨五入すると0と1になります。これが、コンピュータの一部の浮動小数点数演算におけるエラーや精度の低下の根本原因です。
大きな整数の精度の低下は、浮動小数点数の精度の低下と本質的に同じです。仮数部の最大桁数は 52 桁であるため、JS で正確に表現できる最大の整数は Math.pow(2, 53) です。 10 進数では 9007199254740992 です。
9007199254740992より大きい場合は精度が落ちる可能性があります
9007199254740992 >> 10000000000000...000 // 共计 53 个 0 9007199254740992 + 1 >> 10000000000000...001 // 中间 52 个 0 9007199254740992 + 2 >> 10000000000000...010 // 中间 51 个 0
実際
9007199254740992 + 1 // 丢失 9007199254740992 + 2 // 未丢失 9007199254740992 + 3 // 丢失 9007199254740992 + 4 // 未丢失
結果は図の通りです
上記により、一見有限に見える数がバイナリでは無限であることが分かりますストレージビットのため、数値の制限に「丸め」が発生し、精度の低下が発生します。
想了解更深入的分析可以看这篇论文(又长又臭):What Every Computer Scientist Should Know About Floating-Point Arithmetic
对于整数,前端出现问题的几率可能比较低,毕竟很少有业务需要需要用到超大整数,只要运算结果不超过 Math.pow(2, 53) 就不会丢失精度。
对于小数,前端出现问题的几率还是很多的,尤其在一些电商网站涉及到金额等数据。解决方式:把小数放到位整数(乘倍数),再缩小回原来倍数(除倍数
// 0.1 + 0.2 (0.1*10 + 0.2*10) / 10 == 0.3 // true
以上がjs の桁数が多すぎてパラメータの精度が失われる例を共有します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。