@dandropov95

Почему не переполняется float?

#define _CRT_SECURE_NO_WARNINGS

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

int main(void)
{
	float value = FLT_MAX * 1.0000001f; // FLT_MAX + 1.0f

	printf("%e", value);

	_getch();

	return 0;
}


Почему взяв максимальное значение типа float и умножив его например на 1.0000001, получаем бесконечность, а если к этому (вроде как максимальному) числу прибавить 1.0f (или какое либо значение), то выводится все равно максимальное значение (3.402823e+38), но никак не бесконечность?
Значение же вроде как указано максимальное и прибавив к нему малое* число получается больше чем максимум. А если умножать на число, то получается переполнение и выводится inf. Объясните почему именно так, с умножение переполняется, а при сложении как будто просто отсекаются лишние биты. (Единственная догадка это внутреннее хранение вещественного числа)
  • Вопрос задан
  • 1095 просмотров
Пригласить эксперта
Ответы на вопрос 3
maaGames
@maaGames
Погроммирую программы
Магия плаващих точек :)
Числа должны быть примерно одного порядка, иначе UB (с оговорками).
3.4е38 + 1.0 = 3.4е38. Это равнозначно 3.4е38 + 0.0, потому что 1 по сравнению с 1е38 равно нулю.
А при умножении различие будет уже в 7 знаке после запятой, которую float может обнаружить и сообщить о переполнении (+INF).
Ответ написан
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
Объясните почему именно так, с умножение переполняется, а при сложении как будто просто отсекаются лишние биты.

Потому что именно так и есть: для сложения числа приводятся к одному порядку. Порядок FLT_MAX -- 2^127, порядок 1.0 -- 2^0. Т.е. единица сдвигается на 127 разрядов вправо перед сложением с FLT_MAX. Ни в одном стандартном представлении чисел с плавающей точкой столько разрядов не предусмотрено, лишние разряды отсекаются, единица превращается в 0.

Минимальное число, которое можно прибавить к FLT_MAX и получить бесконечность равно 2 ^ (127 - 24). При нормализации этого числа с FLT_MAX получается единица сдвинутая вправо на 24 разряда, как раз в последний значащий разряд мантиссы float.
Ответ написан
Комментировать
@Mercury13
Программист на «си с крестами» и не только
Представьте, у нас десятичная арифметика с тремя значащими цифрами. Соответственно, сложение работает не более чем с пятью цифрами: три собственно значащих, слева на перенос и справа на округление. То, что получилось, в любом случае будет округлено до трёх.
 99900000000000
+             1,00
 -----------------
 9990   →   9,99e13

Если сделать второе слагаемое покрупнее, то будет
 99900000000000
+   50000000000
 -----------------
 9995   →   1,00e14 → переполнение


То есть вот что надо добавить, чтобы случилось переполнение: в зависимости от настроек сопроцессора или ulp(FLT_MAX) (ULP = Unit of Last Place — цена младшего разряда на данном порядке), или ulp(FLT_MAX)/2.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы