追寻真理之美

——此人一贯挖坑不填

刘鑫ID:ccat
103432次访问,排名811好友0人,关注者5
ccat的文章
原创 66 篇
翻译 4 篇
转载 0 篇
评论 88 篇
智拙的公告
Python 2.4
最近评论
zhangjunhd:理解
ccat:错误我改过来了,PDF版和TeX版文件也重新上传了,但是HTML压缩包不知道怎么删除重新上传。
ccat:多谢提醒,我晚上回去看看。
ccat:杨编辑好:)
linux:嘿嘿,刘鑫老师,我是博文的linux!
文章分类
收藏
    相册
    文章插图
    朋友
    bobo,家有三猫
    Fire,永远比我严肃那么一点点
    lee
    limodou,NewEdit之父(RSS)
    Playyuer,近来可好(RSS)
    Ricky的私人领地
    Vicko,聪明的孩子,提着易碎的灯笼
    Vickox,一个人,两枝笔
    冰菊叮叮的绮季
    卡卡和哆哆的小窝,从这里开始,我的人生不再与以前相同
    寻梦的blog
    小尹,成功人士将来时。
    岑心的小天地
    暖暖,美丽的文字,总是让我深陷其中。
    梅劲松,Python经典实践(RSS)
    欢欢小师妹(RSS)
    灰色咆哮,彩色收藏
    蔚蔚,祝你幸福快乐
    西区故事,有故事的男人。
    面面的金鱼缸,内有美人鱼,生人勿近
    饼干~大饼~素饼饼~
    收藏
    cavingdeep,颇有知音之感(RSS)
    Guoly工作室,提供WinCVS中文教程
    Robert Chen(RSS)
    深入浅出,诲人不倦,可为人师也——项武义先生网站
    透明,熊节
    网络项目
    .net 中文讨论组
    Firebird项目的CVS
    Python2.3指南
    Python中文社区
    Python文档中文化项目
    啄木鸟
    啄木鸟的老巢
    我的新家
    休闲收藏
    办公室Party
    廖添丁
    恶搞圣斗士
    魔塔
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 March Library中的Multiboolean——多值逻辑实现收藏

    新一篇: 从苛希纳定律想到 | 旧一篇: March Library 版本更新

    (附前文)习惯上我们在应用系统中一直使用两值逻辑:非TrueFalse。两值逻辑的运算体系已经相当成熟,与、或、非以及衍生的异或、与非等等。但是在实际应用中,我们会有机会遇到三值逻辑。

    三值逻辑通常包含可选的TrueFalseNULL。如何在完备的两值逻辑运算体系中加入这个NULL,使之满足我们的需要,并且不会引发逻辑矛盾,就是我们要在这里讨论的。

    NULL参与逻辑运算时,实际上存在着不同的算法。按NULL值在运算中的“优先级”分为三种。

    通常我们在数据库中使用的三值逻辑,遵循NULL最优的原则。有NULL值参与二值运算时,返回结果为NULL,其它与二值逻辑相同。这一原则基于关系型数据库将NULL视为“无意义(Nil)”。由于其内容无意义,则任何逻辑值与之进行运算的结果都是无意义值,这也与许多数据关系型数据库对NULL的处理一致。

    另一方面,可能有些朋友没有注意到,事实上常见的权限体系也是一种三值逻辑,这个体系里NULL值处于最低优先级,两个权限值进行合并时,False(否定)高于一切,没有否定值时,肯定值(True)高于NULL,只有两个值均为NULL时,结果才为NULL。实际上我们可以将它看作是一个三值与运算,那么出于数学上的对称,很容易可以构造出对应的逻辑或运算。这种运算规则视NULL为“未赋值(Undefine)”。

    最后一种规定NULL值的优先级介于TrueFalse之间,与运算,二者有一为False时,返回False,否则二者有一为NULL时,返回NULL,二者均为True时返回True;或运算,二者有一为True时返回True,否则二者有一为NULL时返回NULL,二者均为False时返回False。这等于分别承认TrueFalse在或和与运算中的最高优先级。它基于NULL值为“未知”的理念。这种规则下,对NULL值严格视为未知的TrueFalseUnknown)。也有一些数据库的三值逻辑是基于这个体系的,MSDN中给出了一个基于此规则的DBBool示例。

    关于NULL值的学术讨论其实一直没有休止过,这期间还出现过四元逻辑等理论。实践也证明,“真实”世界中客观存在着不止一种三值逻辑体系。在实用中应当依据具体情况选择最适合的规则。

    我不想隐瞒,写下这一章的时候,我心里很自豪。对于真正的高手,那些创造了强大的虚拟机、框架和优雅类库的大师来讲,MultiBoolean这样的小东西确实不算什么。但是,这确是第一个可以让我自己满意的作品。虽然这个设计还不能作到完美,但是它已经可以满足我当前对多值逻辑的应用需求。

    长期以来,困扰我的最大问题莫过于多值逻辑中不同的空值如何兼容。当然,从数学意义来讲,不同的空值代表了不同的逻辑空间,它们之间不应该存在交叉。所以理想状态应该是根据某种标记来区分不同的逻辑,并将它们分隔开。但是在实用中,一个可以在不影响各自的逻辑算法、不引发异常的前提下处理多种空值逻辑的多值逻辑类型,似乎更为完美。毕竟它是一个基础类型,应该使用尽可能简单——我的Blog上记载了另一种多值逻辑实现,在实用中,我感觉它确实过于复杂了。一个只有几种状态的逻辑类型,居然需要工厂方法来构造……

    引起这种复杂结构的直接原因,即是我一直试图用-101三个整型来表达逻辑三态。也许对于某一种逻辑来讲,这样作是合适的,但是如果想要用一个0来表达多个逻辑空值,未免太过苛求了。

    用多个整数来表达?这种方式我也想过,比如将Nil设为最小值,UnKnown设为最大值。然而很难实现一个简单优雅的算法来兼容这些值,本来UnKnown本身的算法很简洁漂亮,而其它另两种虽然不够直观,但是足以内洽。当把它们放在一起的时候,不应该产生任何冲突。

    在一个偶然的机会,我想到了复数。是的,复数正是我需要的表达形式!如果将有效逻辑值表达为实数,将空值表达为虚数,这正是我所需要的效果。在形式上,由于Unknown的含义,恰恰可以将它视为“真正的空值”或“可能的逻辑值”两种体系的一个交叉点,也就是说,它正是那个实虚轴交叉的原点——0。而这也与MSDN中的空值算法兼容。

    这是一个令我激动的发现。很快,我着手寻找合适的复数实现。由于.net CLR中没有提供内置的复数类型,我参考STL中的复数实现编写了一个C#版本的Complex类型。后面的事,就是怎样把这个想法具体化了。

    以下就是实现代码,在代码的文档注释中,有各个主要功能的详细介绍:

    using System;

    using System.Data;

    using March.Math;



    namespace March.VBoolean

    {

    /// <summary>

    /// MultiBoolean VBoolean命名空间中最后加入的一个成

    /// 员,从结构来讲,可能也是多值离散逻辑的最终类型了。相比

    /// 同一空间内的VarBooleanBoolw3,它在数学上统一了三种空

    /// 值规则,成为一个完备实用的数据类型。后两者今后将只作为

    /// 向下兼容而存在,并且在以后的版本中可能会去掉这两个类型。

    /// </summary>

    public struct MultiBoolean

    {

    private Complex __value;

    private static readonly Complex TrueValue = new Complex(1, 0);

    private static readonly Complex FalseValue = new Complex(-1, 0);

    private static readonly Complex UnknownValue = new Complex(0, 0);

    private static readonly Complex UndefineValue = new Complex(0, 1);

    private static readonly Complex NilValue = new Complex(0, -1);

    /// <summary>

    /// 真值

    /// </summary>

    public static readonly MultiBoolean True = new MultiBoolean(new Complex(1, 0));



    /// <summary>

    /// 假值

    /// </summary>

    public static readonly MultiBoolean False = new MultiBoolean(new Complex(-1, 0));



    /// <summary>

    /// MultiBoolean 支持的空值类型之一,表示该值是真或假中

    /// 的一种,但是不能确定。

    /// </summary>

    public static readonly MultiBoolean Unknown = new MultiBoolean(new Complex(0, 0));



    /// <summary>

    /// MultiBoolean 支持的空值类型之一,表示未定义的逻辑值。

    /// 如果限定逻辑状态为TrueFalseUndefine中的一种,那么与运算即为权限管

    /// 理体系中的权限校验操作。

    /// </summary>

    public static readonly MultiBoolean Undefine = new MultiBoolean(new Complex(0, 1));

    /// <summary>

    /// MultiBoolean 支持的空值类型之一,表示无意义的逻辑值。

    /// </summary>

    public static readonly MultiBoolean Nil = new MultiBoolean(new Complex(0, -1));



    /// <summary>

    /// MultiBoolean 内部以复数表示逻辑状态,通过这个内部的

    /// 构造函数生成指定状态的逻辑值。

    /// </summary>

    /// <param name="value">代表状态的复数值,可能值为1,-1i-i0</param>

    private MultiBoolean(Complex value)

    {

    this.__value = value;

    }



    public bool IsTrue{get{return __value == TrueValue;}}

    public bool IsFalse{get{return __value == FalseValue;}}

    public bool IsUnknown{get{return __value == UnknownValue;}}

    public bool IsUndefine{get{return __value == UndefineValue;}}

    public bool IsNil{get{return __value == NilValue;}}



    /// <summary>

    /// 两值逻辑向 MultiBoolean 转型的隐式转型函数。

    /// 因为 MultiBoolean 中定义了多种可选的空值,CLR DBNull并未定义

    /// 与二值逻辑的转型规则,所以在这里不定义DBNullMultiBoolean 的隐式

    /// 转换。需要进行转换的用户可以根据自己的应用逻辑定义自己的类型转换。

    /// </summary>

    /// <param name="x">逻辑值</param>

    /// <returns>转换后的 MultiBoolean </returns>

    public static implicit operator MultiBoolean(bool x)

    {

    return x? True: False;

    }



    /// <summary>

    /// MultiBoolean的与操作。

    /// 返回值按NilFalseUnknownTrueUnDefine 的优先级从两值中取一返回。

    /// 如果限定逻辑状态为TrueFalseUndefine中的一种,那么该与运算即为权限管

    /// 理体系中的权限校验操作。

    /// </summary>

    /// <param name="x">左值</param>

    /// <param name="y">右值</param>

    /// <returns>返回值</returns>

    public static MultiBoolean operator & (MultiBoolean x, MultiBoolean y)

    {

    if(x.IsNil || y.IsNil)

    return Nil;



    if(x.IsUndefine )

    return y;

    if(y.IsUndefine)

    return x;



    return new MultiBoolean(x.__value.real < y.__value.real ? x.__value : y.__value);

    }



    /// <summary>

    /// MultiBoolean的或操作。

    /// 返回值按NilTrueUnknownFalseUnDefine 的优先级从两值中取一返回。

    /// </summary>

    /// <param name="x">左值</param>

    /// <param name="y">右值</param>

    /// <returns>返回值</returns>

    public static MultiBoolean operator | (MultiBoolean x, MultiBoolean y)

    {

    if(x.IsNil || y.IsNil)

    return Nil;



    if(x.IsUndefine)

    return new MultiBoolean(y.__value);

    if(y.IsUndefine)

    return new MultiBoolean(x.__value);



    return new MultiBoolean(x.__value.real > y.__value.real ? x.__value : y.__value);

    }



    /// <summary>

    /// MultiBoolean的非操作。TrueFalse互为非值。

    /// 空值的非操作通常没有意义,仍返回空值本身。当且仅当

    /// xTrueFalse时,!x=x&False(实际上x==Nil时也满足这个

    /// 规则,但其行为与T/F值的非不相同)。

    /// </summary>

    /// <param name="x">操作数</param>

    /// <returns>返回值</returns>

    public static MultiBoolean operator ! (MultiBoolean x)

    {

    return new MultiBoolean(new Complex(-x.__value.real, x.__value.imag));

    }



    /// <summary>

    /// MultiBoolean 对象的等值判断,需要指出的是,对于空

    /// 值,判断其是否相等没有意义,故两值中有至少一个为空时,

    /// 按以下规则判断:

    /// 只有一个为空值时,返回该空值状态;

    /// 两个都为空值时,返回优先级较高的一个。

    /// 定义这样的规则只是为了方便最常见的三值逻辑应用,我认为不应该出现不同空值

    /// 之间发生比较的场合,至少这样的运算非常罕见,而它的数学意义也模糊不清。

    /// 需要定义自己的判等规则时,可以调用对象的实例方法Equals或静态方法Equals

    /// </summary>

    /// <param name="x">左值</param>

    /// <param name="y">右值</param>

    /// <returns>返回值</returns>

    public static MultiBoolean operator == (MultiBoolean x, MultiBoolean y)

    {

    if(x.__value.real == 0 && y.__value.real == 0)

    return new MultiBoolean(new Complex(0, System.Math.Min(x.__value.imag, y.__value.imag)));



    if(x.__value.real == 0 && y.__value.real != 0)

    return new MultiBoolean(x.__value);



    if(x.__value.real != 0 && y.__value.real == 0)

    return new MultiBoolean(y.__value);



    return x.__value.real == y.__value.real ? True : False;

    }



    /// <summary>

    /// MultiBoolean 对象的不等判断,需要指出的是,对于空

    /// 值,判断其是否相等没有意义,故两值中有至少一个为空时,

    /// 按以下规则判断:

    /// 只有一个为空值时,返回该空值状态;

    /// 两个都为空值时,返回优先级较高的一个。

    /// 定义这样的规则只是为了方便最常见的三值逻辑应用,我认为不应该出现不同空值

    /// 之间发生比较的场合,至少这样的运算非常罕见,而它的数学意义也模糊不清。

    /// 需要定义自己的判等规则时,可以调用对象的实例方法Equals或静态方法Equals

    /// </summary>

    /// <param name="x">左值</param>

    /// <param name="y">右值</param>

    /// <returns>返回值</returns>

    public static MultiBoolean operator != (MultiBoolean x, MultiBoolean y)

    {

    if(x.__value.real == 0 && y.__value.real == 0)

    return new MultiBoolean(new Complex(0, System.Math.Min(x.__value.imag, y.__value.imag)));



    if(x.__value.real == 0 && y.__value.real != 0)

    return new MultiBoolean(x.__value);



    if(x.__value.real != 0 && y.__value.real == 0)

    return new MultiBoolean(y.__value);



    return x.__value.real == y.__value.real ? False : True;

    }



    /// <summary>

    /// 异或运算,这里按x^y=(!x&y)|(x&!y)规则,当且仅当xyTrue/False中一个

    /// 时,表达式与!=行为相同。

    /// </summary>

    /// <param name="x">左值</param>

    /// <param name="y">右值</param>

    /// <returns>返回值</returns>

    public static MultiBoolean operator ^ (MultiBoolean x, MultiBoolean y)

    {

    return (!x&y)|(x&!y);

    }



    public static bool operator true(MultiBoolean x)

    {

    return x.__value.real == 1;

    }



    public static bool operator false(MultiBoolean x)

    {

    return x.__value.real == -1;

    }



    /// <summary>

    /// MultiBoolean 对象的等值状态判断,需要指出的是,对于空

    /// 值,判断其是否相等没有意义,这里只是判断两个对象是否为同一

    /// “状态”,而它们在数学意义上不一定“相等”。

    /// 这个方法是重载System.Object.Equals(System.Object obj)

    /// 方法的通用接口。

    /// </summary>

    /// <param name="x">操作数</param>

    /// <returns>返回值</returns>

    public override bool Equals(object obj)

    {

    if(obj.GetType() != this.GetType())

    return false;



    return this.Equals((MultiBoolean)obj);

    }



    /// <summary>

    /// MultiBoolean 对象的等值状态判断,需要指出的是,对于空

    /// 值,判断其是否相等没有意义,这里只是判断两个对象是否为同一

    /// “状态”,而它们在数学意义上不一定“相等”。

    /// </summary>

    /// <param name="x">操作数</param>

    /// <returns>返回值</returns>

    public bool Equals(MultiBoolean x)

    {

    return this.__value == x.__value;

    }



    /// <summary>

    /// MultiBoolean 对象的等值状态判断,需要指出的是,对于空

    /// 值,判断其是否相等没有意义,这里只是判断两个对象是否为同一

    /// “状态”,而它们在数学意义上不一定“相等”。这个静态方法是

    /// 为了用户自定义逻辑体系而预留的,它与==运算符的判等规则不同。

    /// </summary>

    /// <param name="x">左值</param>

    /// <param name="y">右值</param>

    /// <returns>返回值</returns>

    public static bool Equals(MultiBoolean x, MultiBoolean y)

    {

    return x.__value == y.__value;

    }



    /// <summary>

    /// 获取Hash值,已重载

    /// </summary>

    /// <returns>对象的Hash值与它的值相对应。</returns>

    public override int GetHashCode()

    {

    return this.__value.GetHashCode ();

    }



    /// <summary>

    /// MultiBoolean对象表达为对应的字符串。

    /// </summary>

    /// <returns>与对象对应的字符串</returns>

    public override string ToString()

    {

    if(this.__value == TrueValue)

    return "True";

    if(this.__value == FalseValue)

    return "False";

    if(this.__value == UndefineValue)

    return "Undefine";

    if(this.__value == NilValue)

    return "Nil";

    return "Unknown";

    }



    /// <summary>

    /// 将字符串解析为对应的MultiBoolean值。

    /// </summary>

    /// <param name="input">待解析的字符串值,可选的范围是"True", "False", "Unknown", "Undefine, "Nil"</param>

    /// <returns>对应的MultiBoolean值。</returns>

    public static MultiBoolean Parse(string input)

    {

    switch(input)

    {

    case "True":

    return True;

    case "False":

    return False;

    case "Unknown":

    return Unknown;

    case "Undefine":

    return Undefine;

    case "Nil":

    return Nil;

    default:

    throw new ArgumentException("The string isn't a available Value.", input);

    }

    }



    /// <summary>

    /// 从数据库字段值中取出逻辑值,并将取转换为MultiBooleanDBNull对应的值取决于

    /// 用户传入的IsNull变量

    /// </summary>

    /// <param name="DBValue">数据库接口的GetValue方法返回的通常是一个object,可能的值为TrueFalseDBNull</param>

    /// <param name="IsNull">DBNull对应的值</param>

    /// <returns>返回的MultiBoolean</returns>

    public static MultiBoolean ReadDBValue(object DBValue, MultiBoolean IsNull)

    {

    if(DBValue is bool)

    return (bool)DBValue ? True : False;

    if(DBValue is DBNull)

    return IsNull;

    throw new ArgumentException("输入参数不是有效的逻辑值", "DBValue");

    }



    /// <summary>

    /// 将当前对象封装为T/F/DBNull

    /// 三值对象,用于对数据库访问接口赋

    /// 值,这个过程中会损失空值状态,所

    /// 以它与ReadDBValue并非互逆操作。

    /// </summary>

    /// <returns>封装好的对象</returns>

    public object ToDBOjbect()

    {

    switch(Convert.ToInt32(this.__value.real))

    {

    case 1 :

    return (object)true;

    case -1 :

    return (object)false;

    default:

    return DBNull.Value;

    }

    }