2014-01-19 3 views
0

Мы знаем, что в C диапазон с плавающей запятой составляет от 1.xxxx * 10^-38 до 3.xxxx * 10^38 для одиночной точности.Операция с плавающей запятой в c

На моей лекции сползает есть эта операция:

(10^10 + 10^30) + (-10^30) ?= 10^10 + (10^30 + -10^30) 
10^30 - 10^30 ?= 10^10 + 0 

Я задаюсь вопросом, почему 10^10 + 10^30 = 10^30 в этом случае?
Я думал, что диапазон FP может опуститься до 10^-38 и до 10^38, не должно быть переполнения, поэтому `10^10 + 10^30 не должно заканчиваться 10^30.

+5

Вы должны проверить остальную часть слайдов, плавающие точки также ограничены в количестве значащих цифр. Таким образом, результат округлен и не точным. – Nabla

+1

@ yklee1013 «Мы знаем, что в C диапазон с плавающей запятой ...» не указан в C. В C диапазон _minimum_ 'float' составляет от 1E-37 до 1E + 37. Для представления о точности: минимальное значение «FLT_DIG» равно 6, а максимальное значение «FLT_EPSILON» равно 1E-5. C11 §5.2.4.2.2. Неудивительно, что 'float' на выбранной платформе (10^10 + 10^30) = (-10^30), просто недостаточно. – chux

ответ

2

Как сказано в комментарии к вашему вопросу, часть, в которой хранятся цифры, является конечной. Он называется значимым.

Рассмотрим следующий простой 14 битный формат:

[знаковый бит] [5 бит показатель] [8 бит мантисса]

да 'смещение' будет 16, то есть, если показатель степени 16 это на самом деле 0 (таким образом мы получаем хороший диапазон или +/- полномочия) и никаких подразумеваемых бит

, так что если у нас есть число больше, чем 2^8, кроме как 2048 и 0,5

в нашем формате:

2048 = 2^11 = [0] [11011] [1000 0000]

0,5 = 2^-1 = [0] [01111] [1000 0000]

когда мы добавим эти числа мы переходим экспонента, чтобы они имели одинаковые десятичные знаки. Десятичное аналогия:

5 х 10^3 + 5 х 10^-2 => 5 х 10^3 + 0,00005 х 10^3

поэтому siginifcand не могу удержать 12 мест:

2^11 + +0,000000000001 х 2^11 = +1,000000000001 х 2^11

так округляет назад 2^11

0

суть понятия значащих цифр. Это примерно 7 десятичных цифр для IEEE754 float. Если мы используем гипотетическое число десятичных чисел с плавающей запятой с 7 значащими цифрами, то расчет производится следующим образом:

10^10 + 10^30 == 1.000 000 * 10^10 + 1.000 000 * 10^30 
       == (0.000 000 000 000 000 000 01 + 1.000 000) * 10^30 (match the exponent part) 
       => (0.000 000 + 1.000 000) * 10^30 (round the left operand) 
       == 1.000 000 * 10^30 
       == 10^30 

Однако обратите внимание, что операция согласования и операция округления выполняются за один шагом, то есть. машина никогда не справится с 0.000 000 000 000 000 000 01 * 10^30, которая имеет слишком много значащих цифр.

Кстати, если вы проводите эксперименты с плавающей точкой арифметика в C, вы можете найти %a спецификатор формата полезных (введен в С99). Но обратите внимание, что printf всегда неявно преобразуют float аргументов double.

#include <stdio.h> 

int main() { 
    float x = 10e10, y = 10e30; 
    printf("(%a + %a) == %a == %a\n", x, y, x+y, y); 
    return 0; 
} 
Смежные вопросы