Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Язык C. Ч3.docx
Скачиваний:
2
Добавлен:
01.07.2025
Размер:
254.2 Кб
Скачать

Int main(void)

{

float aboat = 32000.0;

double abet = 2.14e9;

long double dip = 5.32e-5;

printf("%f может быть записано как %e\n", aboat, aboat);

// для вывода следующей строки требуется компилятор,

// поддерживающий С99 или более поздний стандарт

printf("И его %а в шестнадцатеричной, представляющей степени 2, форме записи\п", aboat);

printf("%f может быть записано как %e\n", abet, abet);

printf("%Lf может быть записано как %Le\n", dip, dip);

return 0;

}

Ниже приведен вывод:

может быть записано как 3.200000е+04

И его 0xl.f4p+14 в шестнадцатеричной, представляющей степени 2, форме записи 2140000000может быть записано как 2.140000е+09

0.000053 может быть записано как 5.320000е — 05

Этот пример иллюстрирует стандартный вывод.

Переполнение и потеря значимости в операциях с плавающей запятой

Предположим, что наибольшее возможное значение типа float равно примерно 3.4Е38, и нужно выполнить следующие операции:

float toobig = 3.4Е38 * 100.Of;

printf("%e\n", toobig);

Что произойдет? Это пример переполнения, когда в результате вычислений получается слишком большое число, чтобы его можно было правильно представить. Поведение системы в таких случаях обычно не определено, но в рассматриваемой ситуации переменной toobig присваивается специальное значение, которое обозначает бесконечность, и функция printf () отображает либо inf, либо infinity (или какую- то другую вариацию на эту тему).

А что можно сказать о делении очень малых чисел? Здесь ситуация более сложная. Вспомните, что число типа float хранится в виде сочетания показателя степени и значащей части, или мантиссы. В рассматриваемом случае это число, имеющее минимально возможный показатель степени, а также наименьшее значение, которое использует все доступные биты, отведенные для представления мантиссы. Это будет наименьшее число, представленное с наибольшей точностью, доступной для типа float. Теперь разделим его на 2. Обычно это приводит к уменьшению показателя сте­пени, но в данном случае показатель уже достиг своего нижнего предела. Происходит сдвиг битов мантиссы вправо, с освобождением первой позиции и потерей последней двоичной цифры. Аналогичная картина возникает, если выбрать 10 в качестве осно­вания системы счисления, взять число с четырьмя значащими цифрами, например,

1234Е-10, и разделить его на 10, получив в итоге 0.0123Е-10. Вы получите результат, но в процессе деления потеряете цифру. Эта ситуация называется потерей значимости, а значения с плавающей запятой, которые утратили полную точность типа, в языке С называются субнормальными. Таким образом, деление наименьшего положительного значения с плавающей запятой на 2 дает субнормальное значение. Деление на доста­точно большое значение приведет к потере всех цифр, и вы получите в результате 0. В настоящее время библиотека С предоставляет функции, которые позволяют прове­рить, не приведут ли вычисления к субнормальным значениям.

Существует еще одно специальное значение с плавающей запятой: NaN (not-a-number — не число). Например, вы передаете функции asin () некоторое значение, а она возвращает угол, для которого переданное значение является синусом. Однако значе­ние синуса не может быть больше 1, поэтому функция не определена для значений, превышающих 1. В таких случаях функция возвращает значение NaN, которое функ­ция printf () отображает в виде nan, NaN или каким-то похожим образом.

Ошибки округления данных с плавающей запятой

Возьмите некоторое число, прибавьте к нему 1 и затем отнимите от суммы исходное число. Что вы получите в результате? Вы получите 1. Тем не менее, вычисления с плавающей запя­той вроде показанного ниже могут дать другой результат:

/* floaterг.с — демонстрирует ошибку округления */

#include <stdio.h>