Google Calculator の不具合、浮動小数点と二重の理由が考えられますか?
-
09-06-2019 - |
質問
私はこれをただのキックでやりました(つまり、正確な質問ではありません、すでにダウンモッディングが起こっているのはわかります)が、Google の新しく見つけた 無能 すること 数学 正しく (チェックしてください!Google によると、500,000,000,000,002 - 500,000,000,000,001 = 0)、ちょっとした理論を実行するために C で次のことを試してみようと思いました。
int main()
{
char* a = "399999999999999";
char* b = "399999999999998";
float da = atof(a);
float db = atof(b);
printf("%s - %s = %f\n", a, b, da-db);
a = "500000000000002";
b = "500000000000001";
da = atof(a);
db = atof(b);
printf("%s - %s = %f\n", a, b, da-db);
}
このプログラムを実行すると、次の結果が得られます
399999999999999 - 399999999999998 = 0.000000
500000000000002 - 500000000000001 = 0.000000
Google は単純な 32 ビット浮動小数点精度 (ここでのエラー) を使用しているように見えますが、上記のコードで float を double に切り替えると、問題は解決します。これでいいでしょうか?
/mp
解決
C# では、 (double.maxvalue == (double.maxvalue - 100)) を試してみると、 true が得られます...
しかし、それは本来あるべきものです:
http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems
考えてみると、2^64 (double.maxvalue) より大きい数値を表す 64 ビットがあるため、不正確さが予想されます。
他のヒント
この種の愚かさの詳細については、Windows 電卓に関するこの素晴らしい記事を参照してください。
算術エンジンの内臓は完全に捨てられ、ゼロから書き直されました。標準のIEEEフローティングポイントライブラリは、任意の前提条件算術ライブラリに置き換えられました。これは、Calcが10進数字類を正しく行うことができなかった方法についてのHa -Haの記事を作成し続けた後に行われました。たとえば、10.21-10.2を計算した結果、0.0100000000000016になりました。
Google は単純な 32 ビット浮動小数点精度 (ここでのエラー) を使用しているように見えますが、上記のコードで float を double に切り替えると、問題は解決します。これでいいでしょうか?
いいえ、問題を延期するだけです。ダブルでも同じ問題が発生しますが、数値が大きくなるだけです。
@ebel
考えてみると、2^64 (double.maxvalue) より大きい数値を表す 64 ビットがあるため、不正確さが予想されます。
2^64 は double の最大値ではありません。2^64 は、double (またはその他の 64 ビット型) が保持できる一意の値の数です。 Double.MaxValue
は 1.79769313486232e308 に等しくなります。
浮動小数点数の不正確さは、次の値より大きい値を表現することに起因するものではありません。 Double.MaxValue
(これは不可能ですが、 Double.PositiveInfinity
)。これは、必要な値の範囲がデータ型に適合するには大きすぎるという事実から来ています。したがって、より広い有効範囲と引き換えに精度を放棄します。本質的には、指数範囲を広げる代わりに有効数字を減らしています。
@DrPizza
均等ではありません。IEEE エンコードでは、同じ値に対して複数のエンコードが使用されます。具体的には、NaN は、全ビット 1 の指数と、仮数のゼロ以外の値によって表されます。したがって、ダブルには 252 個の NaN、シングルには 223 個の NaN があります。
真実。重複したエンコードについては考慮していませんでした。実際には2つあります52ダブルと 2 の場合は -1 NaN23ただし、シングルの場合は -1 NaN です。:p
2^64 は double の最大値ではありません。2^64 は、double (またはその他の 64 ビット型) が保持できる一意の値の数です。Double.MaxValue は 1.79769313486232e308 に等しくなります。
均等ではありません。IEEE エンコードでは、同じ値に対して複数のエンコードが使用されます。具体的には、NaN は全ビット 1 の指数で表され、 どれでも 仮数部のゼロ以外の値。したがって、2つあります52 double の NaN、223 シングルの場合は NaN。
真実。重複したエンコードについては考慮していませんでした。ただし、実際にはダブルスの NaN は 252-1、シングルスの NaN は 223-1 です。:p
ああ、無限を引くのを忘れていました。
私が学んだこの問題の大まかな推定バージョンは、32 ビット浮動小数点では 5 桁の精度が得られ、64 ビット浮動小数点では 15 桁の精度が得られるということです。もちろん、これは float がどのようにエンコードされるかによって異なりますが、出発点としては非常に適しています。