1

该语句的执行顺序和可能的结果是什么:leap = year%4 == 0;

(左边是赋值,右边是断言?)摘自以下用于计算公历中任何日期的星期几的算法:

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;
        }
}
4

2 回答 2

3

看这里operator precendenceyear % 4将被评估,然后将结果与 0 进行比较,然后将结果分配给leap变量。

于 2015-03-18T13:44:00.340 回答
2

year % 4 == 0等价于(year % 4) == 0,取年除以 4 后的余数,然后将其与 0 进行比较并产生布尔结果——truefalse。您没有显示 的​​声明/定义leap,因此我们只能猜测它的类型。如果它是 a bool,则该结果将直接分配给它。基于后面的代码:

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

看起来这leap可能是其他一些算术类型(可能int)。这很常见,尤其是在最初用 C90 编写的代码中,它没有布尔类型。

在这种情况下,bool将在赋值之前进行转换。当被转换为算术类型时,false转换为0true转换为1(在另一个方向上,0转换为false,并且任何其他值都转换为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中“什么是闰年”的条件。我想您可以通过以下方式将原始代码视为历史文物:它首先根据旧儒略历的规则计算是否是闰年,然后分别添加在公历中添加的规则。但是,如果有人真的想反映这段历史,他们可能应该包含一条注释,解释这就是代码按原样编写的原因。就目前而言,它不仅仅是计算正确的值,而是首先计算一个可能不正确的值,然后检查更多条件,然后修补该值。


1. 当然,例如:如果一年能被 4 整除,或者不能被 100 整除,或者也能被 400 整除,那么它就是闰年。例如,2000 年是闰年(能被 400 整除) 4 也能被 400 整除)但 1900 不能(能被 4 整除,但也能被 100 整除且不能被 400 整除)。

于 2015-03-18T13:58:59.863 回答