Вы говорите о безразличном сравнении без учета регистра или полном нормализованном сравнении Unicode?
При тупом сравнении не будут найдены строки, которые могут быть одинаковыми, но не бинарными.
Пример:
U212B (ANGSTROM SIGN)
U0041 (LATIN CAPITAL LETTER A) + U030A (COMBINING RING ABOVE)
U00C5 (LATIN CAPITAL LETTER A WITH RING ABOVE).
Все они эквивалентны, но также имеют разные двоичные представления.
Тем не менее, Unicode Normalisation следует обязательно прочитать, особенно если вы планируете поддерживать хангыль, тайский и другие азиатские языки.
Кроме того, IBM в значительной степени запатентовала наиболее оптимизированные алгоритмы Unicode и сделала их общедоступными. Они также поддерживают реализацию: IBM ICU
Мне они кажутся одинаковыми, но обратите внимание, что эта строка в вашем коде имеет некоторую избыточность:
else if ((year % 4 == 0) && (year % 100 == 0) && (year % 400 == 0))
может быть заменена на:
else if (year % 400 == 0)
Если число кратно 400, то оно автоматически также кратно 100 и 4.
редактировать: (7 лет спустя!)
Обратите внимание, что вышеупомянутое предполагает наличие предшествующего if ((year% 4 == 0) && year% 100! = 0)
из исходного вопроса!
ответ cletus должен быть принятым: https://stackoverflow.com/a/1021373/8331
(я бы удалить свой ответ, но я не могу, поскольку он принят)
Иметь повторение в программном обеспечении почти всегда неправильно. В любой инженерной дисциплине форма должна следовать за функцией, и у вас есть три ветви для чего-то, что имеет два возможных пути - это либо високосный год, либо нет.
Механизм, который имеет тест в одной строке, не имеет этой проблемы, но в целом было бы лучше разделить тест на функцию, которая принимает int, представляющий год, и возвращает логическое значение, указывающее, является ли год високосным. Таким образом, вы можете делать с ним что-то, кроме вывода на стандартный вывод на консоли, и вам будет проще его протестировать.
В коде, который, как известно, превышает бюджет производительности, тесты обычно организуют так, чтобы они не выполнялись. избыточным и выполнять тесты в порядке, который возвращается раньше.
Я предлагаю вам поместить этот код в метод и создать модульный тест.
public static boolean isLeapYear(int year) {
assert year >= 1583; // not valid before this date.
return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
}
В модульном тесте
assertTrue(isLeapYear(2000));
assertTrue(isLeapYear(1904));
assertFalse(isLeapYear(1900));
assertFalse(isLeapYear(1901));
Правильная реализация:
public static boolean isLeapYear(int year) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, year);
return cal.getActualMaximum(Calendar.DAY_OF_YEAR) > 365;
}
Но если вы собираетесь изобретать это колесо, то:
public static boolean isLeapYear(int year) {
if (year % 4 != 0) {
return false;
} else if (year % 400 == 0) {
return true;
} else if (year % 100 == 0) {
return false;
} else {
return true;
}
}
Псевдокод из Википедии, переведенный на самый компактный язык Java
(year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0))