闰年。 Ruby中的程序。有人可以解释一下吗?

时间:2016-11-11 05:44:23

标签: ruby

最近开始使用Ruby(之前没有编程背景)。

任务: 编写一个程序,要求开始年份和结束年份,然后将所有闰年放在它们之间(包括它们,如果它们也是闰年)。闰年是可被4整除的年份(如1984年和2004年)。然而,被100整除的年份不是闰年(例如1800和1900),除非它们可被400整除(如1600和2000,实际上是闰年)

代码:

puts 'Input a starting year:'
start_year = gets.chomp
puts 'Input an ending year:'
end_year = gets.chomp
puts ''

while start_year.to_i <= end_year.to_i

    if start_year.to_f%400 == 0
        puts start_year
    elsif start_year.to_f%100 == 0
    elsif start_year.to_f%4 == 0
        puts start_year
    end
    start_year = start_year.to_i + 1
end

有人可以一步一步地解释这个代码(字面意思)吗?以及控制台如何打印出这些日期?我们在哪里要求程序在这段代码中打印出来?

4 个答案:

答案 0 :(得分:2)

让我们逐行浏览代码。我将解释发生了什么,并说明如何改进。

puts 'Input a starting year:'
start_year = gets.chomp

start_year设为整数会更方便,因此我们不必在字符串和整数之间进行转换。因此,我们应该将第二行更改为

start_year = gets.to_i

如果您查看String#to_i的文档,您会发现这与

相同
start_year = gets.chomp.to_i

接下来,

puts 'Input an ending year:'
end_year = gets.to_i
puts ''

while start_year <= end_year

最后一行要求只要whilestart_year <= end_year,Ruby就会继续true循环。当此表达式变为false时(当start_year == end_year + 1时),她退出循环。请注意此行和下面行中的简化。

if start_year % 400 == 0
    puts start_year

如果年份可被400整除,则为闰年。

elsif start_year % 100 == 0

如果年份可以被100整除,但不能被400整除,那么它不是闰年,所以我们什么都不做,转到if / elsif / end子句的末尾和下一个执行start_year += 1

elsif start_year % 4 == 0
  puts start_year
end

如果年份可以被4整除,但不能被100整除,则是闰年。如果start_year % 4 != 0它不是闰年,那么我们就不打印它。

start_year += 1

Ruby扩展为start_year = start_year + 1

end

返回循环顶部并重复。

<强>更好

这里有一种类似Ruby的编写方式,将代码转换为方法,使用单个布尔表达式并打印方法的返回值(闰年数组)。

def leap_years(start_year, end_year)
  (start_year..end_year).select { |yr|
    yr % 400 == 0 || (yr % 100 != 0 && yr % 4 == 0) }
end 

puts 'Input a starting year:'
start_year = gets.to_i
puts 'Input an ending year:'
end_year = gets.to_i

p leap_years(start_year, end_year)
  #=> [1904, 1908, 1912, 1916, 1920]

first_year..last_year是一个范围(类Range的一个实例)。 Range包含模块Enumerable,为其提供实例方法Enumerable#select

<强>最佳

通过使用类方法Date::leap?,以下方法可以更轻松地获得两年之间的闰年。

require 'date'

def leaps_between(first_year, last_year)
  (first_year..last_year).select { |y| Date.leap?(y) }
end

leaps_between(2000, 2016)
  #=> [2000, 2004, 2008, 2012, 2016]

leaps_between(1900, 1916)
  #=> [1904, 1908, 1912, 1916]

答案 1 :(得分:0)

# Print the sentence "Input a starting year:"
puts 'Input a starting year:'
# Create a variable start_year and set its content to the user's input stripping it from the new line character 
start_year = gets.chomp
# Read above
puts 'Input an ending year:'
end_year = gets.chomp
puts ''

# Do something while start_year is smaller or equal to end_year
while start_year.to_i <= end_year.to_i
    # If start_year divided by 400 doesn't have any remainder
    if start_year.to_f%400 == 0
        # Print that year in the console
        puts start_year
    # Else if ...
    elsif start_year.to_f%100 == 0
    elsif start_year.to_f%4 == 0
        puts start_year
    end
    # Increase start_year by 1
    start_year = start_year.to_i + 1
end

答案 2 :(得分:0)

你问的是输出来自哪里? puts打印到控制台。

来自Kernel#puts的文档:

  

相当于

$stdout.puts(obj, ...)

来自IO#puts的文档:

  

将给定对象写入ios,与IO#print一样。在没有以换行符结束的任何内容之后写入记录分隔符(通常是换行符)。如果使用数组参数调用,则将每个元素写入新行。如果不带参数调用,则输出单个记录分隔符。

$stdout.puts("this", "is", "a", "test")
     

产生

this
is
a
test

答案 3 :(得分:0)

我还将使用迭代器:

puts "Please select 2 years to calculate the leap ones in between.  What's your 1st one?"
start_year = gets.chomp.to_i

puts "...and your second one?"
end_year = gets.chomp.to_i

range = start_year..end_year

range.select do |year| 
  puts year if year % 4 == 0 or year % 400 == 0
end

上面的while循环也可以重写如下:

puts 'Input a starting year:'
start_year = gets.chomp.to_i
puts 'Input an ending year:'
end_year = gets.chomp.to_i
puts ''

while start_year <= end_year
  if start_year % 400 == 0 or start_year % 4 == 0
      puts start_year
  end
  start_year += 1
end