March Library中的Multiboolean——多值逻辑实现

(附前文)习惯上我们在应用系统中一直使用两值逻辑:非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;

}

}

}

}



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ccat

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值