9

Double から int への値の変換で問題に直面しています。私は次のコードを実行しようとします:

int main()
{
    double val_d= 6.25e-05;
    cout << (1/val_d) << endl;
    unsigned int val_ui = (unsigned int ) (1/val_d);
    cout << val_ui << endl;
}

double から int への変換では、小数部分が削除される場合がありますが、整数部分はそのままにする必要がありますか?

私が得る出力は次のとおりです:16000 15999

では、なぜここで o/p が異なるのでしょうか? これは、fedora でのみ発生しています。Windows と Ubuntu では正常に動作します。(両方の出力は 16000 です)

上記のコードを微調整したところ、次の結果が得られました。

int main()
{
  double val_d= 6.25e-05;
  cout << (1/val_d) << endl;
  double val_intermediate =  (1/val_d) ;
  cout << val_intermediate << endl;
  unsigned int val_ui = (unsigned int ) val_intermediate;
  cout << val_ui << endl;

}

新しい出力は 16000 16000 16000 です

4

3 に答える 3

16

ソース テキスト「6.25e-05」が 10 進数として解釈され、double に変換されると、正確に表現できません。 10 進数。6.25e-5 に最も近い IEEE 754 倍精度値は、6.2500000000000013010426069826053208089433610439300537109375e-05、または 16 進浮動小数点では 0x1.0624dd2f1a9fcp-14 です。

これの逆数を取ると、正確な数学的結果は正確に表現できないため、再度丸める必要があります。最も近い倍精度値は 16000 または 0x1.f4p+13 です。

C++ 標準により、実装では、公称型が必要とする精度よりも高い精度で浮動小数点式を評価できます。一部の実装では、拡張精度、特に 64 ビット仮数を持つ Intel の 80 ビット浮動小数点型が使用されます。(通常の倍精度の仮数部は 53 ビットです。) この拡張精度では、逆数は 0xf.9fffffffffffe89p+10 または 15999.9999999999966693309261245303787291049957275390625 です。

明らかに、拡張精度の結果が整数に切り捨てられると、結果は 15999 になります。

long-double の結果を double に丸めると、16000 になります (double への明示的なキャストでこれを行うことができます。中間値を double オブジェクトに割り当てる必要はありません)。

于 2012-09-06T13:18:36.140 に答える
6

四捨五入の違い。

  1. (1/val_d) - double は、倍精度で表現できる最も近い数値に丸められます。(例: 3.6999999999999999 == 3.7)
  2. (unsigned int ) (1/val_d) - int へのキャストで小数部分が切り捨てられた場合、切り捨てられます(例: int(3.6) == 3
于 2012-09-06T11:33:55.203 に答える
1

浮動小数点値を整数値に変換すると、結果が整数型で表現できる場合 (つまり、値が大きすぎて収まらない場合)、小数部分が削除されます。ストリームに挿入すると値が丸められるため、異なる結果が生じる可能性があります。

于 2012-09-06T11:13:47.950 に答える