2016-05-12 3 views
2

Я решаю одно из упражнений C Primer Plus, занимающихся потоком с плавающей точкой. Задача - имитировать его. Я сделал это так:Float underflow in C пояснение

#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 

я ожидал меньше точности для минимального значения с плавающей точкой разделить на два и четыре, но это, кажется, точность в порядке и нет сгущенной ситуации. Как это возможно? Я что-то пропустил?

Большое спасибо

+0

Аргументы, которые не соответствуют параметрам функций в прототипе претерпевают акции по умолчанию. –

+0

@Kerrek SB Ваш комментарий верен, но не влияет на так называемое отсутствие «ожидаемой меньшей точности» OP, если код использует IEEE 754 [binary32] (https://en.wikipedia.org/wiki/Single-precision_floating-point_format). – chux

ответ

1

Некорректное метод оценки точности как код простых водоразделы FLT_MIN (конечно, сила 2) 2.

Вместо начать с номером, который чуть выше степени 2 так его двоичный кодsignificand что-то вроде 1.000...(maybe total of 24 binary digits)...0001. Исключить значения, напечатанные изначально float. (FLT_MIN/2.0 является double.)

Обратите внимание ниже, что точность теряется, когда число становится меньше 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