Friday, August 19, 2005

[C++]閏年的啟發

「判斷某一年是否為閏年」是個很典型的初級程設例題。
閏年的規則如下:四年一閏,每一百年不閏,每四百年又閏。
此規則的圖解為:
                  400的倍數→閏年
           100的倍數<
      4的倍數<       非400的倍數→平年
西曆年數<      非100的倍數→閏年
      非4的倍數→平年

(取自88年高雄市程式設計競賽 題目)

意思是說,我們要判斷 a 年是否為閏年,得經過三個關卡檢驗:
1. a 是否被4整除;如果是則進入下一關。
2. a 是否也被100整除;如果是則進入下一關。
3. a 是否也被400整除。如果是則 a 年為閏年
第1.關的答案若是否定的(非4的倍數),則 a 年為平年。
第2.關的答案若是否定的(非100的倍數),則 a 年為閏年

由此可見,在程式編寫時,我們須要用到三層 if 判斷指令:

if(a%4==0)
{ 
  if(a%100==0)
  { 
    if(a%400==0)
    {
     cout<<a<<"年為閏年";
    }
    else cout<<a<<"年為平年";
  }
  else cout<<a<<"年為閏年";

else cout<<a<<"年為平年";

此程式中,我們使用三層 if 指令(邏輯判斷)將所有狀況分成四塊,這四塊由不同的條件隔開,各自對應到正確的動作,印出正確的答案。這種方法完全符合上面的圖解與文字說明的要求。

上面的解釋方式看似還蠻清晰的,但若是我們使用邏輯中的「集合」概念來看此問題,上述的三個關卡之間的關系將變得更加地簡明。
「集合式」的圖解:(本圖並未使用正確的比例繪製)

圖中我們可以看到,圈圈的內外分別代表條件的是與非。閏年其實就是由兩個著色塊構成的集合:一藍一紅。藍色的形狀是個甜甜圈,紅色是個小圓形。它們兩個互不相交,所以應該可以用簡單的條件定義出這兩個區塊(註)。仔細地想一下,可以發現如果我們要定義一個甜甜圈只須要兩個條件:外圈條件與內圈條件--此題的外圈是「是否被4整除」,內圈是「是否被100整除」。而定義一個圓形更簡單,只要一個條件--此題為「是否被400整除」--即可。所以現在我們可以只用一層 if 判斷指令,完成先前的三層 if 所完成的工作:

if( (a%4==0 && a%100!=0) || a%400==0)

 cout<<a<<"年為閏年";

else cout<<a<<"年為平年";

結果,我們受到的啟發是:使用邏輯中的「集合」概念來分析題目,會是個好方法。在文氏圖中,一條分隔線代表一個(判斷)條件;一塊區域是由一到數條分隔線圍成的,所以一塊區域的定義也必然是由一到數個(判斷)條件寫成的。

註:如果我們須要用到的著色塊彼此相交,則須使用更複雜的方式來描述他們的定義。

0 Comments:

Post a Comment

<< Home