Char_x <(char_y + 1) == char_x <= char_y?
Привет всем Я просматривал некоторые исходные коды Java, когда я натолкнулся на это (java.lang.Character
):
public static boolean isHighSurrogate(char ch) {
return ch >= MIN_HIGH_SURROGATE && ch < (MAX_HIGH_SURROGATE + 1);
}
public static boolean isLowSurrogate(char ch) {
return ch >= MIN_LOW_SURROGATE && ch < (MAX_LOW_SURROGATE + 1);
}
Мне было интересно, почему автор добавил 1 к верхнему пределу и сделал меньше, чем сравнение, вместо того, чтобы просто сравнивать меньшее или равное?
Я могу понять, помогает ли читаемость, но в этом случае это не так.
Мне было интересно, какая разница между приведенным выше кодом:
public static boolean isHighSurrogate(char ch) {
return ch >= MIN_HIGH_SURROGATE && ch <= MAX_HIGH_SURROGATE;
}
public static boolean isLowSurrogate(char ch) {
return ch >= MIN_LOW_SURROGATE && ch <= MAX_LOW_SURROGATE;
}
Ответы
Ответ 1
Возможно, автор пытается быть совместимым с советом Дейкстры, чтобы сделать все диапазоны полуоткрытыми - начальная точка включена, а конечная точка является эксклюзивным.
Здесь нет семантической разницы, но тонкая разница в байткоде: (ch + 1)
- это int
, поэтому первый фрагмент кода выполняет сравнение char
to char
, за которым следует int
to int
а второй выполняет два сравнения char
- char
. Это не приводит к семантической разнице - неявные отбрасывания относятся к более широким типам, поэтому нет риска переполнения в фрагменте кода.
Оптимизация добавления и преобразования сравнения int
в int
обратно в сравнение 2 байта без знака int
хорошо входит в сферу видов оптимизации, выполняемых JIT, поэтому я не вижу никаких конкретных чтобы предпочесть один за другим.
Я предпочитаю писать такие вещи, как
MIN_LOW_SURROGATE <= ch && ch <= MAX_LOW_SURROGATE
Таким образом, ch
в середине делает очевидным для читателя, что ch
тестируется в пределах диапазона внешних значений.
Ответ 2
Дикая догадка
Суррогатный символ, любой из ряда кодов Unicode, которые являются используется в парах в UTF-16 для представления символов за пределами Basic Многоязычный самолет.
В моей точке зрения он хотел проигнорировать 8-битный материал, что означает, что max был 0xFF. 0xFF + 1 переполнится и вернется к 0x00. Выполнение сравнения всегда неверно.
Итак, если код был скомпилирован с символами из 8 бит. Он всегда будет возвращать false (вне диапазона UTF-16), а если он компилирует char в > 8 бит, то 0xFF + 1 будет 0x100 и все еще работать.
Надеюсь, это сделает для вас некоторое преимущество.
Ответ 3
Я бы сказал, что нет никакой разницы между двумя способами его кодирования, а просто вопросом вкуса, что вы бы предпочли, поскольку у вас нет никаких преимуществ одной из двух разных реализаций.
Мне было интересно, почему автор добавил 1 к верхнему пределу и сделал меньше, чем сравнение, вместо того, чтобы просто сравнивать меньшее или равное?
Я имею в виду, почему вы предпочли бы второй выбор? Я что-то пропустил здесь?
Ответ 4
Потому что автор был С++ или ассемблером.
Быстрее сделать a >= than > и быстрее выполнить <= than <. Фактически, когда вы пишете < b компилятор делает <= b + 1, поэтому он делает добавление и сравнение, потому что единственная доступная инструкция сборки делает < =. Если вы напишете эту сумму в коде вручную, компилятор С++ изменит MIN_HIGH_SURROGATE + 1 с фактическим значением результата во время компиляции. Таким образом, вы получаете инструкцию и цикл.
Но все это странное рассуждение применяется только для скомпилированного кода, например С++ или C. Или ASM.
ИЗМЕНИТЬ
Хотя для каждого из операторов равенства есть инструкции (я был неправ), все они сводятся к вычитаниям и (если необходимо) дополнениям в микрокоде. Затем процессор проверяет бит знака результата. Таким образом, приведенная выше формулировка кода будет еще быстрее.
Чтобы убедиться, что при добавлении 1 нет переполнений, микропроцессор сначала вычитает, а затем добавляет один.