0

インライン関数で周波数から周期への変換を行います。計算精度はdouble型ではなくlong型を使用する必要があります。そうしないと、丸め誤差が発生する可能性があります。次に、関数は結果をdoubleに変換します。以下のコードで、どの行が計算をlong型に保持するのか疑問に思っていました。パラメータ バーが 100、100.0、33.3333 のいずれであっても。

double foo(long bar)
{
  return 1000000/bar;
  return 1000000.0/bar;
  return (long)1000000/bar;
  return (long)1000000.0/bar;
}

自分で試してみたところ、4行目でうまくいきました。しかし、この場合の型変換の概念について疑問に思っています。

編集:

エラーの 1 つは、26.9993 ではなく、1000000/37038 = 26 です。

4

3 に答える 3

2
return 1000000/bar;

これは長いとして計算を行います。

return 1000000.0/bar;

これは double として計算を行います。

return (long)1000000.0/bar;

これは最初のものと同等です -- 1000000.0 は double ですが、除算のずっと前にキャストするため、除算は long で行われます。

于 2013-01-22T16:45:17.540 に答える
1

最初の行 (および 3 番目のより冗長な行) は、次のように計算を行いlong(C++ では常に結果を切り捨てます)、整数値を double として返します。存在についての質問であなたが何を言っているのか理解できませんbar33.3333それは可能なlong値ではないからです。

于 2013-01-22T16:46:17.713 に答える
1

あなたが提起したように、この問題は意味がありません。

barは整数型であるため、1000000/bar確実に よりも小さくなります。これは11000000で正確に表すことができます。そのため、すべての計算を整数演算で実行しても精度が向上することはありません。実際には、整数除算が得られます。この場合、小数部分が切り捨てられるため、 の値に対して精度が低くなります。ここでのto変換で問題が発生する唯一の方法は、への変換ですが、除算の最終結果の範囲を超えると、整数演算の場合と同様に 0 になります。doublebarlongdoublebardoubledouble

まだ:

1000000/bar

s間の除算を実行しlongます。1000000 はintまたは であり、プラットフォームlongに応じて 最初のオペランドは、必要に応じて a に昇格され、整数除算が実行されます。barlonglong

1000000.0/bar

doubles: の間の除算を実行します:1000000.0doubleリテラルなので、除算の前に にbar昇格します。double

(long)1000000/bar

最初のものと同等です。キャストは除算よりも優先され、1000000( alongまたは an のいずれかint) が a になるように強制されますlongbarが a の場合、 s のlong間で除算が行われます。long

(long)1000000.0/bar

は前のものと同等です:1000000.0は adoubleですが、これを a にキャストするlongと、整数除算が実行されます。


  1. C++ 標準がこの問題を委譲している C 標準では、doubles の仮数として最低 10 桁の 10 進数を要求し ( ) 、範囲外に出る前にDBL_DIG少なくとも10 のべき乗を要求しています(C99、附属書 E、¶ 4)。10**37DBL_MAX_10_EXP
于 2013-01-22T16:46:29.793 に答える