2016-08-15 240 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; 

优化编译器会无论如何,要制作高效的代码,这种事情真的可以帮助像我这样的穷人阅读它。