В КУРСЕ?

Разбираемся в теме

Почему Java делит семь на два и получает три, даже если переменная имеет тип double?

В Java математически знакомая операция может дать неожиданный результат, если не учитывать типы данных. Особенно часто это проявляется при делении целых чисел. Запись результата в double не возвращает уже отброшенную дробную часть. Разберём порядок вычисления на простых выражениях, которые можно сначала проверить вручную без установки инструментов.

Сначала вычисляется правая часть

В выражении 7 / 2 оба числовых литерала имеют целочисленный тип int. Поэтому выполняется целочисленное деление, результат которого равен 3. Это не обычное округление до ближайшего числа: дробная часть отбрасывается в направлении нуля. Если затем результат присваивается переменной типа double, число 3 преобразуется в 3.0. Само деление уже завершено. Например, в записи double result = 7 / 2; переменная способна хранить дробные значения, но получает уже вычисленный целый результат. Тип места хранения не меняет задним числом операцию над исходными значениями.

Преобразуйте операнд до деления

Чтобы получить дробный результат в данном примере, можно записать 7 / 2.0. Литерал 2.0 имеет тип double, поэтому операция выполняется с числами с плавающей точкой и даёт 3.5. Если исходные значения находятся в переменных int a = 7; и int b = 2;, аналогичную задачу решает выражение (double) a / b. В нём преобразование a происходит до деления. Другой вариант, (double) (a / b), работает иначе: скобки требуют сначала вычислить целочисленное частное, и только потом преобразовать 3 в 3.0. Внешне записи похожи, но место преобразования меняет результат.

Выбирайте операцию по смыслу задачи

Предположим, девять карандашей нужно распределить по коробкам, в каждую из которых помещаются четыре. Для вопроса о числе полностью заполненных коробок целочисленное деление 9 / 4 даёт полезный ответ: две. Дробная коробка здесь не является полностью заполненной. Если же девять обозначает общий объём работы, а четыре число одинаковых промежутков времени, средний объём на промежуток может быть дробным. Тогда 9 / 4.0 даёт 2.25. Одинаковые исходные числа не определяют подходящий тип результата без понимания вопроса. Не нужно автоматически заменять все int на double ради устранения одного неожиданного вывода.

Проверяйте границы и промежуточные значения

Для целочисленного деления полезно проверить отрицательный пример: -7 / 2 даёт -3, поскольку округление направлено к нулю. Деление целого числа на ноль приводит к исключению, поэтому допустимость делителя следует учитывать в задаче. При этом числа с плавающей точкой имеют собственные правила и не являются универсальным способом избежать ошибок. При разборе выражения запишите тип каждого операнда, порядок действий, промежуточный результат и только затем тип итоговой переменной. Такой подход помогает понять причину, а не запомнить отдельный удачный шаблон. Для денежных и других точных десятичных вычислений отдельно рассматривают подходящие типы и правила округления: пример с половиной не решает все задачи точности.

Попробуйте на практике

Предскажите результаты нескольких выражений на бумаге и объясните различие до проверки в Java.

  1. Для выражений 7 / 2 и 7 / 2.0 подпишите типы операндов и ожидаемые значения.
  2. Разберите запись double result = 7 / 2; в два этапа: вычисление правой части и присваивание.
  3. Сравните (double) (7 / 2) и (double) 7 / 2, отметив момент преобразования.
  4. Вычислите -7 / 2 и объясните, чем округление к нулю отличается от округления вниз.
  5. Для девяти карандашей и коробок по четыре выберите подходящее деление, а затем сравните его с вычислением среднего 9 / 4.0.

Как проверить результат. Получены 3, 3.5, значение result 3.0, результаты преобразований 3.0 и 3.5, отрицательное частное -3. Для полных коробок ответ 2, для указанного среднего 2.25.

Частые вопросы

Точка в 2.0 действительно меняет вычисление?

Да. Она задаёт в этом примере литерал типа double, что влияет на числовое преобразование операндов и вид выполняемого деления.

Почему преобразование результата не помогает?

К моменту преобразования дробная часть уже потеряна при целочисленной операции. Изменение типа результата не восстанавливает сведения, которых в нём больше нет.

Самостоятельный разбор темы. Содержание конкретной обучающей программы здесь не представлено.

Зарегистрируйтесь, чтобы уточнить возможность доступа к этому материалу

Зарегистрироваться
← К списку материалов