web-dev-qa-db-ja.com

doubleをfloatにキャストすると、常に同じ値が返されますか?

doublefloatにキャストすると常に同じ結果が得られますか、それとも「丸めの違い」がありますか?

たとえば、x

float x = (float)0.123456789d;

常に同じ値?

Floatをdoubleにキャストし、次にそれをfloatにキャストする場合はどうでしょうか。 (float)(double)someFloat

主にC#の結果に興味がありますが、これが他の言語でどのように機能するかについての知識があれば気軽に共有してください。

22
user925777

言語がIEEE仕様から逸脱していない限り、結果は言語に依存してはなりません。

すべての浮動小数点は、倍精度浮動小数点数として正確に表現できるため、浮動小数点数から倍精度浮動小数点数への往復では、開始時と同じ値が得られます。

同様に、double値をfloatにキャストすると常に同じ結果が得られますが、もちろん、同じfloat値に切り捨てられるさまざまなdouble値が多数あります。

12
phoog

downcastdoublefloatにダウンキャストすると、精度とデータが失われます。 floatからdoubleへのアップキャストは、widening変換です。ラウンドトリップされた場合、つまり、フロートにダウンキャストする前に値に何かを実行しない限り、データは失われません。

浮動小数点数は、rangeの精度と精度を犠牲にします。単精度浮動小数点数は、32ビットの精度を提供します。倍精度は64ビットを提供します。ただし、基になる精度が示す範囲外の値を表すことはできます。

C#floatおよびdoubleはIEEE 754浮動小数点値です。

  • float単精度IEEE 754値 (32ビット)であり、

    • 1ビット符号
    • 8ビット指数
    • 23ビット仮数/仮数
  • double倍精度IEEE 754値 (64ビット)であり、

    • 1ビット符号
    • 11ビット指数
    • 52ビットの仮数/仮数

仮数の有効な精度は、見かけのサイズ(浮動小数点マジック)より1ビット多くなります。

いくつかのCLR浮動小数点リソース:

この論文はおそらく、浮動小数点演算の危険と落とし穴に関する標準的な論文でしょう。 ACMのメンバーでない場合は、タイトルのリンクをクリックして、記事の公開ダウンロードを検索してください。

  • デビッド・ゴールドバーグ。 1991。 すべてのコンピューター科学者が浮動小数点演算について知っておくべきこと 。 ACM計算。 Surv。 23、1(1991年3月)、5-48。 DOI = 10.1145/103162.103163 http://doi.acm.org/10.1145/103162.10316

    要約
    浮動小数点演算は、多くの人々によって難解な主題と見なされています。これはかなり驚くべきことです。なぜなら、浮動小数点はコンピューターシステムではどこにでもあるからです。ほとんどすべての言語には浮動小数点データ型があります。 PCからスーパーコンピューターまでのコンピューターには、浮動小数点アクセラレーターがあります。ほとんどのコンパイラは、時々浮動小数点アルゴリズムをコンパイルするために呼び出されます。また、事実上すべてのオペレーティングシステムは、オーバーフローなどの浮動小数点例外に対応する必要があります。このホワイトペーパーでは、コンピューターシステムの設計者に直接影響を与える浮動小数点の側面に関するチュートリアルを紹介します。浮動小数点表現と丸め誤差の背景から始まり、IEEE浮動小数点標準の説明に続き、コンピューターシステムビルダーが浮動小数点をより良くサポートできる方法の例で締めくくります。

7
Nicholas Carey

場合によっては、数値に最も近いfloat表現が、最も近いdouble表現をfloatに丸めた値と異なる場合があります。このような2つの数量は、12,344,321.4999999991と12,345,678.50000000093です。これらの量の上下の整数はfloatとして正確に表現できますが、それらのそれぞれに最も近いdoubleの端数部分は正確に0.5です。そのようなdouble値(正確には0.5の端数を持つ2 ^ 23から2 ^ 24まで)をfloatに変換すると、最も近い偶数の整数に丸められます。コンパイラーは、それぞれの場合に、元の数値に近い値から切り捨てられます。

実際には、コンパイラは数値をdoubleとして解析し、floatに変換するように見えるため、12344321.4999999991fは12344321fに丸める必要がありますが、代わりに12344322fに丸めることに注意してください。同様に、12345678.50000000093fは12345679fに丸められますが、12345678fに丸められます。したがって、doubleに変換してからfloatに変換すると精度が失われる場合でも、float

ちなみに、値12344321.4999999992fと12345678.50000000094fは正しく丸められます。

1
supercat

それらが異なる精度を持っていることを考えると、私があなたがより低い精度からより広い精度にキャストしている場合でも(実際にはあなたの疑いだと思います)、結果は常に同じではありません。

浮動小数点演算、特にキャストは、常に切り捨て/丸めおよびその他のタイプのapproximationの対象です。

1
Tigran

C#の浮動小数点数は、IEEE 754形式(http://en.wikipedia.org/wiki/IEEE_754)を使用して保存されます。この形式には、数字と指数の2つの部分があります。ダブルは52桁、フロートは23桁を保持します。基数は10ではなく2です。したがって、上記の例(0.123456789)の場合、数字は111010110111100110100010101(123456789のバイナリ表現)になります。これは27桁で、浮動小数点数ではなく倍精度に収まります。そのため、往復変換では精度が失われます。

一方、数値が0.123456だった場合、数字は11110001001000000(17桁)になり、浮動小数点または小数のどちらにも快適に収まるため、ラウンドキャストで精度を失うことはありません。

0
Ethan Brown

Doubleは、floatのすべての可能な値を正確に保持できる必要があります。 floatをdoubleにキャストしても値は変更されず、その間にdoubleで計算を実行しなかった限り、floatにキャストすると元の値が返されます。

0
Kendall Frey