闰年计算

时间:2009-04-07 10:58:15

标签: algorithm calendar leap-year

为了找到闰年,为什么一年必须与100不可分割并被400整除? 我理解为什么它必须被4整除。请解释算法。

27 个答案:

答案 0 :(得分:100)

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

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

364.992196 + 0,01 = 365.002196 (哎呀,有点太大了,让我们在400年左右的时间里添加一天)

365.002196 - 1/400 = 364.999696

现在几乎就是这样,只是偶尔玩闰秒,然后你就定了。

(注意:在此步骤之后不再应用更正的原因是因为一年也改变了长度!!这就是为什么leapseconds是最灵活的解决方案,请参阅例如here

这就是为什么我猜

答案 1 :(得分:74)

wikipedia上有一个算法来确定闰年:

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

wikipedia page about leap years上有关于此主题的大量信息,包含有关不同日历的信息。

答案 2 :(得分:14)

一般而言,计算闰年的算法如下......

如果一年可以被4整除而不是100,那么一年将是闰年。如果一年可以被4和100整除,那么除非它也可以被400整除,否则它不是闰年。

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

答案 3 :(得分:9)

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

if( (year%400==0 || year%100!=0) &&(year%4==0))
    cout<<"It is a leap year";
else
    cout<<"It is not a leap year";

答案 4 :(得分:9)

a)年份为365.242199天。

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

c)但是我们仍然会损失0.21299天/世纪。所以在4个世纪里我们失去了0.8796天。 这就是为什么我们每4个世纪增加1天(每四个世纪我们算一个闰年)。

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

e)但这意味着我们每3200年就会损失0.0368天。所以在24x3200年(= 76800年),我们失去了0.8832天。这就是我们算闰年的原因。

等等......(到那时我们将摧毁这个星球,所以它并不重要)

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

答案 5 :(得分:6)

我确信Wikipedia可以比我更好地解释它,但这基本上与这样一个事实有关:如果你每四年增加一天,我们就会超越太阳作为它的时间太阳的轨道运行时间不到365.25天所以我们通过在不能被400整除的年份(例如1900年)上增加闰日来弥补这一点。

希望有所帮助

答案 6 :(得分:5)

以下是使用javascript三元运算符的mklement0 answer的简单实现:

isLeapYear = (year % 100 === 0) ? (year % 400 === 0) : (year % 4 === 0);

答案 7 :(得分: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年   朱利安历法规则每四年开始于46BC,但在Cesar宣布的公元10年之前并不一致。   然而,它们确实每三年增加一些闰年,而在此之前的几年:   因此,闰年是公元前45年,公元前42年,公元前39年,公元前36年,公元前33年,公元前30年,公元前27年,公元前24年,公元前21年,公元前18年,公元前15年,公元前12年,公元前9年,公元8年,公元12年   在45BC年之前没有添加闰年。   http://www.wwu.edu/depts/skywise/leapyear.html

第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;

答案 8 :(得分:2)

你真的应该先尝试谷歌。

维基百科有一个explanation of leap years。您描述的algorithm适用于Proleptic Gregorian calendar

有关它周围数学的更多信息,请参阅文章Calendar Algorithms

答案 9 :(得分:1)

如果我们更进一步,那会不会好得多。 假设每3200年没有闰年, 一年的长度将来临

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

之后,大约需要120000年才能进行调整。

答案 10 :(得分:1)

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

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

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

答案 11 :(得分: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);

答案 12 :(得分:0)

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

BIS = A MOD 4=0 - (A MOD 100=0 AND A>1600) + (A MOD 400=0 AND A>1600)

答案 13 :(得分:0)

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

答案 14 :(得分:0)

在shell中,您可以使用cal -j YYYY打印一年中的儒略日。如果最后的儒略日是366,则它是a年。

$ 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
$

答案 15 :(得分:0)

从1700年到1917年,官方日历为儒略历。从那时起,我们就使用公历系统。从儒略历到公历的转换发生在1918年,即1月31日之后的第二天是2月14日。这意味着1918年的第32天是2月14日。

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

可除以400。

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

因此leap年的程序将是:

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

答案 16 :(得分:0)

C#实现

public bool LeapYear()
{
     int year = 2016;

     return year % 4 == 0 && year % 100 != 0 || year % 400 == 0 ? true : false;
}

答案 17 :(得分:0)

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

Python:

def leap(n):
    if n % 100 == 0:
        n = n / 100
    return n % 4 == 0

答案 18 :(得分:0)

我在《 Python 3图解指南》一书中发现了这个问题。在很早的一章中,它仅讨论了数学运算,没有循环,没有比较,没有条件。如何判断给定年份是否为a年?

下面是我的想法:

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

答案 19 :(得分:0)

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

答案 20 :(得分:0)

Python 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))

答案 21 :(得分:0)

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

  1. 年份可以被4整除;
  2. 如果年份可以平均除以100,则不是闰年,除非;
  3. 这一年也可以被400整除。然后是闰年。 Why the year divided by 100 is not leap year

答案 22 :(得分:0)

你可以检查一下年份数是否可以被4和400整除。你真的不需要检查它是否不可分为100.原因400有问题是因为根据公历,我们的“日长“略微偏离,因此为了弥补这一点,我们有303个常规年份(每个365天)和97个闰年(每个366天)。不是闰年的3个额外年份的差异是与公历保持一致,公历每400年重复一次。查看Christian Zeller的同余方程式。这将有助于了解真正的原因。希望这会有所帮助:)

答案 23 :(得分:0)

这是一个相当模糊的想法。 当每年可分为100天获得365天时,此时应该做什么?在遥远的未来,即使只有400年的可分割年限也可以获得365天。

然后有可能或有理由在80岁时进行更正。 正常年份将有365天,而那些可以分为400天可以获得366天。或者这是一个松散的情况。

答案 24 :(得分:0)

目前平均每年大约365.2425天(地球正在放缓,但现在让我们忽略它)。

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

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

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

我相信在3600倍数可能会有另一条规则,但我从来没有为它编码(Y2K是一回事,但在我看来计划未来一千五百年 - 请记住我以前错了。

因此,规则优先级越来越低:

  • 400的倍数是闰年。
  • 100的倍数不是闰年。
  • 4的倍数是闰年。
  • 其他任何事情都不是闰年。

答案 25 :(得分:0)

闰年是任意的,用于描述它们的系统是人造构造。没有原因。

我的意思是,每28年可能会有一个闰年,我们在这些闰年中会有一个额外的一周......但是决定每4年就有一天能够赶上它。 / p>

它也与地球有一个令人讨厌的365.25天绕太阳等。当然它不是真的365.25它稍微少一点( 365.242222 ...... ),所以为了纠正这种差异,他们决定放弃可以被100整除的闰年。

答案 26 :(得分:-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,而事实上那年 a根据当时使用的朱利安历法,闰年。我仍然会在我正在编写的日期时间库中保留它,因为编写正确的代码来快速处理日期会令人惊讶地参与其中,因此我只会支持格里高利历(或者获得另一个日历)。