55

为了找到闰年,为什么年份必须不能被 100 整除且能被 400 整除?

我明白为什么它必须能被 4 整除。请解释一下算法。

4

27 回答 27

106

一年的长度是(或多或少)365.242196 天。因此,我们必须或多或少地减去四分之一天以使其适合:

365.242196 - 0.25 = 364.992196 (在 4 年内增加 1 天):但是哎呀,现在它太小了!!让我们加百分之一(一百年不加一天:-))

364.992196 + 0,01 = 365.002196(哎呀,有点太大了,无论如何让我们在大约 400 年内添加一次)

365.002196 - 1/400 = 364.999696

现在差不多了,只是偶尔玩一下闰秒,你就准备好了。

(注意:在此步骤之后不再应用更正的原因是因为一年也会改变长度!!,这就是为什么闰秒是最灵活的解决方案,请参见此处的示例)

这就是为什么我猜

于 2009-04-07T11:16:45.983 回答
88

维基百科上有一个算法来确定闰年:

function isLeapYear (year):
    if ((year modulo 4 is 0) and (year modulo 100 is not 0))
    or (year modulo 400 is 0)
        then true
    else false

在关于闰年的维基百科页面上有很多关于这个主题的信息,包括关于不同日历的信息。

于 2009-04-07T11:01:52.777 回答
15

一般来说,计算闰年的算法如下......

如果一年能被 4 整除但不能被 100 整除,则一年将是闰年。如果一年能被 4 和 100 整除,则除非它也能被 400 整除,否则它不是闰年。

因此,1996、1992、1988 等年份是闰年,因为它们可以被 4 整除,但不能被 100 整除。对于世纪年,400 规则很重要。因此,世纪年 1900、1800 和 1700 虽然仍然可以被 4 整除,但也可以被 100 整除。由于它们不能被 400 整除,因此它们不是闰年

于 2009-04-07T11:01:46.503 回答
11

这足以检查一年是否是闰年。

if( (year%400==0 || year%100!=0) &&(year%4==0))
    cout<<"It is a leap year";
else
    cout<<"It is not a leap year";
于 2014-08-30T09:39:39.163 回答
8

a) 一年是 365.242199 天。

b) 如果每年是 365 天,那么 100 年我们将失去 24.2199 天。这就是为什么我们每世纪增加 24 天(每 4 年,除以 100 时除外)

c) 但是我们仍然损失了 0.21299 天/世纪。因此,在 4 个世纪中,我们损失了 0.8796 天。这就是为什么我们每 4 个世纪增加 1 天(每 4 个世纪我们计算一个闰年)。

d) 但这意味着我们每四百年(4 个世纪)损失 -0.1204 天(我们前进)。因此,在 8 个四百周年(3200 年)中,我们不计算闰年。

e) 但这意味着我们每 3200 年损失 0.0368 天。因此,在 24x3200 年(=76800 年)中,我们损失了 0.8832 天。这就是为什么我们要计算闰年。

等等...(到那时我们将摧毁地球,所以没关系)

但我无法理解的是,为什么我们不计算每 500 年而不是 400 年的闰年。这样我们会更快地收敛到正确的时间(我们会损失 2.3 小时/500 年)。

于 2015-08-09T17:46:26.833 回答
6

我相信维基百科可以比我更好地解释它,但这基本上与这样一个事实有关,即如果你每四年增加一天,我们就会领先于太阳,因为它绕太阳运行的时间少于365.25 天,因此我们通过在不能被 400 整除的年份(例如 1900 年)上不添加闰日来弥补这一点。

希望有帮助

于 2009-04-07T11:04:30.320 回答
6

这是使用 javascript 三元运算符的wikipedia algorithm的简单实现:

isLeapYear = (year % 100 === 0) ? (year % 400 === 0) : (year % 4 === 0);
于 2016-10-18T17:45:33.393 回答
4

如果输入年份是闰年,则返回 true

基本现代代码:

  If year mod 4 = 0, then leap year
  if year mod 100 then normal year
  if year mod 400 then leap year
  else normal year

今天的规则开始于公元 1582 年的儒略历规则,每 4 年开始于公元前 46 年,但在公元 10 年之前并不一致,正如塞萨尔所宣布的那样。然而,他们确实在前几年每隔三年添加一些闰年:因此闰年是公元前 45 年、公元前 42 年、公元前 39 年、公元前 36 年、公元前 33 年、公元前 30 年、公元前 27 年、公元前 24 年、公元前 21 年、公元前 18 年BC, 15 BC, 12 BC, 9 BC, 8 AD, 12 AD 45BC 之前没有添加闰年。

0 年不存在,因为它是 ...2BC 1BC 1AD 2AD... 对于某些计算,这可能是一个问题。

function isLeapYear(year: Integer): Boolean;
begin
  result := false;
  if year > 1582 then // Todays calendar rule was started in year 1582 
    result := ((year mod 4 = 0) and (not(year mod 100 = 0))) or (year mod 400 = 0)
  else if year > 10 then // Between year 10 and year 1582 every 4th year was a leap year 
    result := year mod 4 = 0
  else //Between year -45 and year 10 only certain years was leap year, every 3rd year but the entire time
    case year of
      -45, -42, -39, -36, -33, -30, -27, -24, -21, -18, -15, -12, -9:
        result := true;
    end;
end;
于 2014-03-12T12:52:45.850 回答
2

你真的应该先尝试谷歌。

维基百科对闰年有解释。您描述的算法适用于Proleptic Gregorian calendar

更多关于它的数学可以在文章日历算法PDF)中找到。

于 2009-04-07T11:05:30.583 回答
1

如果我们更进一步,会不会好很多。假设每 3200 年为无闰年,一年的长度将到来

364.999696 + 1/3200 = 364.999696 + .0003125 = 365.0000085

在此之后,大约 120000 年后需要进行调整。

于 2011-12-28T14:55:43.263 回答
1

Java下面的代码中计算两个给定年份之间的闰年计数。确定循环的起点和终点。

然后如果参数模 4 等于 0 且参数模 100 不等于 0 或参数模 400 等于 0 则为闰年并增加计数器。

static int calculateLeapYearCount(int year, int startingYear) {
        int min = Math.min(year, startingYear);
        int max = Math.max(year, startingYear);
        int counter = 0;
        for (int i = min; i < max; i++) {
            if ((i % 4 == 0 && i % 100 != 0) || i % 400 == 0) {
                counter = counter + 1;
            }
        }
        return counter;
    }
于 2017-01-07T19:20:18.860 回答
1

PHP:

// is number of days in the year 366?  (php days of year is 0 based)
return ((int)date('z', strtotime('Dec 31')) === 365);
于 2017-03-04T19:20:15.330 回答
0

这里出现了一个相当晦涩的想法。当每年用100整除得到365天时,这个时候该怎么办?在遥远的未来,当连年可以用400整除时,只能得到365天。

那么就有可能或有理由对可被 80 整除的年份进行更正。正常年份将有 365 天,而那些可被 400 整除的年份可以得到 366 天。或者这是一个松散的情况。

于 2013-04-22T12:00:58.310 回答
0

闰年是任意的,用来描述闰年的系统是人造的。没有为什么。

我的意思是,每 28 年可能会有一个闰年,在那些闰年我们会有额外的一周……但是决定每 4 年让它成为一天以迎头赶上的权力。

这也与地球需要 365.25 天才能绕太阳转等有关。当然,它并不是真正的 365.25,它是否略少(365.242222...),所以为了纠正这种差异,他们决定放弃飞跃能被 100 整除的年份。

于 2009-04-07T11:07:36.023 回答
0

如果您对这些规则的原因感兴趣,那是因为地球绕太阳运行一圈所需的时间是一个很长的不精确的十进制值。它不完全是 365.25。它略小于 365.25,因此每 100 年必须消除一个闰日(365.25 - 0.01 = 365.24)。但这也不完全正确。该值略大于 365.24。因此,4 次中只有 3 次适用 100 年规则(或者换句话说,每 400 年加回 1 天;365.25 - 0.01 + 0.0025 = 365.2425)。

于 2009-04-07T11:13:06.010 回答
0

目前平均一年大约有 365.2425 天(地球正在减速,但我们暂时忽略它)。

我们每 4 年有闰年的原因是因为这使我们平均达到 365.25 [(365+365+365+366) / 4 = 365.25, 1461 days in 4 years]

我们在 100 倍数上没有闰年的原因是为了让我们达到 365.24 `[(1461 x 25 - 1) / 100 = 365.24,100 年有 36,524 天。

那么我们再次在 400 倍数上有闰年的原因是为了让我们达到 365.2425 [(36,524 x 4 + 1) / 400 = 365.2425, 146,097 days in 400 years]

我相信在 3600 倍数上可能还有另一条规则,但我从来没有为它编码(千年虫是一回事,但在我看来,没有必要计划未来一千年半 - 请记住,我一直之前错了)。

所以,规则是,在降低优先级:

  • 400的倍数是闰年。
  • 100的倍数不是闰年。
  • 4的倍数是闰年。
  • 其他任何事情都不是闰年。
于 2009-04-07T11:21:11.620 回答
0

你可以只检查年份数字是否能被 4 和 400 整除。你真的不需要检查它是否不能被 100 整除。400 出现问题的原因是因为根据公历,我们的“日长”略关闭,因此为了弥补这一点,我们有 303 个常规年(每个 365 天)和 97 个闰年(每个 366 天)。额外的 3 年不是闰年的区别在于与公历保持循环,公历每 400 年重复一次。查找 Christian Zeller 的同余方程。这将有助于理解真正的原因。希望这可以帮助 :)

于 2014-05-01T00:33:25.577 回答
0

在公历中,必须考虑 3 个标准来识别闰年:

  1. 年份可以被 4 整除;
  2. 如果年份可以被 100 整除,则它不是闰年,除非;
  3. 年份也能被 400 整除。那么就是闰年。为什么年份除以 100 不是闰年
于 2014-11-26T09:39:36.260 回答
0

C# 实现

public bool LeapYear()
{
     int year = 2016;

     return year % 4 == 0 && year % 100 != 0 || year % 400 == 0 ;
}
于 2019-05-26T10:39:36.193 回答
0

在 shell 中,您可以使用cal -j YYYYwhich 打印一年中的儒略日,如果最后一个儒略日是 366,那么它是闰年。

$ function check_leap_year
 {
  year=$1
   if [ `cal -j $year | awk 'NF>0' | awk 'END { print $NF } '` -eq 366 ];
   then
      echo "$year -> Leap Year";
   else
      echo "$year -> Normal Year" ;
   fi
 }
$ check_leap_year 1900
1900 -> Normal Year
$ check_leap_year 2000
2000 -> Leap Year
$ check_leap_year 2001
2001 -> Normal Year
$ check_leap_year 2020
2020 -> Leap Year
$

使用awk,你可以做到

$ awk -v year=1900 ' BEGIN { jul=strftime("%j",mktime(year " 12 31 0 0 0 ")); print jul } '
365
$ awk -v year=2000 ' BEGIN { jul=strftime("%j",mktime(year " 12 31 0 0 0 ")); print jul } '
366
$ awk -v year=2001 ' BEGIN { jul=strftime("%j",mktime(year " 12 31 0 0 0 ")); print jul } '
365
$ awk -v year=2020 ' BEGIN { jul=strftime("%j",mktime(year " 12 31 0 0 0 ")); print jul } '
366
$
于 2020-05-16T09:30:50.453 回答
0

我在“Python 3 图解指南”一书中发现了这个问题。在很早的一章中,只讨论了数学运算,没有循环,没有比较,没有条件。如何判断某一年是否为闰年?

以下是我想出的:

y = y % 400
a = y % 4
b = y % 100
c = y // 100
ly = (0**a) * ((1-(0**b)) + 0**c)   # ly is not zero for leap years, else 0
于 2018-12-26T08:16:32.400 回答
0

从 1700 年到 1917 年,官方日历是儒略历。从那以后他们我们使用公历系统。从儒略历到公历的过渡发生在 1918 年,当时 1 月 31 日之后的第二天是 2 月 14 日。这意味着 1918 年的第 32 天,是 2 月 14 日。

在这两个日历系统中,二月是唯一一个天数可变的月份,闰年有 29 天,其他年份有 28 天。在儒略历中,闰年可以被 4 整除,而在格里高利历中,闰年是以下之一:

能被 400 整除。

能被 4 整除,不能被 100 整除。

所以闰年的程序是:

Python:

def leap_notleap(year):

    yr = ''
    if year <= 1917:
        if year % 4 == 0:
            yr = 'leap'
        else:
            yr = 'not leap'
    elif year >= 1919:
        if (year % 400 == 0) or (year % 4 == 0 and year % 100 != 0):
            yr = 'leap'
        else:
            yr = 'not leap'
    else:
        yr = 'none actually, since feb had only 14 days'

    return yr
于 2019-11-29T04:29:28.767 回答
0

很简单,因为 2000 年是闰年,它可以被 100 整除并且可以被 4 整除。所以为了保证它是正确的闰年,我们需要确保它可以被 400 整除。2000 % 4 = 0 2000 % 100 = 0 根据算法它是不是飞跃,但它可以被 400 2000 % 400 = 0 整除,所以它是飞跃。

于 2018-10-19T08:24:57.050 回答
0

如果年份是闰年,BIS 将为 1,否则在此布尔逻辑中为 0:

BIS = A MOD 4=0 - (A MOD 100=0 AND A>1600) + (A MOD 400=0 AND A>1600)
于 2021-06-13T00:40:05.947 回答
0

蟒蛇 3.5

def is_leap_baby(year):
    if ((year % 4 is 0) and (year % 100 is not 0)) or (year % 400 is 0):
        return "{0}, {1} is a leap year".format(True, year)
    return "{0} is not a leap year".format(year)

print(is_leap_baby(2014))
print(is_leap_baby(2012))
于 2016-12-25T17:19:31.230 回答
0

我认为这是最有效的方法。

Python:

def leap(n):
    if n % 100 == 0:
        n = n / 100
    return n % 4 == 0
于 2019-03-06T01:19:20.033 回答
-2

刚刚用 Coffee-Script 写了这个:

is_leap_year = ( year ) ->
  assert isa_integer year
  return true   if year % 400 == 0
  return false  if year % 100 == 0
  return true   if year %   4 == 0
  return false

# parseInt? that's not even a word. 
# Let's rewrite that using real language:
integer = parseInt 

isa_number = ( x ) ->
  return Object.prototype.toString.call( x ) == '[object Number]' and not isNaN( x )

isa_integer = ( x ) ->
  return ( isa_number x ) and ( x == integer( x ) )

当然,这里所做的有效性检查比所要求的要远一些,但我发现在良好的编程中这是必要的事情。

请注意,此函数的返回值表示所谓的公历中的闰年,因此对于 1400 年,它表示false,而事实上,根据当时使用的儒略历,那一年闰年。我仍然会将它留在我正在编写的日期时间库中,因为编写正确的代码来快速处理日期会令人惊讶地涉及,所以我只会支持公历(或为另一个公历付费)。

于 2011-08-21T21:05:44.343 回答