2015-03-18 5 views
1

Что такое порядок выполнения и возможные результаты этого утверждения: leap = year%4 == 0;Внеочередные & Arity в странном заявлении

(левая часть присваивание и правильное утверждение?) Который является отрывком из следующего алгоритма, используемого для расчета дня недели любой даты в григорианском календаре:

static char daytab[2][13] = 
{ 
       {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 
       {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 
}; 
for (year = 1; year <= y; year++) 
{ 
     leap = year%4 == 0; 
     if (year%100 == 0 && year%400 != 0) 
       leap = 0; 
     for (month = 1; month <= m; month++) 
     { 
       d += daytab[leap][month - 1]; 
       daystotal = 365*(year - 1) + (int)floor((year-1)/4) 
       - (int)floor((year - 1)/100) + (int)floor((year - 1)/400) + d; 
     } 
} 
+0

Оценивается первый «год% 4», затем сравнивается с 0, присваивание сравнения сохраняется на «прыжок». – Maroun

ответ

2

year % 4 == 0 эквивалентно (year % 4) == 0, который берет остаток от деления на 4 года, а затем сравнивает это значение 0 и производит логическое result-- true или false. Вы не показываете декларацию/определение leap, поэтому мы можем только догадываться о ее типе. Если это bool, этот результат будет присвоен непосредственно ему. На основе последующего кода:

if (year%100 == 0 && year%400 != 0) 
    leap = 0; 

Оказывается, что leap, вероятно, какой-то другой арифметический тип (вероятно int). Это довольно часто, особенно в коде, который был первоначально написан на C90, который не имеет типа Boolean.

В этом случае bool будет преобразован перед назначением. Когда были преобразованы в арифметические типы, false преобразует в 0 и true преобразует в 1 (идущий в другом направлении, преобразует в 0false, а любое другое значение преобразуется в true).

Таким образом, код имеет в основном тот же эффект, что-то вроде:

if ((year % 4) == 0) 
    leap = 1; 
else 
    leap = 0; 

... или:

leap = ((year % 4) == 0) ? 1 : 0; 

Если бы я писал это, я думаю, что я бы, наверное, написать код больше, как это:

if ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)) 
    leap = 1; 
else 
    leap = 0; 

... или (более вероятно) просто:

leap = ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)); 

По крайней мере, для этого более прямо указано условие «какой високосный год» в григорианском календаре . Я предполагаю, что вы можете просмотреть исходный код как исторический артефакт через: он сначала вычисляет, является ли он високосным годом по правилам старого юлианского календаря, а затем отдельно добавляет правила, которые были добавлены в григорианский календарь. Однако, если кто-то действительно хотел отразить эту историю, они должны, вероятно, включить комментарий, объясняющий, что именно поэтому код написан как есть. Поскольку он стоит прямо сейчас, вместо того, чтобы просто вычислять правильное значение, он начинается с вычисления значения, которое может быть неправильным, затем проверяет наличие большего количества условий и после этого исправляет значение.


1. Что, конечно, что-то вроде: А год является високосным, если он делится на 4, либо не делится на 100, или же делится на 400.Так, например, 2000 год был високосным годом (делился на 4, а также делился на 400), но 1900 не был (делится на 4, а также делится на 100 и не делится на 400).

3

Смотри здесь operator precendence. year % 4 будет оцениваться, иначе результат будет сравниваться с 0, а затем результат будет присвоен переменной leap.

Смежные вопросы