25

25


Операции И, ИЛИ и НЕ применяются только к логическим (boolean) значе¬ниям. Нельзя использовать в логических выражениях не-Ьоо1еап-типы в качест¬ве булевых, как это разрешается в С и С++. Неудачные попытки такого рода видны в строках, помеченных особым комментарием //! (этот синтаксис позво¬ляет автоматически удалять комментарии для удобства тестирования). После¬дующие выражения вырабатывают логические результаты, используя операто¬ры сравнений, после чего к полученным значениям примененяются логические операции.

Заметьте, что значение boolean автоматически переделывается в подходящее строковое представление там, где предполагается использование строкового типа String.

Определение int в этой программе можно заменить любым примитивным типом, за исключением boolean. Впрочем, будьте осторожны с вещественными числами, поскольку их сравнение проводится с крайне высокой точностью. Число, хотя бы чуть-чуть отличающееся от другого, уже считается неравным ему. Число, на тысячную долю большее нуля, уже не является нулем.

Ускоренное вычисление

При работе с логическими операторами можно столкнуться с феноменом, назы¬ваемым «ускоренным вычислением». Это значит, что выражение вычисляется только до тех пор, пока не станет очевидно, что оно принимает значение «исти¬на» или «ложь». В результате, некоторые части логического выражения могут быть проигнорированы в процессе сравнения. Следующий пример демонстри¬рует ускоренное вычисление:

//. operators/ShortCircuit.java // Демонстрация ускоренного вычисления // при использовании логических операторов, import static net mindview util Print *;

public class ShortCircuit {

static boolean testl(int val) {

print ("testlC + val + ")"); print("результат- " + (val < 1)); return val <1,

}

static boolean test2(int val) {

print("test2(" + val + ")"); print("результат- " + (val < 2)); return val <2,

}

static boolean test3(int val) {

pnnt("test3(" + val + ")"); print("результат: " + (val < 3)). return val <3;

}

public static void main(String[] args) {

boolean b = testl(O) && test2(2) && test3(2); print ("выражение: " + b);

}

} /* Output: testl(O) результат: true test2(2)

результат: false выражение: false *///:-

Каждый из методов test() проводит сравнение своего аргумента и возвраща¬ет либо true, либо false. Также они выводят информацию о факте своего вызова. Эти методы используются в выражении

testl(O) && test2(2) && test3(2)

Естественно было бы ожидать, что все три метода должны выполняться, но результат программы показывает другое. Первый метод возвращает резуль¬тат true, поэтому вычисление выражения продолжается. Однако второй метод выдает результат false. Так как это автоматически означает, что все выражение будет равно false, зачем продолжать вычисления? Только лишняя трата вре¬мени. Именно это и стало причиной введения в язык ускоренного вычисления; отказ от лишних вычислений обеспечивает потенциальный выигрыш в произ¬водительности.

Литералы

Обычно, когда вы записываете в программе какое-либо значение, компилятор точно знает, к какому типу оно относится. Однако в некоторых ситуациях одно¬значно определить тип не удается. В таких случаях следует помочь компилятору определить точный тип, добавив дополнительную информацию в виде опреде¬ленных символьных обозначений, связанных с типами данных. Эти обозначе¬ния используются в следующей программе:

//: operators/Literals.java

import static net.mindview.util.Print.*:

public class Literals {

public static void main(String[] args) {

int il = 0x2f; // Шестнадцатеричное (нижний регистр)

printC'ii: " + Integer.toBinaryString(il));

int i2 = 0X2F; // Шестнадцатеричное (верхний регистр)

print("i2: " + Integer.toBinaryString(i2));

int i3 = 0177: // Восьмеричное (начинается с нуля)

print("i3: " + Integer.toBinaryString(i3)):

char с = Oxffff; // макс, шестнадцатеричное знач. char

printC'c: " + Integer.toBinaryString(c));

byte b = 0x7f. // макс шестнадцатеричное знач. byte

printC'b " + Integer toBinaryString(b));

short s = 0x7fff. // макс шестнадцатеричное знач. short

printC's " + Integer.toBinaryString(s));

long nl = 200L; // Суффикс, обозначающий long

long n2 = 2001, // Суффикс, обозначающий long (можно запутаться)

long n3 = 200,

float fl = 1,

float f2 = IF; // Суффикс, обозначающий float float f3 = If, // Суффикс, обозначающий float double dl = Id, // Суффикс, обозначающий double double d2 = ID; // Суффикс, обозначающий double

}

} /* Output- il 101111 12 101111 13: 1111111 c: 1111111111111111 b: 1111111 s- 111111111111111 *///:-

Последний символ обозначает тип записанного литерала. Прописная или строчная буква L определяет тип long (впрочем, строчная I может создать про¬блемы, потому что она похожа на цифру 1); прописная или строчная F соответ¬ствует типу float, а заглавная или строчная D подразумевает тип double.

Шестнадцатеричное представление (основание 16) работает со всеми встро¬енными типами данных и обозначается префиксом Ох или ОХ с последующим числовым значением из цифр 0-9 и букв a-f, прописных или строчных. Если при определении переменной задается значение, превосходящее максимально для нее возможное (независимо от числовой формы), компилятор сообщит вам об ошибке. В программе указаны максимальные значения для типов char, byte и short. При выходе за эти границы компилятор автоматически сделает значе¬ние типом int и сообщит вам, что для присвоения понадобится сужающее при¬ведение.

Восьмеричное представление (по основанию 8) обозначается начальным ну¬лем в записи числа, состоящего из цифр от 0 до 7. Для литеральной записи чи¬сел в двоичном представлении в Java, С и С++ поддержки нет. Впрочем, при ра¬боте с шестнадцатеричныыми и восьмеричными числами часто требуется по¬лучить двоичное представление результата. Задача легко решается методами static toBinaryString() классов Integer и Long.

Экспоненциальная запись

Экспоненциальные значения записываются, по-моему, очень неудачно: 1.39e-47f. В науке и инженерном деле символом е обозначается основание натурального логарифма, равное примерно 2,718. (Более точное значение этой величины можно получить из свойства Math.E.) Оно используется в экспоненциальных выражениях, таких как 1,39хе-47, что фактически значит 1,39х2,718-47. Одна¬ко во время изобретения языка FORTRAN было решено, что е будет обозначать «десять в степени», что достаточно странно, поскольку FORTRAN разрабатывался для науки и техники и можно было предположить, что его создатели обратят внимание на подобную неоднозначность1. Так или иначе, этот обычай был пе¬ренят в С, С++, а затем перешел в Java. Таким образом, если вы привыкли ви¬деть в е основание натурального логарифма, вам придется каждый раз делать преобразование в уме: если вы увидели в Java выражение 1.39e-43f, на самом деле оно значит 1,39х10~43.

Report Page