Опубликован: 27.09.2006 | Уровень: для всех | Доступ: свободно | ВУЗ: Московский государственный индустриальный университет
Лекция 4:

Особенности представления чисел в ЭВМ

< Лекция 3 || Лекция 4: 123 || Лекция 5 >

Арифметические и побитовые операторы языка Java

К арифметическим операторам языка Java, которые определены для всех числовых типов, относятся: + (сложение и унарный плюс), += (сложение с присваиванием), - (вычитание и унарный минус), -= (вычитание с присваиванием), * (умножение), *= (умножение с присваиванием), / (деление), /= (деление с присваиванием), % (остаток от деления или деление по модулю), %= (остаток от деления с присваиванием), ++ (инкремент) и -- (декремент).

Любой оператор с присваиванием с точки зрения получаемого результата эквивалентен выполнению соответствующей операции с последующим присваиванием, но работает обычно быстрее: a @= b эквивалентно а = a @ b (здесь символ @ означает любую из бинарных арифметических операций).

Результат выполнения операций деления и деления по модулю (нахождения остатка) для целочисленных операндов является целым числом. Так, например, 5/3 равняется 1.

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

int i = 2, j = 3;   // i = 2, j = 3
    int k = i + j++;    // k = 5, j = 4
    int m = --i;        // i = 1, m = 1

С величинами целых типов можно выполнять дополнительные действия. К побитовым (или поразрядным) операторам языка Java относятся следующие: ~ (дополнение), & (побитовое И ), &= (побитовое И с присваиванием), | (побитовое Или ), |= (побитовое Или с присваиванием), ^ (исключающее Или ), ^= (исключающее Или с присваиванием), << (сдвиг влево), <<= (сдвиг влево с присваиванием), >> (сдвиг вправо), >>= (сдвиг вправо с присваиванием), >>> (сдвиг вправо с размножением нуля) и >>>= (сдвиг вправо с присваиванием с размножением нуля).

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

Таблица 4.1. Битовые операции
a b ~a a|b a^b a&b
0 0 1 0 0 0
1 0 0 1 1 0
0 1 1 1 1 0
1 1 0 1 0 1

Например, 4^5 равняется 1 (ибо двоичные представления этих чисел есть соответственно 100 и 101 ).

У операторов сдвига второй аргумент показывает количество разрядов, на которое надо осуществить сдвиг в двоичном представлении первого операнда влево (для << ) или вправо (для >> и >>> ).

int i = 3, j = 100;	// i = 3, j = 100
    int k = i << 4;     // k = 48
    int m = j >> 2;     // m = 25

Легко понять, что сдвиг влево на n разрядов эквивалентен умножению на 2^n, а сдвиг вправо — делению на то же число.

Задачи для самостоятельного решения

Задача 4.3.Предъявите целое число x такое, что x + 1 < x.

Задача 4.4.Явно перечислите и изобразите на числовой прямой все точки множества \mathbb{R}_M, сделав следующие допущения: числа хранятся в нормализованной форме с плавающей точкой; для хранения как мантиссы, так и порядка числа отводится по три бита (из которых в обоих случаях один является знаковым); никаких особых значений нет.

Задача 4.5.Предъявите действительное (типа double ) число x такое, что (x /2) \cdot 2 \ne x. Воспользуйтесь тем, что класс java.lang.Double определяет константу MIN_VALUE.

Задача 4.6.Определите (приближенно) MACHEPS (машинное эпсилон) для типов double и float. Машинным эпсилоном называется наибольшее число x данного типа, удовлетворяющее соотношению 1+x=1.

Задача 4.7.Предъявите последовательность чисел (типа float ), при суммировании которой в прямом и обратном порядке результаты будут отличаться не менее, чем вдвое.

Задача 4.8.Напишите программу, вводящую действительные коэффициенты a, b и c квадратного уравнения a x^2 + b x + c = 0 с положительным дискриминантом, находящую оба корня этого уравнения достаточно точно во всех случаях.

Числа произвольной длины и точности

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

В случае языка Java пакет java.math дает возможность программисту работать с целыми и вещественными числами произвольной длины и точности, не требуя при этом никакого дополнительного кодирования, однако обсуждение данного пакета в нашем курсе не предполагается.

Некоторые задачи, требующие реализовать арифметические операции над целыми числами достаточно большой величины, будут рассмотрены в курсе далее, а вот проблемы, связанные с особенностями представления действительных чисел, нас интересовать не будут. О них придется вспомнить позже, при изучении курса вычислительной математики.

< Лекция 3 || Лекция 4: 123 || Лекция 5 >
Анастасия Халудорова
Анастасия Халудорова
екатерина яковлева
екатерина яковлева