2016-08-15 62 views
4

哪個「更正確(邏輯上)」? 具體到閏年,不一般閏年布爾邏輯:包括括號?

  1. 用括號

    return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0) 
    
  2. 沒有

    return year % 4 == 0 and year % 100 != 0 or year % 400 == 0 
    

附加信息

括號更改評估布爾值的順序(andor之前(不帶圓括號))。

鑑於所有較大的數字在此問題中可以被較小的數字整除,它會以任何方式返回正確的結果,但我仍然很好奇。

注意括號的影響:

  1. False and True or True 
    #True 
    
    False and (True or True) 
    #False 
    
  2. False and False or True 
    #True 
    
    False and (False or True) 
    #False 
    

沒有括號,還有場景中,即使一年不被4整除(第一布爾)仍然返回True(我知道這是不可能的)! 不能被4整除,因此包含括號更正確嗎?還有什麼我應該關注的嗎?有人能解釋不包括括號的理論邏輯嗎?

+3

的括號會改變評估順序而不是默認的從左到右。所以你必須真正有你的理由在種植它們之前改變訂單 –

+3

留下評論並不意味着我低估了。 –

回答

1

答:在括號


John Kugelman解釋了爲什麼他們是相對於3 2次獨立的邏輯測試, - >最後2要相對集中:

  1. 的年份必須是被4整除
  2. (2)年份不得爲100,(3)除非它能被400整除。

帶圓括號的版本最適合這種雙管齊下的規則。

return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0) 
     ^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
      (1)       (2) 

碰巧,去掉括號不破的代碼,但它會導致不自然的版本規則:

  1. 的年份必須是被4整除,但不能被100;或
  2. 年必須由400

這不是我想的閏年規則的方式整除。


通過mrdomoboto啓發,100/400是例外!:

的年份必須是被4整除,100是個例外,400是例外的例外,但他們仍然是一個例外(見上文)。這意味着如果年份不能被4整除,那麼整個事情都必須是假的。確保這一點的唯一方法是將異常放在例外情況,因爲False and bool將始終返回False。

見下面的這樣的例子從JBallin

  1. False and True or True 
    #True 
    
    False and (True or True) 
    #False 
    
  2. False and False or True 
    #True 
    
    False and (False or True) 
    #False 
    

Adam Smith翻譯英語成代碼:

所有年份被4整除是閏年,聯合國少他們是由100整除和400不能整除,轉化爲:

return y % 4 == 0 and not (y % 100 == 0 and y % 400 != 0) 

JBallin引用De Morgan's Laws

not(a and b) = (not a or not b) 

爲上述轉換成所需的答案:

#convert using "DML" 
return y % 4 == 0 and (not y % 100 == 0 or not y % 400 != 0) 
#remove "not"s by switching "==" and "!=" 
return y % 4 == 0 and (y % 100 != 0 or y % 400 == 0) 
5

parens會影響你的布爾值的順序。 and s的組合在一起,並解決之前or s爲,那麼:

a and b or c 

變爲:

(a and b) or c 

如果不是都是ab是truthy,或者如果c是truthy,我們得到True

和您的括號:

a and (b or c) 

現在你True如果兩個a是truthy,要麼b OR c是truthy。


只要「正確性」,只要您的代碼得出正確的結果,那麼「更正確」只是一個意見問題。我會在你想讓結果更清晰的地方加入parens。例如:

if (a and b) or c: 

if a and b or c: 

更加清晰,但這不是更清晰(在我看來)比:

if some_long_identifier and some_other_long_identifier or \ 
    some_third_long_identifier_on_another_line: 

您的指南時,編寫Python代碼應該是PEP8 。 PEP8在你應該包括文體括號的時候很安靜(閱讀:按照自然順序操作的parens),所以請使用你最好的判斷。


閏年具體而言,邏輯是:

  1. 如果年份是整除4,轉到步驟2 ...
  2. 如果年份是100整除,請轉到步驟3. ...
  3. 如果年份能夠被400整除,請轉至步驟4. ...
  4. 年份是閏年(有366天)。
  5. 今年不是閏年(它有365天)。

換句話說:所有能被4整除的是閏年,除非他們被100整除和NOT被400整除,轉化爲:

return y % 4 == 0 and not (y % 100 == 0 and y % 400 != 0) 
+1

已經在「附加信息」中說過,不回答問題:具體詢問有關閏年問題的問題,通常不是問題 – JBallin

+0

@JBallin然後我認爲您應該重申您的問題,因爲這正好回答了問題。 –

+0

最後一行顯示了我可以如何從邏輯上分離(b或c)!另外 - [德摩根定律](https://en.wikipedia.org/wiki/De_Morgan's_laws):不是(a和b)=不是或不是b – JBallin

2

哪個答案是「多正確「,爲什麼?

這不是什麼'更正確',而是;你希望實現什麼邏輯?圓括號'在布爾表達式變化order of operations。這使您可以在其執行中強制優先。

>>> (True or True) and False # or expression evaluates first. 
False 
>>> True or True and False # and evaluates first. 
True 

對於閏年式中的邏輯,所述rules去如下:

  1. 閏年是任何一年可通過圖4(如2012被均勻地劃分,2016年,等)

  2. 除非其可通過100被均勻地劃分,則它不是(如2100 ,2200,等)

  3. 除非其可通過400被均勻地劃分,則它是(如2000,2400)

因此例外規則必須優先,這是爲什麼圍繞or的括號有必要遵守公式的規則。其他方面,and的兩個參數將首先評估。

+0

我在「附加信息」中說明了這一點 – JBallin

+0

@JBallin更新了更多的邏輯解釋。 – ospahiu

+0

你是說:「(可以被4整除)AND(不是例外)」? – JBallin

3

包括括號。在英語中,規則是:

  1. 的年份必須是整除4
  2. 年度不得被100是可見的,除非它是整除400

用括號中的版本兩場比賽最好的規則。

return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0) 
     ^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
      (1)       (2) 

碰巧,去掉括號不破的代碼,但它會導致不自然的版本規則:

  1. 的年份必須是被4整除,但不能被100;或
  2. 年必須由400

這不是我想的閏年規則的方式整除。

1

哪個答案「更正確」,爲什麼? (具體到閏年邏輯,而不是在普通)

帶括號

回報年%4 == 0和(年%100!= 0或年%400 == 0)

沒有

年收益4%== 0和年100%!= 0或每年400%== 0

取決於你的 「更正確」 的定義。如你所知,兩者都返回正確。

現在推測「更正確」 - 如果您指的是性能優勢,考慮到當前的智能編譯器,我想不出任何方法。

如果你正在討論的觀點可讀性點,我會去的,

年收益4%== 0和年100%!= 0或每年400%== 0

它自然地縮小了範圍,與您的另一個選擇相反,這似乎包括兩個不相關的元素。

我建議,包括括號,但如下:

回報(!一年%4 == 0和年100%= 0),或每年400%== 0

1

正如你所注意到的,在操作中,沒有區別,因爲可以被400整除的數字意味着它也可以被100整除,這意味着它也可以被4整除。在操作上,括號是否有任何效果取決於詞彙語言順序(評估順序)。今天的大多數語言遵循c的慣例,這意味着操作符的指定優先級,否則從左到右。如有疑問,我總是爲了可讀性而放置括號。

從文體上看,這類事情很難在閱讀這樣的長篇文章時閱讀。如果一定要一個表情,我寧願到「概括產品的」邏輯「的產品和」所以我會去

return (year%400 == 0) or (year%100 != 0 and year%4 == 0) 

甚至

bool IsLeap = false; 
if (year%4 == 0) IsLeap = true; 
if (year%100 == 0) IsLeap = false; 
if (year%400 == 0) IsLeap = true; 

return IsLeap; 

優化編譯器會無論如何,要製作高效的代碼,這種事情真的可以幫助像我這樣的窮人閱讀它。