如何计算 [a, b] 范围内的闰年而不在 C# 上循环
How to count leap years in range [a, b] without loops on C#
假设,您有年份 a 和年份 b,它们是 年份范围 (它们包括在内),如何在不使用 loops 的情况下正确计算此 range 中的 leap years? (公历)
我是用 C# 写的,但我不认为我的代码很棒。我还使用了一个全局变量,但是大声笑,我认为有一个比这更好更优雅的解决方案。我只是一个新手,很抱歉我问了这个愚蠢的问题。
另外,我认为你不应该在这里使用 DateTime 等
这是我的代码:
class Program
{
public static int leap_years = 0;
static void Main()
{
do
{
int a, b;
leap_years = 0;
do Console.Write("Enter a: ");
while (!int.TryParse(Console.ReadLine(), out a) || a < 0);
do Console.Write("Enter b: ");
while (!int.TryParse(Console.ReadLine(), out b) || b < 0 || a == b || a >= b);
Console.WriteLine("Leap years: " + countLeapYears(a, b));
} while (Console.ReadKey().Key != ConsoleKey.Escape);
}
其中countLeapYears
是
static public int countLeapYears(int a, int b)
{
if (a > b)
return leap_years;
else
{
if (a % 4 == 0)
{
if (a % 100 == 0)
{
if (a % 400 == 0)
{
Console.WriteLine("Year {0} - leap year", a);
leap_years++;
a += 4;
countLeapYears(a, b);
}
else
{
Console.WriteLine("Year {0} - not a leap year", a);
a++;
countLeapYears(a, b);
}
}
else
{
Console.WriteLine("Year {0} - leap year", a);
leap_years++;
a += 4;
countLeapYears(a, b);
}
}
else
{
Console.WriteLine("Year {0} - not a leap year", a);
a++;
countLeapYears(a, b);
}
}
return leap_years;
}
}
public int LeapYear(int initialYear, int endYear, int ref countYear)
{
if (initialYear > endYear)
{
return countYear;
}
if(DateTime.IsLeapYear(initialYear)
{
countYear++;
}
initialYear++;
LeapYear(initialYear, endYear, countYear)
}
嗯,我们没有年份 0
:1BC
后面是 1AD
,这 破坏了乐趣 。但是,如果我们只能使用 AD
(正数年),您可以尝试这样的操作:
private static int countLeapYears(int from, int to) =>
(to / 4 - (from - 1) / 4) -
(to / 100 - (from - 1) / 100) +
(to / 400 - (from - 1) / 400);
让我们测试一下朴素计算:
private static int naiveCount(int from, int to) {
int result = 0;
for (int i = from; i <= to; ++i)
if (i % 400 == 0 || i % 4 == 0 && i % 100 != 0)
result += 1;
return result;
}
...
Random gen = new Random(123);
var result = Enumerable
.Range(1, 20)
.Select(i => {
int to = gen.Next(1590, 2222);
int from = gen.Next(1590, 2222);
return (from: Math.Min(from, to), to: Math.Max(from, to));
})
.Select(test => $"{test.from} - {test.to} actual: {countLeapYears(test.from, test.to),3} expected: {naiveCount(test.from, test.to),3}");
Console.Write(string.Join(Environment.NewLine, result));
结果:
2163 - 2212 actual: 12 expected: 12
2059 - 2102 actual: 10 expected: 10
1620 - 2056 actual: 107 expected: 107
1600 - 1684 actual: 22 expected: 22
1713 - 1988 actual: 67 expected: 67
1902 - 2164 actual: 65 expected: 65
1709 - 1881 actual: 42 expected: 42
1639 - 2124 actual: 118 expected: 118
1751 - 1948 actual: 48 expected: 48
1594 - 2184 actual: 144 expected: 144
1605 - 1691 actual: 21 expected: 21
1591 - 2082 actual: 120 expected: 120
1993 - 2066 actual: 18 expected: 18
2022 - 2158 actual: 33 expected: 33
1678 - 1919 actual: 57 expected: 57
1966 - 2128 actual: 40 expected: 40
1635 - 2069 actual: 106 expected: 106
1649 - 1963 actual: 75 expected: 75
1719 - 2169 actual: 110 expected: 110
1847 - 2093 actual: 61 expected: 61
假设,您有年份 a 和年份 b,它们是 年份范围 (它们包括在内),如何在不使用 loops 的情况下正确计算此 range 中的 leap years? (公历)
我是用 C# 写的,但我不认为我的代码很棒。我还使用了一个全局变量,但是大声笑,我认为有一个比这更好更优雅的解决方案。我只是一个新手,很抱歉我问了这个愚蠢的问题。 另外,我认为你不应该在这里使用 DateTime 等
这是我的代码:
class Program
{
public static int leap_years = 0;
static void Main()
{
do
{
int a, b;
leap_years = 0;
do Console.Write("Enter a: ");
while (!int.TryParse(Console.ReadLine(), out a) || a < 0);
do Console.Write("Enter b: ");
while (!int.TryParse(Console.ReadLine(), out b) || b < 0 || a == b || a >= b);
Console.WriteLine("Leap years: " + countLeapYears(a, b));
} while (Console.ReadKey().Key != ConsoleKey.Escape);
}
其中countLeapYears
是
static public int countLeapYears(int a, int b)
{
if (a > b)
return leap_years;
else
{
if (a % 4 == 0)
{
if (a % 100 == 0)
{
if (a % 400 == 0)
{
Console.WriteLine("Year {0} - leap year", a);
leap_years++;
a += 4;
countLeapYears(a, b);
}
else
{
Console.WriteLine("Year {0} - not a leap year", a);
a++;
countLeapYears(a, b);
}
}
else
{
Console.WriteLine("Year {0} - leap year", a);
leap_years++;
a += 4;
countLeapYears(a, b);
}
}
else
{
Console.WriteLine("Year {0} - not a leap year", a);
a++;
countLeapYears(a, b);
}
}
return leap_years;
}
}
public int LeapYear(int initialYear, int endYear, int ref countYear)
{
if (initialYear > endYear)
{
return countYear;
}
if(DateTime.IsLeapYear(initialYear)
{
countYear++;
}
initialYear++;
LeapYear(initialYear, endYear, countYear)
}
嗯,我们没有年份 0
:1BC
后面是 1AD
,这 破坏了乐趣 。但是,如果我们只能使用 AD
(正数年),您可以尝试这样的操作:
private static int countLeapYears(int from, int to) =>
(to / 4 - (from - 1) / 4) -
(to / 100 - (from - 1) / 100) +
(to / 400 - (from - 1) / 400);
让我们测试一下朴素计算:
private static int naiveCount(int from, int to) {
int result = 0;
for (int i = from; i <= to; ++i)
if (i % 400 == 0 || i % 4 == 0 && i % 100 != 0)
result += 1;
return result;
}
...
Random gen = new Random(123);
var result = Enumerable
.Range(1, 20)
.Select(i => {
int to = gen.Next(1590, 2222);
int from = gen.Next(1590, 2222);
return (from: Math.Min(from, to), to: Math.Max(from, to));
})
.Select(test => $"{test.from} - {test.to} actual: {countLeapYears(test.from, test.to),3} expected: {naiveCount(test.from, test.to),3}");
Console.Write(string.Join(Environment.NewLine, result));
结果:
2163 - 2212 actual: 12 expected: 12
2059 - 2102 actual: 10 expected: 10
1620 - 2056 actual: 107 expected: 107
1600 - 1684 actual: 22 expected: 22
1713 - 1988 actual: 67 expected: 67
1902 - 2164 actual: 65 expected: 65
1709 - 1881 actual: 42 expected: 42
1639 - 2124 actual: 118 expected: 118
1751 - 1948 actual: 48 expected: 48
1594 - 2184 actual: 144 expected: 144
1605 - 1691 actual: 21 expected: 21
1591 - 2082 actual: 120 expected: 120
1993 - 2066 actual: 18 expected: 18
2022 - 2158 actual: 33 expected: 33
1678 - 1919 actual: 57 expected: 57
1966 - 2128 actual: 40 expected: 40
1635 - 2069 actual: 106 expected: 106
1649 - 1963 actual: 75 expected: 75
1719 - 2169 actual: 110 expected: 110
1847 - 2093 actual: 61 expected: 61