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 нет переполнений, микропроцессор сначала вычитает, а затем добавляет один.