LearnDotnet: Boolean

Boolean

很多人学过数学,但是对于逻辑缺乏基本的常识。因此我们需要先简单介绍逻辑。

数学背景

逻辑试图以简单且严谨的方式,解决言语上的纷争。大致上来说,我认为它基于两个基本假设:

  • 非黑即白。一句话要么是真的,要么是假的。不存在第三种情况。
  • 普遍相关。语句之间是有联系的。如果已知一些语句的真假,就可以推断出与之关联的其他语句的真假。而且在数学中,我们可以基于非常少的语句(几句或者几十句),推断出数学中绝大多数语句的真假。

在基本假设之下,语句的真假被分为两个层面研究。如果一个语句是由完整的其他语句通过联词联接组成的,那么这个语句的真假是各个组成部件确定的。研究这种关系的叫做命题逻辑。如果把语句进一步拆解为动词和名词等,然后把这些动词名词重新组合,就能得到另外的语句。研究重组前后语句真假值的联系的,就叫谓词逻辑。

一般来说,为了方便,人们认为“谓词逻辑”包含“命题逻辑”。也就是说,一般所说的“谓词逻辑”既研究名词和动词的重组,也研究句子通过联词的联接。

在确定了一些公理(公理就是假定为真的语句)之后,通过谓词逻辑,就能确定非常多语句的真假。一旦两个人承认相同的公理,并且都承认谓词逻辑。那么当两个人有分歧的时候,不必争吵,更不必打架,坐下来算一算就明了了。

当计算机出现以后,这套方法又有了新的用武之地。将一些实际中的问题抽象成逻辑问题,然后用计算机来计算,就能省下更多事情。为了把这一套方法搬到计算机中,就有了Boolean类型等机制。

机制

dotnet中的System.Boolean是用于表示真假的类型。它有两个值:truefalseBoolean值之间的运算,就能表示命题逻辑。

命题之间的联词有很多种,但是各种联词之间可以相互替代。最基本的联词是两个——“非”和“或”。其他联词可以通过这两个联词构造出来。一般为了使用方便,我们会把“非((非A)或(非B))”简写为“A与B”。这样就得到了三个最常用的联结词——与或非。

F#中分别使用&&||not三个算符表示这三个联结词。C#中则使用&&||!

异或

异或操作也可以由非或两个联结词组合。但是由于历史原因,C#中也用了专门的算符来表示它。这就是^。这个算符实际上有重载。除了处理逻辑异或,它还表示二进制异或运算。

相等

逻辑值也可以判断是否相等。如果两个逻辑变量的值一样就返回true,不一样就返回false。C#中用==进行判断,而F#中使用=进行判断。

作为相等关系的反面,还有不等关系。在两个变量一样的时候返回false,在不一样的时候返回true。C#中不等关系用!=表示,F#中用<>表示。

这两种关系判断实际上也是两种逻辑联结词。A==B等价于!(A^B)。而对于逻辑值来说,A!=BA^B具有相同的返回结果。

条件逻辑

对于“与”联结词来说,当知道第一个参数是false的时候,就没有必要得知第二个参数的真假。最终结果肯定是false。类似的情况“或”联结词也有。因此,&&||并不会完整计算前后两个表达式。如果第一个表达式的结果能够确定最终结果,第二个表达式就不会被求值。也就是说,第二个表达式是否被执行、求值,取决于第一个表达式的值。因此这种运算被称为“条件逻辑”。这种条件逻辑虽然看起来像是一种简单的运算,实际上能起到类似条件语句的效果。例如:

bool outputValue = y&&Print()

其中y是一个逻辑变量,Print是一个返回值为bool的函数。仅当ytrue才会执行Print函数。当然了,出于可读性考虑,个人非常不建议这样使用逻辑算符。

如果你需要不论什么情况,都完全计算前后两个表达式的逻辑运算。可以使用C#的|&。这两个算符也是重载了(C语言中)本来用于按位运算的算符。这两个算符分别对应||&&

C#中有保证两个表达式都运算的算符,主要是要使用函数的副作用。而函数式编程中,一般不允许函数副作用。因此,如果一个函数的返回值没有用,这个函数根本就不需要被执行。因此,你根本不会需要这种功能。如果你认为很需要,只能说明你的程序不够函数式。

作为算符的true和false

C#中有作为算符的truefalse。但是我们并不像使用其他算符一样用它们。这两个算符存在的意义就是重载。如果我们给一个类定义了truefalse的算符重载,那么这个类的对象就能像逻辑值一样用于作为跳转条件,条件表达式的条件等。

这两个算符如果要定义必须成对定义。它们接受一个类对象作为输入。当操作true的返回为true,这个对象在作为条件时就被转化为逻辑值true。当操作false的返回值为true时,这个对象在作为条件时就会被转化为逻辑值false

来看一个例子:

class Test
{
    public int x;
    public static bool operator true(Test t)
    {
        return t.x > 5;
    }
    public static bool operator false(Test t)
    {
        return t.x <= 5;
    }
}
class Program
{
    static void Main(string[] args)
    {
        var t = new Test();
        t.x = 20;
        if (t) // Use Text object as condition, not a logic value.
            Console.WriteLine("bigger than 5");
        else
            Console.WriteLine("equal to 5 or less than 5");
    }
}

谓词逻辑

Boolean类型看起来主要对应逻辑中的命题逻辑。只涉及组合语句层面的真假,而不能表示语句中的动词,量词,名词等更细致的结构。这是因为编程中,以函数调用作为不可进一步拆分为其他完整语句的原子语句。Boolean类型只需要处理命题逻辑层面的问题。而语句内部,谓词逻辑层面的事情,是函数定义内部决定的。

一个函数作用于某组参数的时候,返回值是true还是false是函数定义确定的。

顺便提一句,编程中的逻辑运算,旨在用逻辑方法让编程更方便。而不是通过程序完整模拟谓词推演。当然了用计算机模拟形式逻辑推演也是非常有意义的事情。只不过如果你想这么做,需要自己写程序或者调用别人写的逻辑推理程序。

有一些符号运算库,例如Python的sympy,中涉及了一些模拟逻辑推理的功能。但是似乎都不是很完善。因此有空的话,我计划用Haskell或者F#自己写一写试试。

主要参考

dotnet:

C#:

F#:

Boolean是一个值类型类,仅有truefalse两个值。外加与或非三种常用运算。此类型经常用于各种条件表达式,条件语句或者循环结构中。

需要注意C#和F#中的||&&都是short-circuit操作。当算符右边表达式的值就能确定表达式结果的时候,就不会计算算符左边表达式的值。

此外Boolean相关的可空类型,也是一个比较独特的点。这是C和C++没有的特性。当可空Boolean参与逻辑运算的时候遵循三值逻辑的运算法则。简单来说你把为null的变量当作未知变量,然后按照二值逻辑的标准做判断。如果一定要知道这个未知变量是true还是false之后才能确定整个表达式的结果,这个表达式的三值逻辑结果就是null。其他情况下三值逻辑的输出和二值逻辑一致。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值