web-dev-qa-db-ja.com

浮動小数点数を宣言するときに「f」が必要なのはなぜですか?

例:

float timeRemaining = 0.58f;

数字の最後にfが必要なのはなぜですか?

75
Thomas

フロートの宣言には2つの部分が含まれます。

  1. 変数timeRemainingfloat型であることを宣言します。
  2. 0.58をこの変数に割り当てます。

この問題はパート2で発生します。

右側はそれ自体で評価されます。 C#仕様によると、サフィックスのない小数点を含む数値はdoubleとして解釈されます。

これで、double型の変数に割り当てるfloat値ができました。これを行うには、doubleからfloatへの暗黙的な変換が必要です。このような変換はありません。変換中に情報が失われる可能性があるためです(この場合は失われます)。

コンパイラが使用する値は実際には0.58ではなく、0.58に最も近い浮動小数点値であり、doubleの場合は0.57999999999999978655962351581366 ...であり、floatの場合は正確に0.579999946057796478271484375です。

厳密に言えば、fは必要ありません。値をfにキャストすることで、floatサフィックスを使用する必要がなくなります。

float timeRemaining = (float)0.58;
84
Jeffrey Sax

コンパイラが値0.58を表すために使用できるいくつかの数値型があるため、: floatdouble および- decimal 。コンパイラが選択してくれるのでなければ、明確にする必要があります。

doubleのドキュメントでは、自分で型を指定しない場合、コンパイラは常に実際の数値リテラルの型としてdoubleを選択すると述べています。

デフォルトでは、代入演算子の右側にある実数値リテラルはdoubleとして扱われます。ただし、整数をdoubleとして処理する場合は、サフィックスdまたはDを使用します。

サフィックスfを追加すると、floatが作成されます。接尾辞ddoubleを作成します。サフィックスmdecimalを作成します。これらはすべて大文字でも機能します。

ただし、これでコンパイルできない理由を説明するにはまだ不十分です。

float timeRemaining = 0.58;

答えの欠けている半分は、double0.58からfloattimeRemainingへの変換が潜在的に情報を失うため、コンパイラは暗黙的にそれを適用することを拒否するということです。明示的なキャストを追加すると、変換が実行されます。 fサフィックスを追加する場合、変換は必要ありません。どちらの場合も、コードはコンパイルされます。

36
Jon

問題は、.NETが、floatおよびdoubleを含むいくつかのタイプの暗黙的な操作を実行できるようにするために、混合オペランドを含むすべてのシナリオで何が起こるかを明示的に指定するか、そうでない場合は、型間の暗黙的な変換を一方向のみで実行できます。 MicrosoftはJavaのリードに従うことを選択しました。これは、精度をときどき好む方向を可能にしますが、しばしば正確さを犠牲にし、通常は面倒を生じさせます。

ほとんどすべての場合、特定の数値に最も近いdouble値を取得してfloatに割り当てると、その同じ量に最も近いfloat値が得られます。値9,007,199,791,611,905など、いくつかのコーナーケースがあります。最適なfloat表現は9,007,200,328,482,816(536,870,911でオフ)になりますが、最高のdouble表現(つまり9,007,199,791,611,904)をfloatにキャストすると9,007,199,254,740,992(536,870,913オフ)になります)。ただし、一般的に、ある量の最高のdouble表現をfloatに変換すると、可能な限り最高のfloat表現、または本質的に同等の2つの表現のいずれかが得られます。

この望ましい動作は、極端な場合でも適用されることに注意してください。たとえば、数量10 ^ 308の最適なfloat表現は、その数量の最適なfloat表現を変換することによって達成されるdouble表現と一致します。同様に、10 ^ 309の最高のfloat表現は、その量の最高のfloat表現を変換することによって達成されるdouble表現と一致します。

残念ながら、明示的なキャストを必要としない方向への変換は、ほとんど正確ではありません。値の最適なfloat表現をdoubleに変換すると、その値の最適なdouble表現に特に近いものはほとんど得られず、場合によっては結果がオフになります。数百桁(たとえば、10 ^ 40の最高のfloat表現をdoubleに変換すると、10 ^ 300の最高のdouble表現よりも大きい値が得られます。

悲しいかな、変換ルールはそのままなので、値を「安全な」方向に変換する際に愚かな型キャストと接尾辞を使用しなければなりません。また、しばしば誤った結果をもたらす危険な方向の暗黙の型キャストに注意してください。

2
supercat