© 2008 Наталия Македа
Все материалы блога защищены авторским правом. Любая перепечатка или использование материалов этого блога в коммерческих целях возможна лишь с письменного согласия автора. При некоммерческом использовании ссылка на блог обязательна.

воскресенье, 27 апреля 2008 г.

2.3 Арифметические операторы: умножение, деление, деление по модулю

2.3 Арифметические операторы

По приоритетности за унарными операторами следуют арифметические операторы. Эта группа включает в себя четыре наиболее распространённых оператора: сложение, вычитание, умножение, деление. И не только их. Существует также оператор деления по модулю, который обозначается знаком %. Арифметические операторы разделены на две группы. В первой, более приоритетной, группе находятся *, /, %. Во второй, соответственно, + и -.

Умножение и деление (* и /)

Операторы * и / выполняют умножение и деление над всеми примитивными числовыми типами и char. При делении на ноль возникает ArithmeticException.

Вы, наверное, недоумеваете, зачем я вам рассказываю про умножение и деление известное вам с первого класса. Однако, в программировании мы имеем дело с некоторыми ограничениями, связанными с представлением чисел в компьютере. Эти ограничения накладываются на все числовые форматы, от byte до double. Но наиболее заметны они для целочисленного типа int.

Если вы умножаете или делите два числа, результат вычисляется посредством целочисленной арифметики и сохраняется либо в int, либо в long. Если числа очень большие, то результат будет больше максимального числа, которое можно представить в этих числах. А значит, результат не сможет правильно закодироваться компьютером и не будет иметь смысла. Например, тип byte используется для представления чисел в диапазоне от -128 до 127. Если мы умножим 64 и 4, то результат 256, имеющий в двоичной записи 100000000 девять символов, будет закодирован, как 0, потому что byte использует лишь 8 символов.

Рассмотрим деление. Если вы делите в целочисленной арифметике, результат должен быть обязательно целочисленным. И значит, дробная часть будет потеряна. Например, 7/4 даёт нам 1.75, но в целочисленной арифметике это будет 1.

Таким образом, если вы имеете дело со сложными выражениями, вы можете выбирать последовательность умножений и делений. Но имейте в виду, что умножение может привести к переполнению, а деление - к потере точности. Народная мудрость считает, что выполнение сначала умножений, а потом делений в большинстве случаев выдаёт правильный результат. Рассмотрим пример:

1. int a = 12345, b = 234567, c, d;
2. long e, f;
3.
4. c = a * b / b; // должно равняться а=12345
5. d = a / b * b; // тоже должно равняться а=12345
6. System.out.println(“a is “ + a +
7. “\nb is “ + b +
8. “\nc is “ + c +
9. “\nd is “ + d);
10.
11. e = (long)a * b / b;
12. f = (long)a / b * b;
13. System.out.println(
14. “\ne is “ + e +
15. “\nf is “ + f);

Результат работы данного фрагмента выдаст следующее:

a is 12345
b is 234567
c is -5965
d is 0
e is 12345
f is 0

Пусть вас не смущают числовые значения данного примера. Важно то, что при выполнении умножения первым мы получили переполнение (c is -5965), когда закодировали его в тип int. Однако мы можем получить правильный результат, если закондируем его в более длинный тип, как, например, long. В обоих случаях применение первым деления будет катастрофическим для результата, независимо от длины его типа.

Деление по модулю %

Результат деления по модулю - остаток от деления. Например, 7/4 равно 1 с остатком 3. Поэтому 7%4 = 3. Обычно операнды имеют целочисленный тип, но иногда оператор применяется и к числам с плавающей точкой. Также следует знать некоторые особенности данного оператора, когда операнды отрицательные.

При негативных или дробных операндах правило такое: вычитайте правый операнд из левого до тех пор, пока последний не станет меньше первого. Примеры:

17%5 = ? 17-5=12>5; 12-5=7>5; 7-5=2<5. Значит 17%5 = 2

21%7? 21-7=14>7; 14-7=7=7; 7-7=0<7. Значит 21%7 = 0

7.6%2.9? 7.6-2.9=4.7>2.9; 4.7-2.9=1.8<2.9. Значит 7.6%2.9=1.8

Заметьте: знак результата (положительный или отрицательный) целиком и полностью определён знаком левого операнда, то есть делимого.

Когда деление по модулю производится над дробными числами, то суть этой операции состоит в том, чтобы вычесть делитель несколько раз. Результат может быть также дробным числом.

Простое правило для отрицательных операндов такое: отбросьте знак минуса от операндов, произведите деление по модулю с положительными операндами, а затем поставьте перед результатом минус, если левый операнд (делимое) был отрицательным.

Деление по модулю, как и нормальное деление, может выбросить исключение ArithmeticException, если делитель (правый операнд) ровняется нулю.

2 комментария:

dream-x комментирует...
Этот комментарий был удален автором.
Алексей комментирует...

Спасибо.Доступно изложено о делении по модулю.