3

暗黙の型変換について少し混乱しています。次のプログラムを考えると

   float x = 4.23423451;
   double y = 4.23423451;

   float z = 101.9876;

   float res1 = x * z;
   float res2 = y * z;

   std::cout << "res1 & res2 " << res1 << "  & " << res2 << std::endl;
   std::cout << "equality " << (res1 == res2) << std::endl;

出力は

   res1 & res2 431.839  & 431.839
   equality 1

私の質問は、「x、y、z(x = y)の任意の値、および任意のコンパイラーについて、等式は常に真になるでしょうか?」です。

res2 = y * z;

変数「y」はfloatに型キャストされますか、それとも変数「z」はdoubleに型キャストされますか?

4

4 に答える 4

7

私のコメントを参照してください。

これは明確に定義されています。の中間式はzに広がりdouble、式y * zになりdoubleます。暗黙のナローイング変換は、floatに保存するために変換しres2ます。これと同じナローイングがに適用されres1ます。

これは、C++11標準の§5¶9式[expr]に反映されています。

算術型または列挙型のオペランドを期待する多くの二項演算子は、同様の方法で変換を引き起こし、結果型を生成します。目的は、結果のタイプでもある共通のタイプを生成することです。このパターンは通常の算術変換と呼ばれ、次のように定義されます。

..。

  • それ以外の場合、一方のオペランドがdouble、の場合、もう一方はに変換されdoubleます。
  • それ以外の場合、一方のオペランドがfloat、の場合、もう一方はに変換されfloatます。

..。

ただし、これは平等が維持されることを保証するものではありません。

そうは言っても、res1必ずしも同等である必要はありません-それは環境の精度と環境res2に大きく依存します。2つのリテラルは、等しくない可能性もあります。。と同等である必要はありません。に等しくなるかどうかはわかりません。floatdouble4.23423451f4.23423451static_cast<double>(static_cast<float>(4.23423451))4.23423451

§5.17¶3代入および複合代入演算子[expr.ass]を参照してください。

左のオペランドがクラス型でない場合、式は暗黙的に左のオペランドのcv非修飾型に変換されます(第4節)。

§4標準変換[conv]は次のように述べています。

標準変換は、組み込みの意味を持つ暗黙の変換です。条項4は、そのような変換の完全なセットを列挙しています。標準変換シーケンスは、次の順序での標準変換のシーケンスです。

..。

  • 次のセットからのゼロまたは1つの変換:積分プロモーション、浮動小数点プロモーション、積分変換、浮動小数点変換、浮動小数点変換、ポインター変換、メンバーへのポインター変換、およびブール変換。

§4.6浮動小数点プロモーション[conv.fpprom]で詳しく説明されているように、

  1. タイプのprvalueは、タイプのfloatprvalueに変換できますdouble。値は変更されません。
  2. この変換は浮動小数点プロモーションと呼ばれます。

...および§4.8浮動小数点変換[conv.double]

  1. 浮動小数点型のprvalueは、別の浮動小数点型のprvalueに変換できます。ソース値を宛先タイプで正確に表すことができる場合、変換の結果はその正確な表現になります。ソース値が2つの隣接する宛先値の間にある場合、変換の結果は、これらの値のいずれかの実装定義の選択になります。それ以外の場合、動作は未定義です。

  2. 浮動小数点プロモーションとして許可されている変換は、浮動小数点変換のセットから除外されます。

ここでの問題は、変換がプロモーションではなく、潜在的に低精度のタイプ(doubleto float)に絞り込まれる複数のケースがあることです。

double基本的に、に変換するときはいつでも、float精度が失われる可能性があります。

于 2012-09-12T21:06:55.717 に答える
3

浮動小数点値が等しいかどうかを比較しないでください。

于 2012-09-12T21:47:17.587 に答える
1

いいえ、これは保証されていません。必ずしも同じ値である必要はxありません。両方が式とでプロモートされることは事実ですが、doubleにプロモートした結果は、の値と等しくなる必要はありませんとして評価されるのに対し、式はdoubleに昇格し、乗算の結果が等しくなる必要はないため、より狭いタイプに戻すと異なる値になる可能性があります。ydoublex * zy * zxyx * zfloaty * zz

于 2012-09-12T21:07:27.607 に答える
0

鋳造は同じままである必要があります。ただし、プロセッサとOSが実際の数学に高精度で影響を与えるのを見てきました。

ただし、それはさておき、static_castを使用して明示的にします。

float res2 = static_cast<float>(y * static_cast<double>(z));

このようにして、誰もがあなたが何を意味しているのか、そしてあなたが物事を投げかけているのかを知っています。

于 2012-09-12T21:06:48.593 に答える