Проверка високосного года - без использования операции деления

Как проверить, является ли данный год високосным, без использования операции деления или какого-либо библиотечного метода в Java. Можно ли это проверить с помощью побитового оператора?

PS: валидация не нужна веками


person Apurv Chatterjee    schedule 04.09.2018    source источник
comment
Можно ли считать оператор по модулю (%) опцией? И просто из любопытства, почему разделение не вариант?   -  person n247s    schedule 04.09.2018
comment
@ n247s Вероятно, домашнее задание для ученика. В противном случае простым решением было бы: java.time.Year.isLeap( 2018 )   -  person Basil Bourque    schedule 04.09.2018
comment
Можно просто поставить вопрос надо ли проверять веками?   -  person billjamesdev    schedule 06.09.2018
comment
return ((year & 3) == 0; Чтобы проверить столетние годы, вам нужно по модулю (это операция деления): return ((year & 3) == 0 && ((year % 25) != 0 || (year & 15) == 0)); Подробнее: stackoverflow.com/a/11595914/733805< /а>   -  person Kevin P. Rice    schedule 10.12.2018


Ответы (5)


Вот несколько способов определения високосных лет без использования функции по модулю.

Во-первых, давайте предположим (или проверим), что год находится в диапазоне 1901 - 2099.

  • Високосный год, выраженный в виде двоичного числа, будет иметь 00 в качестве последних двух цифр. Так:

    это високосный год if year & (not 4) == 0

  • Если у вас есть функция для усечения действительного числа до целого числа, то это работает:

    x = trunc(year / 4)

    это високосный год if x * 4 == year

  • Если у вас есть операторы сдвига (не циклического сдвига), которые, я уверен, есть у Verilog, тогда:

    x = year >> 2

    это високосный год if (x << 2) == year

Если предположение о том, что диапазон равен 1901 - 2099, неверно, вам понадобится дополнительная логика, чтобы исключить 1900, 1800, 1700 and 2100, 2200, 2300 and so on.

person Krishna Choudhary    schedule 04.09.2018

Хорошо обязательно. Поскольку деление или мод на степени двойки (в данном случае 4) — это всего лишь битовая проверка.

boolean isLeapYear( int year ) {
    return (( year & 3 ) == 0 );  // if the bottom two bits are 0, then the int is divisible by 4
}

Обратите внимание, что это не идеально, так как некоторые века не являются високосными, но кажется, что это не имеет отношения к вашему вопросу (как вы сейчас заявляете).

person billjamesdev    schedule 04.09.2018

  • Если год является столетним годом, то есть делится на 100, то он должен делиться на 400, чтобы называться високосным годом.

  • Если год не столетний, то он должен делиться на 4, чтобы его можно было назвать високосным.

В приведенном ниже коде используется бинарный поиск, чтобы проверить, делится ли число на другое число или нет (поскольку / не разрешено, я не уверен, что вы можете использовать %).

    public static boolean isLeapYear(int year){
        return isDivisible(1,year,100,year) ? isDivisible(1,year,400,year) : isDivisible(1,year,4,year);
    }

    private static boolean isDivisible(int low,int high,int divisor,int dividend){
        int mid = 0;
        while(low <= high){
            mid = low + ((high - low) >> 1);
            int result = divisor * mid;
            if(result == dividend) return true;
            else if(result > dividend) high = mid - 1;
            else low = mid + 1;
        }

        return false;
    }
person nice_dev    schedule 04.09.2018

Да, вы можете сделать это без использования каких-либо арифметических операций. Используйте карту, которая сопоставляет год с логическим значением, независимо от того, является ли год високосным или нет.

person Teodor Dyakov    schedule 04.09.2018
comment
Итак, индивидуально добавлять значения на карту? - person nice_dev; 04.09.2018

Year.isLeap(someYear)

Вы должны быть более конкретными с вашими требованиями, это сайт для программистов :)

person Community    schedule 29.10.2018