3

float アンダーフローを扱う C Primer Plus 演習の 1 つを解いています。課題は、それをシミュレートすることです。私はこのようにしました:

#include<stdio.h>
#include<float.h>

int main(void)
{
    // print min value for a positive float retaining full precision
    printf("%s\n %.150f\n", "Minimum positive float value retaining full precision:",FLT_MIN);

    // print min value for a positive float retaining full precision divided by two
    printf("%s\n %.150f\n", "Minimum positive float value retaining full precision divided by two:",FLT_MIN/2.0);

    // print min value for a positive float retaining full precision divided by four
    printf("%s\n %.150f\n", "Minimum positive float value retaining full precision divided by four:",FLT_MIN/4.0);

    return 0;
}

結果は

Minimum positive float value retaining full precision:                 0.000000000000000000000000000000000000011754943508222875079687365372222456778186655567720875215087517062784172594547271728515625000000000000000000000000
Minimum positive float value retaining full precision divided by two:  0.000000000000000000000000000000000000005877471754111437539843682686111228389093327783860437607543758531392086297273635864257812500000000000000000000000
Minimum positive float value retaining full precision divided by four: 0.000000000000000000000000000000000000002938735877055718769921841343055614194546663891930218803771879265696043148636817932128906250000000000000000000000

最小浮動小数点値を 2 と 4 で除算する精度が低いと予想していましたが、精度は問題ないようで、アンダーフローの状況はありません。それはどのように可能ですか?私は何か見落としてますか?

どうもありがとうございました

4

1 に答える 1

1

FLT_MINコードは単純に(確かに 2 の累乗) を 2 で除算するため、精度を評価する不適切な方法です。

代わりに、2 の累乗を少し上回る数から始めて、2進数の 仮数が のようになるようにし1.000...(maybe total of 24 binary digits)...0001ます。印刷された保険の値が元のものであることを確認してfloatください。(FLT_MIN/2.0doubleです。)

数値が :正規化さFLT_MINれた最小の正の浮動小数点数 よりも小さくなると、精度が失われることに注意してください。

また、考慮してFLT_TRUE_MINください:最小の正の浮動小数点数。binary32を参照

#include <float.h>
#include <math.h>
#include <stdio.h>

int main(void) {
  char *format = "%.10e %a\n";
  printf(format, FLT_MIN, FLT_MIN);
  printf(format, FLT_TRUE_MIN, FLT_TRUE_MIN);

  float f = nextafterf(1.0f, 2.0f);
  do {
    f /= 2;
    printf(format, f, f);  // print in decimal and hex for detail
  } while (f);
  return 0;
}

出力

1.1754943508e-38 0x1p-126
1.4012984643e-45 0x1p-149

5.0000005960e-01 0x1.000002p-1
2.5000002980e-01 0x1.000002p-2
1.2500001490e-01 0x1.000002p-3
...
2.3509889819e-38 0x1.000002p-125
1.1754944910e-38 0x1.000002p-126
5.8774717541e-39 0x1p-127  // lost least significant bit of precision
2.9387358771e-39 0x1p-128
...
2.8025969286e-45 0x1p-148
1.4012984643e-45 0x1p-149
0.0000000000e+00 0x0p+0
于 2016-05-12T18:15:46.597 に答える