100

させて:

double d = 0.1;
float f = 0.1;

表現する必要があります

(f > d)

戻るtruefalse

経験的に、答えはtrueです。しかし、私はそれがfalse.

as0.1は 2 進数で完全に表すことはできませんが、double は10 進数15まで16の精度が必要であり、float は7. したがって、どちらも 未満ですが0.1、double は により近くなり0.1ます。

の正確な説明が必要trueです。

4

7 に答える 7

172

答えは、 を に変換するときの丸めモードに依存すると思いdoubleますfloatfloat24バイナリビットの精度があり、double53 です。バイナリでは、0.1 は次のとおりです。

0.1₁₀ = 0.0001100110011001100110011001100110011001100110011…₂
             ^        ^         ^   ^ 
             1       10        20  24

したがって、24 桁目を切り上げると、次のようになります。

0.1₁₀ ~ 0.000110011001100110011001101

これは、正確な値よりも大きく、53 桁のより正確な概算値よりも大きくなっています。

于 2013-10-10T09:46:56.730 に答える
55

数値 0.1 は、指定された精度で最も近い浮動小数点表現に丸められます。この近似値は 0.1 より大きいか小さいかのいずれかである可能性があるため、実際の値を見ないと、単精度または倍精度の近似値が大きいかどうかを予測できません。

倍精度値は次のように丸められます (Python インタープリターを使用):

>>> "%.55f" % 0.1
'0.1000000000000000055511151231257827021181583404541015625'

そして、単精度値は次のとおりです。

>>> "%.55f" % numpy.float32("0.1")
'0.1000000014901161193847656250000000000000000000000000000'

したがって、単精度近似の方が大きいことがわかります。

于 2013-10-10T09:43:39.867 に答える
19

.1バイナリに変換すると、次のようになります。

0.000110011001100110011001100110011001100110011001100...

永遠に繰り返す

データ型にマッピングすると、次のようになります。

float(.1) = %.00011001100110011001101
                                     ^--- 丸めに注意
double(.1) = %.0001100110011001100110011001100110011001100110011010

それを基数 10 に変換します。

float(.1) = .10000002384185791015625
double(.1) = .100000000000000088817841970012523233890533447265625

これは、Bruce Dawson によって書かれた記事から引用されました。ここで見つけることができます:
Doubleはfloatではないため、比較しないでください

于 2013-10-10T14:13:55.000 に答える
5

質問に対する Eric Lippert のコメントが実際には最も明確な説明だと思うので、回答として再投稿します。

10 進数 3 桁と 10 進数 6 桁で 1/9 を計算しているとします。0.111 < 0.111111 ですよね?

ここで、6/9 を計算しているとします。0.667 > 0.666667 ですね。

6/9 に最も近い 3 桁の 10 進数ではないため、3 桁の 10 進数で 6/9 を 0.666 にすることはできません。

于 2013-10-14T12:49:15.520 に答える
4

正確に表すことができないため、2 進数で 1/10 を比較することは、10 進数で 1/7 を比較するようなものです。

1/7 = 0.142857142857... しかし、異なる基数 10 の精度 (小数点以下 3 桁対 6 桁) で比較すると、0.143 > 0.142857 になります。

于 2013-10-10T17:51:12.510 に答える
1

IEEE-754 と x86 について話している他の回答に追加するだけです。この問題は、見た目よりもさらに複雑です。IEEE-754 には 0.1 の表現が「1 つ」ではなく、2 つ存在します。最後の桁の切り上げまたは切り上げのいずれかが有効です。x86 は内部の浮動小数点計算に 64 ビットを使用しないため、この違いが実際に発生する可能性があります。実際には 80 ビットを使用しています。これは倍精度拡張精度と呼ばれます。

そのため、x86 コンパイラだけでも、同じ数値が 2 つの異なる方法で表現されることがあります。これは、バイナリ表現を 64 ビットで計算するものと、80 を使用するものがあるためです。


実際、同じコンパイラでも、同じマシンでも発生する可能性があります。

#include <iostream>
#include <cmath>

void foo(double x, double y)
{
  if (std::cos(x) != std::cos(y)) {
    std::cout << "Huh?!?\n";  //← you might end up here when x == y!!
  }
}

int main()
{
  foo(1.0, 1.0);
  return 0;
}

なぜでcos(x) != cos(y)あってもx == y参照してください詳細については。

于 2013-10-10T16:44:04.400 に答える