37

なぜこれが起こるのか説明できますか?

static void Main()
{
    const float xScaleStart = 0.5f;
    const float xScaleStop = 4.0f;
    const float xScaleInterval = 0.1f;
    const float xScaleAmplitude = xScaleStop - xScaleStart;

    const float xScaleSizeC = xScaleAmplitude / xScaleInterval;

    float xScaleSize = xScaleAmplitude / xScaleInterval;

    Console.WriteLine(">const float {0}, (int){1}", xScaleSizeC, (int)xScaleSizeC);

    Console.WriteLine(">      float {0}, (int){1}", xScaleSize, (int)xScaleSize);

    Console.ReadLine();
}

出力:

>const float 35, (int)34
>      float 35, (int)35

0.1 のバイナリ表現が実際には 0.09999990463256835937 であることはわかっていますが、なぜこれが「float」ではなく「const float」を使用して発生するのでしょうか? これはコンパイラのバグと見なされますか?

記録のために、コードは次のようにコンパイルされます。

private static void Main(string[] args)
{
    float xScaleSize = 35f;
    Console.WriteLine(">const float {0}, (int){1}", 35f, 34);
    Console.WriteLine(">      float {0}, (int){1}", xScaleSize, (int)xScaleSize);
    Console.ReadLine();
}
4

2 に答える 2

17

これの「理由」は基本的に、データを操作するときに、 orfloatに指定されているよりも高い精度を持つ内部表現が頻繁に使用される可能性があるという事実に要約されます。これは、仮想実行システム (VES) 仕様 (パーティション Iのセクション 12) で明示的に規定されています。floatdouble

浮動小数点数は、内部浮動小数点型を使用して表されます。そのような各インスタンスでは、変数または式の公称型は または のいずれfloat32float64ですが、その値は追加の範囲および/または精度で内部的に表すことができます

その後、次のようになります。

開発者がコードに一見関係のない変更を加えた場合、それよりも広い、float32またはfloat64計算結果に違いを引き起こす可能性のある内部表現の使用。その結果、値が内部表現 (レジスタなど) からこぼれる可能性があります。スタック上の場所に。

さて、C#言語仕様によると:

定数式のコンパイル時評価では、非定数式の実行時評価と同じ規則が使用されますが、実行時評価で例外がスローされる場合、コンパイル時評価によってコンパイル時エラーが発生する点が異なります。

しかし、上で見たように、ルールでは実際にはより多くの精度を使用できる場合があり、この強化された精度が使用される場合は、実際には直接制御できません。


そして明らかに、さまざまな状況では、結果はあなたが観察したものとは正反対になる可能性があります.コンパイラはより低い精度に落ち、ランタイムは代わりにより高い精度を維持した可能性があります.

于 2014-06-03T13:52:27.523 に答える