【问题标题】:Determine if a given year is a leap year确定给定年份是否为闰年
【发布时间】:2017-07-08 11:42:23
【问题描述】:

更新我试图解决的问题需要的不仅仅是 Date 实现,因为它需要一种方法来同时考虑 1752 年之后的公历和 1752 年之前的儒略历闰年的不同定义。

以下是我的解决方案,它通过了我所有的 RSpecs,并且对我开始使用的嵌套条件进行了相当大的改进:

def leap_year?(year)

  gregorian_year = true if year >= 1752
  julian_year = true if year < 1752

  gregorian_test = true if year % 4 == 0 && year % 100 != 0 || year % 400 == 0
  julian_test = true if year % 4 == 0

  case
  when gregorian_year && gregorian_test
    true
  when julian_year && julian_test
    true
  else
    false
  end
end

原始问题

我写了一个简单、丑陋的嵌套条件来实现以下目标:

要实现以下目标:

如果年份满足以下条件,则返回“true”:

  1. 能被四整除
  2. AND 不是世纪年(例如)1900
  3. 除非它可以被 400 整除(例如 400、800、2000)

我写了一个丑陋的嵌套条件:

if year % 4 == 0
  puts "Divisible by four"
  if year % 100 == 0
    puts "Century year"
    if year % 400 == 0
      puts "Quad-century year, leap year"
      true
    else
      "Not a Quad-century year, not a leap year"
      false
    end
  else
    puts "Not a century year, leap year"
    true
  end
else
  puts "Not divisible by four: not a leap year."
  false
end

我尝试使用 case 条件来达到同样的效果,但它未能将数字 2016 检测为闰年:

case year
when (year % 4 == 0 && year % 100 != 0)
  true
when year % 400
  true
when year % 4 != 0
  false
end

两个问题:

  1. 在有条件的情况下我做错了什么?
  2. 有没有更好的方法来实现这一点?

【问题讨论】:

  • 更新了答案以包括 Date#gregorian_leap?Date#julian_leap?。请记住,不同国家/地区在不同年份将儒略历转换为公历。
  • 请不要在问题中包含答案(即您的“更新”)。如果您有解决方案,请将其作为答案单独发布。 (这在 SO 上经常看到。)读者喜欢中肯、清晰和简洁的问题。然后他们可能会查看答案,添加评论或答案,或者只是继续下一个问题,但他们不会不想浪费时间在问题本身中研究无关的材料。查看有多个赞成票的问题,并注意它们的共同特征。
  • 你的问题,因为它包含工作代码,更适合 SO 的姊妹站点 Code Review,在那里你会得到关于如何改进你的代码的建议。 SO 的任务是帮助修复损坏的代码并提出解决问题的方法。

标签: ruby if-statement switch-statement case


【解决方案1】:

如果您想确定给定的年份是否是闰年,那么已经在 Date 类中为您实现了 Date#leap?

Date.leap?(2000)
#=> true

# Or, alternatively:

Date.gregorian_leap?(1900)
#=> false

Date.julian_leap?(1900)
#=> true

Ruby 文档中的更多信息:Date#leap?

如果您想自己构建它,这应该可以:

def leap_year?(year)
  return false unless year % 4 == 0
  return true unless year % 100 == 0
  year % 400 == 0
end

leap_year?(2016)
#=> true

【讨论】:

  • 我个人觉得这个版本比case 语句更容易在我的脑海中解析,但这当然是主观的。
【解决方案2】:

如果您的 when 参数都是布尔值,则从 case year 中删除 year

  case
  when (year % 4 == 0 && year % 100 != 0)
    true
  when year % 400 == 0
    true
  else
    false
  end

您可以检查它是否有效:

def is_leap?(year)
  case
  when (year % 4 == 0 && year % 100 != 0)
    true
  when year % 400 == 0
    true
  else
    false
  end
end

require 'date'

p (0..2050).all?{|y| Date.leap?(y) == is_leap?(y)}
# true

这个变体可能更具可读性:

def is_leap?(year)
  case
  when year % 400 == 0
    true
  when year % 100 == 0
    false
  when year % 4 == 0
    true
  else
    false
  end
end

最后,你可以只写一个没有任何ifcase 的表达式:

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

【讨论】:

  • 最后一个变体更具可读性,但倒数第二个也很有帮助。谢谢!
  • @Eric 似乎对您的倒数第二个解决方案不太热情。
猜你喜欢
  • 2022-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多