Перейти к содержанию

Как сравнить int, float и double

К общим материалам · К лабораторным

Что именно сравниваем

Для простого эксперимента возьмите небольшие целые исходные данные. Прочитайте их один раз в int, проверьте и скопируйте в float и double. Если исходные числа точно представимы во всех трёх типах, можно отдельно исследовать различия при вычислениях.

Выполните одну формулу три раза, сохраняя её скобки и порядок операций. Менять тип только у переменной результата недостаточно: важны типы операндов справа от =.

Для среды MSVC используются 32-битный int, 32-битный float и 64-битный double. До эксперимента убедитесь, что промежуточные целочисленные результаты укладываются в диапазон int. Переполнение не является способом показать «неточность» целых чисел.

Целочисленное деление

int a = 10;
int b = 3;
double wrong = a / b;

Здесь сначала выполняется деление двух int: получается 3. Затем 3 преобразуется в double. Дробная часть уже потеряна. Целочисленное деление отбрасывает дробную часть к нулю; это не округление к ближайшему целому.

Чтобы разделить в вещественном типе, сначала подготовьте операнды нужного типа.

Небольшой пример трёх расчётов

Это фрагмент для размещения внутри main; исходные числа в вашей программе должны поступать через scanf_s.

int a_i = 10;
int b_i = 3;

float a_f = a_i;
float b_f = b_i;

double a_d = a_i;
double b_d = b_i;

int result_i = a_i / b_i;
float result_f = a_f / b_f;
double result_d = a_d / b_d;

printf("int: %d\n", result_i);
printf("float: %.9f\n", result_f);
printf("double: %.17lf\n", result_d);

Ожидаемый вывод для обычных IEEE 754 float и double с округлением к ближайшему:

int: 3
float: 3.333333254
double: 3.33333333333333348

Математический ответ — точная дробь 10/3. Она не имеет конечной двоичной записи. Поэтому оба вещественных типа хранят приближение. Для примера 12/4 все три результата равны 3: различие типов не обязано проявляться на каждом вводе.

Константы тоже влияют на вычисление

Если в формуле есть числовая константа, запишите её в соответствующем типе.

Расчёт Константа 60 Константа 1000
int 60 1000
float 60.0f 1000.0f
double 60.0 1000.0

Суффикс f обозначает литерал float. Литерал 60.0 имеет тип double и может перевести часть выражения с float в вычисление с большей точностью. В данном эксперименте смешивать типы внутри одного расчёта не нужно.

Значащие цифры и цифры после точки

В обычной реализации MSVC у float около 6–7 значащих десятичных цифр, у double около 15–16. Это количество значащих цифр всего числа, а не фиксированное количество знаков после точки. См. описание типов Microsoft.

Для исследования выводите float через %.9f, а double через %.17lf. Это девять и семнадцать знаков после точки соответственно. Такое форматирование не увеличивает точность вычислений: часть напечатанных разрядов показывает округление. Число знаков после точки не равно числу достоверных значащих цифр. Для очень малых значений различие может оказаться дальше выбранного числа знаков. Короткая печать через %.2f для float и %.2lf для double тоже может скрыть различие.

Как записывать ожидания и сравнивать с эталоном

Сначала подставьте входы в математическую формулу и получите точную дробь либо десятичное число высокой точности. Ожидаемый результат int найдите по правилам целочисленных операций в указанном порядке. Для float и double можно указать приближённый эталон и допуск, не угадывая все последние разряды.

Допуски и требуемые форматы вывода задаются в условиях конкретной лабораторной. Их нельзя автоматически переносить на другой алгоритм: ошибка зависит в том числе от числа и порядка операций.

Если хотите численно оценить ошибку, абсолютная погрешность равна |полученный результат - математический эталон|. Для ненулевого эталона её можно разделить на |эталон| и получить относительную погрешность. Разность ответов float и double сама по себе не является точной ошибкой float: double тоже округляет.

Что написать в выводах

Укажите конкретные входы и результаты. Объясните, на каких наборах ответы совпали, а на каких различаются. Назовите операцию, при которой потерялась дробная часть в int. Отдельно объясните различие float и double и влияние формата печати. При желании повторите печать с %.2f для float и %.2lf для double и проверьте, какие отличия перестали быть видны.