Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / XML

SSTypesLT Library. Implementation of Ternary Logical Type SmartBool

0.00/5 (No votes)
6 May 2019MIT8 min read 8.1K   78  
Three state (ternary) logical type implemented using C# programming language

Before compilation and running, please read in the code comments or in chapter "Using the code" below how to install necessary libraries.

Introduction

Standard boolean type in programming languages has only two states “true” and “false”. For some cases, it is not enough. This article briefly describes development and practical use of ternary (three state) boolean type implemented in SSTypesLT library.

Motivation

Ternary logic is a logic having third value named for example “Undefined” or “Unknown” additionally to “True” and “False”. Modern programming languages directly supports only two state (binary) boolean logic. This fact is a result of hardware characteristics, because hardware operates on base of binary system. But ternary logic can be very helpful for programmers in some cases.

Database Management Systems support NULL values for all the data types representing absence of data. This value has the same semantic as logical “Unknown” – absent data or unknown value. The author faced the same problem with configuration files, where getting information about absent value for a boolean key cannot be easy signalled. Actually ternary logic extends possibilities of other data processing techniques. Comparing of two double values, for example, could be implemented with ternary logic with “Unknown” result if one of the values is NAN.

SSTypesLT Library

This article describes type SmartBool located in SSTypesLT library that is planned to be intensively used in data processing and quality control in project www.GoMap.Az. The author hopes to have time to develop SSTypesLT library and describe it. The author heartily invites readers to try SSTypesLT library and give their feedback.

SSTypesLT library is an Open Source project located here. SSTypesLT library is an open part of proprietary SSTypes library intensively used in project www.GoMap.Az. The author acknowledges:

Nullable Boolean Types in C#

Nullable Boolean type can be used to implement ternary logic in C#. Semantically, “null” value of Nullable Boolean variables fully equals to the NULL value in databases. But it does not originate to support third logical state because it is provided by generics that is applicable for any value type. Nullable Boolean is adoption of this language feature to implementation of the ternary logic.

As a result, this approach has some drawbacks:

  • null” value has another semantics and behavior comparing to “true” and “false
  • The operation with Nullable Boolean variable can throw an exception if the value is “null”. Operations with “true” and “false” in their turn do not ever throw exception.
  • Nullable Boolean variable in some operations, such as use in conditional statements requires explicit conversion to bool type
  • Nullable Boolean variable takes additional memory space for storing “hasValue” flag (see struct Nullable <T>, Microsoft Reference Source)

Examples of such drawbacks are presented in the following code snippets:

C#
bool? bn = null;
bool b2 = (bool)bn;

This code shows the following drawbacks:

  • Assignment of value of variable bn to variable b2 throws an exception
  • Assignment of value of variable bn to variable b2 requires explicit conversion to bool type (this cannot be considered as a flaw because Nullable Bool is more informative than bool)
  • null” value, but not an “unknown” nor “Undefined” assigned to variable bn (semantics problem)
C#
bool? bn = null;

if ((bool)bn)
{
    Console.WriteLine("True");
}
else
{
    Console.WriteLine("False or Unknown");
} 

This code shows the following drawbacks:

  • Statement “if” throws an exception
  • Statement “if” requires explicit conversion to bool type
  • String "False or Unknown" will be never displayed if bn is null (semantics problem)
  • null” value, but not an “unknown” nor “undefined” assigned to variable bn (semantics problem)

Operators "&&" and "||"

Nullable Bool does not implement operators "&&" and "||". The following code will not be compiled because operator "&&" cannot be apply to Nullable Bools:

C#
bool? nb1 = null;
bool? nb2 = true;

bool? nbt1 = nb1 && nb2;
bool? nbt2 = nb1 & nb2;

Extension for Nullable Boolean Type

Extension for Nullable Boolean type could improve the readability of code, its semantics and behavior (see Ternary logic.). But it does not resolve all problems relating to adoption of Nullable Boolean type to implement ternary logic.

SmartBool Type in C#

SmartBool is a structure, located in SSTypeLT library (see SSTypes project.). The structure has features allowing to implement ternary logic in the most convenient for the programmer way. Another structure SmartInt that represents 32-byte integer has been developed with the similar approach and successfully exploited for several years in web portal www.GoMap.Az, (see Accelerated .NET Types.).

SmartBool is based on sbyte (signed byte) type. This approach allows to implement negate operator “!” without jump statements (“if” statements). Jumps reduce predictability in CPU conveyor that influence performance. Unfortunately almost all operations of ternary logic cannot be implemented by single instructions on binary hardware platform. SmartBool has been developed to be memory small and fast in “if” statements. Performance of SmartBool and Nullable Boolean has been benchmarked and compared (See chapter “Performance” below).

Behavior of SmartBool slightly differs from behavior of Nullable Boolean. The following code is logically similar to the code presented above, but behaves in other manner.

C#
SmartBool sb = SmartBool.Unknown;
bool sb2 = (bool)sb;

if (sb)
{
    Console.WriteLine("True");
}
else
{
    Console.WriteLine("False or Unknown");
}

The advantages of the code are:

  • Variable sb takes value of SmartBool.Unknown that semantically is logical value, but not a representation of absent value;
  • Assignment of sb value to sb2 does not throw an exception;
  • Statement “if” works semantically right and does not throw an exception.

Implicit type cast in 2nd line needs because SmartBool is more informative than bool;

Operators “true“ and “false“

C# Reference by Microsoft describes “true” and “false” operators (see true and false operators (C# Reference).) as stated below. A type with the defined true operator can be the type of a result of a controlling conditional expression in the “if”, “do”, “while”, and “for” statements and in the conditional operator “?:”.

The “true” operator returns the bool value true to indicate that an operand is definitely true. The “false” operator returns the bool value true to indicate that an operand is definitely false. The “true” and “false” operators are not guaranteed to complement each other. That is, both the “true” and “false” operator might return the bool value false for the same operand.

SmartBool type implements “true” and “false” operators according to this description. It means that the following code will run as is described in comments:

C#
SmartBool sb1 = ...
SmartBool sb2 = ...
...

if (sb1)
{
    // Run if sb1 is True
    Console.WriteLine("True");
}
else
{
    // Run if sb1 is False or Unknown
    Console.WriteLine("False or Unknown");
}

if (!sb2)
{
    // Run if sb2 is False
    Console.WriteLine("False");
}
else
{
    // Run if sb2 is True or Unknown
    Console.WriteLine("True or Unknown");
}

So, the “else” section will run for Unknown value for both the above mentioned cases.

Operators "&&" and "||"

SmartBool implements operators "&&" and "||". The following code will be compiled without problems:

C#
SmartBool sb1 = null;
SmartBool sb2 = true;

SmartBool sbt1 = sb1 && sb2;
SmartBool sbt2 = sb1 & sb2;

Equality Operators “==” and “!=”

Equality operators “==” and “!=” of SmartBool return result of type SmartBool. These operators for bool and Nullable Bool return result as bool value. This is important difference of SmartBool from bool and Nullable Bool.

Semantic of comparing of unknown value with known one can be described as the process with unknown result. For long calculations, unknown value in input should produce unknown result if the result is dependent on this input value. SmartBool supports this semantics, but Nullable Bool does not.

The following code showed this difference:

C#
bool? nb1 = null;
bool? nb2 = true;

bool? nbt1x = nb1 == nb2;
// nbt1x has false value here

SmartBool sb1 = null;
SmartBool sb2 = true;

SmartBool sbt1x = sb1 == sb2;
// sbt1x has SmartBool.Unknown value here

Truth Tables for SmartBool

SmartBool supports standard truth tables for ternary logic. Truth tables for ternary logic are presented in many sources.

Operation NOT (operator “!”)

Image 1

Operation OR (operators “|” and “||”)

Image 2

Operation AND (operators “&” and “&&”)

Image 3

Operation EQUIVALENCE (operator “==”)

Image 4

Operation IMPLICATION

Image 5

Operation EXCLUSIVE OR (operator “^”)

Image 6

Performance

Benchmarks shows that performance of SmartBool is better than of Nullable Bool for operators “!”, “true”, and “false”. Benchmarks of operators OR “|” and AND “&” for SmartBool show somewhat slow performance comparing to Nullable Bool.

Equality operators of SmartBool do not show good performance comparing to Nullable Bool. But this fact is the result that equality operators of SmartBool implement a slightly complex logic and return SmartBool. But equality operators of Nullable Bool return bool. See chapter "SmartBool type in C# / Equality operators “==” and “!=”" above.

The following table shows benchmarks for several operations for considering 3 types. The values are relative and state only for comparing. Values for operators “true” and “false” are multiplied by 1000. The table has been built on figures of table located below:

Image 7

Benchmarks for assignment operators are presented in the following table. As it shows assignment of bool to SmartBool shows quite low performance. It is due to several “if” - checks in the logic of operator. At the same time, assignment of SmartBool to SmartBool is somewhat faster than Nullable Bool to Nullable Bool.

Image 8

The original benchmark output table. See the codes in downloadable zip-archives available by links in chapter "Using the code" below:

                       Method |      Median |      StdDev |
----------------------------- |------------ |------------ |
        Asg_Bool2NullableBool |  32.1589 us |  14.2492 us |
           Asg_Bool2SmartBool | 137.1827 us |  64.1514 us |
                Asg_Bool2Bool |  23.0328 us |   9.5130 us |
Asg_NullableBool2NullableBool |  39.7319 us |  15.7200 us |
      Asg_SmartBool2SmartBool |  28.5209 us |  11.4954 us |
                NOT_Bool2Bool |  31.4698 us |   8.9368 us |
NOT_NullableBool2NullableBool | 111.9670 us |  38.0665 us |
      NOT_SmartBool2SmartBool |  28.3513 us |   9.2716 us |
                 OR_Bool2Bool |  38.7323 us |  17.7660 us |
 OR_NullableBool2NullableBool | 204.6962 us |  76.5525 us |
       OR_SmartBool2SmartBool | 254.5754 us | 102.0478 us |
                AND_Bool2Bool |  37.4744 us |  11.4081 us |
AND_NullableBool2NullableBool | 170.3016 us |  54.8486 us |
      AND_SmartBool2SmartBool | 194.5647 us |  60.3215 us |
                 EQ_Bool2Bool |  35.4095 us |  12.3996 us |
 EQ_NullableBool2NullableBool |  72.4243 us |  22.2527 us |
       EQ_SmartBool2SmartBool | 184.6553 us |  56.8425 us |
                NEQ_Bool2Bool |  37.7590 us |  12.0692 us |
NEQ_NullableBool2NullableBool |  70.6348 us |  21.5845 us |
      NEQ_SmartBool2SmartBool | 154.4584 us |  62.6584 us |
                    TRUE_Bool | 317.5711 ns |  82.5786 ns |
            TRUE_NullableBool | 425.9031 ns | 140.4248 ns |
               TRUE_SmartBool | 299.9301 ns |  99.3415 ns |
                   FALSE_Bool | 312.6404 ns | 102.9978 ns |
           FALSE_NullableBool | 494.9714 ns | 133.1724 ns |
              FALSE_SmartBool | 294.6255 ns |  67.9278 ns |

Testing environment:

BenchmarkDotNet =v0.9.7.0
OS=Microsoft Windows NT 6.2.9200.0
Processor=Intel(R) Core(TM) i7-3610QM CPU 2.30GHz, ProcessorCount=8

Note: Due to cooling problem, the frequency of the CPU was forcibly set to 1.2 GHz.

Summary

To be laconic, the following results can be stated as summary:

  • Nullable Bool (bool?) was not designed to implement ternary logic
  • Extension for Nullable Bool can improve Nullable Bool but not solve all problems
  • SmartBool implements ternary logic by the best way
  • Logic of SmartBool differs from logic of Nullable Bool

Using the Code

Codes contain examples and benchmark. Microsoft Visual Studio Community 2015 was used to create the projects. Both projects require installation of SSTypesLT library. SmartBoolBenchMark project requires also BenchmarkDotNet library.

To install the libraries, you can use NuGet Package Manager Console from Microsoft Visual Studio. NuGet Package Manager Console can be activated through user menu "Tools/NuGet Package Manager/Package Manager Console".

For installation of SSTypesLT library, type the following command and press Enter:

Install-Package SSTypesLT

For installation of BenchmarkDotNet library, type the following command and press Enter:

Install-Package BenchmarkDotNet

For .NET Framework version 4.0 or later, you can use version 0.9.7 installed by the following command:

Install-Package BenchmarkDotNet -Version 0.9.7

The code can be downloaded from the link at the top of this page.

History

  • 20th April, 2019 - Initial article released

License

This article, along with any associated source code and files, is licensed under The MIT License