Алгебра условных выражений в C # - PullRequest
1 голос
/ 17 августа 2011

Я работаю над небольшой частью соответствующей системы, которая использует логические условные выражения.

Эти условные выражения ограничены одной переменной и одним оператором (с краевым регистром Inclusive Between).

Меня интересует:

  • равно "="
  • Больше, чем ">"
  • Больше или равно "> ="
  • Меньше, чем "<" </li>
  • Меньше или равно "<=" </li>
  • включительно между "> = AND <=" </li>

У меня есть требование сравнить два условных выражения и оценить:

1) Возможно ли совпадение возможных значений?

Пересекается ли "X> 1000" с "X> 999"? Да.

2) Если есть перекрытие, верните перекрытие:

Перекрытие «X> 1000» с «X> 999» равно «X> 1000»

3) Ограничено ли условное выражение другим?

«X <999» ограничен «X <1000»; «X <1001» не ограничено «X <1000» </strong>


Что я сделал до сих пор, так это построил таблицу истинности всех возможных комбинаций и вернул результаты, но мне было интересно, есть ли более простой способ рассчитать их?

Какие-нибудь теории / справочные материалы / библиотеки C # существуют?

Ответы [ 2 ]

3 голосов
/ 17 августа 2011

Я не слышал о них, но вы легко можете обойтись без них, если представите ограничения в виде интервалов:

x> 1000 становится (1000, double.Infinity)
х == 1000 становится [1000, 1000]

и т.д.

Таким образом, вам нужен только один класс

class Constraint
{
    double Lower; bool isLowerStrict;
    double Upper; bool isUpperStrict;
    bool isIn(double d)
    { 
        return (isLowerStrict ? Lower < d : Lower <= d) &&
               (isUpperStrict ? Upper > d : Upper >= d);
    }

    Constraint intersect(Constraint other)
    {
        Constraint result = new Constraint();
        if (Lower > other.Lower)
        {
            result.Lower = Lower;
            result.isLowerStrict = isLowerStrict;
        }
        else if (Lower < other.Lower)
        {
            result.Lower = other.Lower;
            result.isLowerStrict = other.isLowerStrict;
        }
        else
        {
            result.Lower = Lower;
            result.IsLowerStrict = isLowerStrict || other.isLowerStrict;
        }
        // the same for upper
        return result;
    }

    public bool isEmpty()
    {
        if (Lower > Upper) return true;
        if (Lower == Upper && (isLowerStrict || isUpperStrict)) return true;
        return false;
    }
    public bool Equals(Constraint other)
    {
        if (isEmpty()) return other.isEmpty();
        return (Lower == other.Lower) && (Upper = other.Upper) &&
               (isLowerStrict == other.IsLowerStrict) &&
               (isUpperStrict == other.isUpperStrict);
    }

    // construction:
    static Constraint GreaterThan(double d)
    {
        return new Constraint()
        {
            Lower = d,
            isLowerStrict = true,
            Upper = double.PositiveInfinity,
            isUpperStrict = false
        };
    }
    static Constraint IsEqualTo(double d)
    {
        return new Constraint()
        {
            Lower = d,
            isLowerStrict = false,
            Upper = d,
            isUpperStrict = false
        };
    }
    // etc.
}

С помощью этого кода вы можете ответить на вопросы:

1) перекрытие: a.Intersect(b).isEmpty()

2) пересекаются: a.Intersect(b)

3) ограничение: a.Intersect(b).Equals(a)


EDIT:
Как подсказывает @CodeInChaos, вы должны рассмотреть возможность замены double на десятичное. Имейте в виду, что десятичному не хватает бесконечных значений, поэтому вы должны использовать вместо него decimal.MaxValue и decimal.MinValue.

0 голосов
/ 17 августа 2011

Я быстро написал пример кода.Надеюсь, это имеет смысл:

enum SygnType
{
    More, Less, Equal
}
public class Representation
{
    public SignType sign;
    public int value;
}
public class Range
{
    public bool infinityNegative;
    public bool infinityPositive;
    public int minValue;
    public int maxValue;
    public Range(List<Representation> values)
    {
        infinityNegative=true;
        infinityPositive=true;
        foreach(var value in values)
        {
            if (value.sign==SignType.More)
            {
                infinityNegative=false;
                if (value>minValue)
                    minValue=value;
            }
            else if (value.sign==SignType.Less)
            {
                infinityPositive=false;
                if (value<maxValue)
                    maxValue=value;
            }
            else if (value.sign==SignType.Equal)
            {
                infinityPositive=infinityNegative=false;
                minValue=maxValue=value;
                break;
            }
        }
    }
    public bool Overlaps(Range checkRange)
    {
        if (checkRange.infinityPositive)
            return CompareUpperLevelValue(checkRange); //this method should compare upper value overlapping
        else if (checkRange.infinityNegative)
            return CompareLowerLevelValue(checkRange); //this method should compare lower value overlapping
        else
            return CompareInterval(checkRange); //this method should compare interval
    }
    public bool CompareUpperLevelValue(Range checkRange)
    {
        if (checkRange.maxValue<maxValue)
            return true;
        else 
            return false
    }
    public bool CompareLowerLevelValue(Range checkRange)
    {
        if (checkRange.minValue>minValue)
            return true;
        else 
            return false
    }
    public bool CompareInterval(Range checkRange)
    {
        if ((checkRange.minValue>minValue)&&(checkRange.maxValue<maxValue))
            return true;
        else
            return false;
    }
}
...