Порівнюючи приблизні значення в c # 4.0?

Перш за все, будь ласка, вибачте, будь ласка, англійська мова не моя рідна мова.

Ось моє питання. Я створюю клас, який представляє приблизні значення як такі:

public sealed class ApproximateValue
{
    public double MaxValue { get; private set; }
    public double MinValue { get; private set; }
    public double Uncertainty { get; private set; }
    public double Value { get; private set; }

    public ApproximateValue(double value, double uncertainty)
    {
        if (uncertainty < 0) { throw new ArgumentOutOfRangeException("uncertainty", "Value must be postivie or equal to 0."); }

        this.Value = value;
        this.Uncertainty = uncertainty;
        this.MaxValue = this.Value + this.Uncertainty;
        this.MinValue = this.Value - this.Uncertainty;
    }
}

Я хочу використовувати цей клас для невизначених вимірювань, наприклад, x = 8.31246 +/- 0.0045, наприклад, і провести розрахунки за цими значеннями.

I want to overload operators in this class. I don't know how to implement the >, >=, <= and < operators... The first thing I thought of is something like this:

    public static bool? operator >(ApproximateValue a, ApproximateValue b)
    {
        if (a == null || b == null) { return null; }

        if (a.MinValue > b.MaxValue) { return true; }
        else if (a.MaxValue < b.MinValue) { return false; }
        else { return null; }
    }

Проте в останньому випадку я не задоволений цим "нулем", оскільки точний результат не є "нульовим". Це може бути "істинним", або воно може бути "помилковим".

Чи є об'єкт у .Net 4, який би допоміг реалізувати цю функцію, я не знаю, чи правильно я роблю? Я також думав про використання об'єкта замість логічного, який визначатиме, за яких обставин цінність перевершує, а не іншому, а не для операторів порівняння, але я відчуваю, що це набагато складніше для того, що я намагаюся досягти .. .

4
@ Джон, ти маєш рацію. Я думаю, що використання правил - це найточніший спосіб продовжити. У деяких випадках, якщо у мене є, наприклад, 3.5 <4.3 та 3.7 <4.1, у деяких випадках мені може знадобитися a> b, щоб повернути істинне, оскільки в деяких випадках це є істинним, і воно є достатньою, а в деяких випадках помилковим, тому що це не завжди істинно.
додано Автор Guillaume, джерело
@ JamesMichaelHare, хороший відгук, я не знав про це насправді.
додано Автор Guillaume, джерело
@Ramhound, я реалізував bool? тому що нульовим було найкраще, що я міг бачити, щоб запровадити невизначене значення.
додано Автор Guillaume, джерело
Ви не можете провести порівняння, оскільки у вас немає специфікації, яким має працювати порівняння. Запишіть правила, які б регулювали таке порівняння. Якщо у вас виникають труднощі з розробкою таких правил, це натяк на те, що порівняння безглуздо без контексту.
додано Автор Jon, джерело
Чому ви намагаєтесь повернути null на логічну операцію? Я не є причиною того, що ви навіть дозволите приблизному значення бути типовим для нульового типу.
додано Автор Security Hound, джерело
@Guillume: Як FYI, у .NET null> null є помилковим, null <�і> з нулями.
додано Автор James Michael Hare, джерело

5 Відповіді

I'd probably do something like this. I'd implement IComparable and then define <, >, <=, and >= according to the result of CompareTo():

public int CompareTo(ApproximateValue other)
{
   //if other is null, we are greater by default in .NET, so return 1.
    if (other == null)
    {
        return 1;
    }

   //this is > other
    if (MinValue > other.MaxValue)
    {
        return 1;
    }

   //this is < other
    if (MaxValue < other.MinValue)
    {
        return -1;
    }

   //"same"-ish
    return 0;
}

public static bool operator <(ApproximateValue left, ApproximateValue right)
{
    return (left == null) ? (right != null) : left.CompareTo(right) < 0;
}

public static bool operator >(ApproximateValue left, ApproximateValue right)
{
    return (right == null) ? (left != null) : right.CompareTo(left) < 0;
}

public static bool operator <=(ApproximateValue left, ApproximateValue right)
{
    return (left == null) || left.CompareTo(right) <= 0;
}

public static bool operator >=(ApproximateValue left, ApproximateValue right)
{
    return (right == null) || right.CompareTo(left) <= 0;
}

public static bool operator ==(ApproximateValue left, ApproximateValue right)
{
    return (left == null) ? (right == null) : left.CompareTo(right) == 0;
}

public static bool operator !=(ApproximateValue left, ApproximateValue right)
{
    return (left == null) ? (right != null) : left.CompareTo(left) != 0;
}
3
додано
Це хороша відповідь, але з огляду на те, що в обох випадках ці два значення однакові, може бути недостатньо точно.
додано Автор Guillaume, джерело
return a.Value - a.Uncertainty > b.Value + b.Uncertainty

I wouldn't really mess with the semantics of >: I think bool? is a dangerous return type here. That said, given the uncertainty, you could return true, if a is more likely to be > b.

1
додано

Мені здається, що ви повинні перевірити, чи a.MaxValue == b.MinValue теж у вашій поточній реалізації, яка поверне null , яка виглядає неправильною, вона повинна або повернімо true або false на основі того, як ви хочете, щоб специфікація дійсно працювала. Я не впевнений, що для будь-яких вбудованих .net-функцій для цього, тому я вірю, що ви йдете про це правильним шляхом.

1
додано

Це один з рідкісних випадків, коли для визначення значення типу (struct) може бути більше сенсу, що виключає нульову ситуацію. Ви також можете змінити значення MinValue і MaxValue для обчислювальних властивостей (просто застосуйте метод отримання, який обчислює результат), а не зберігати їх при побудові.

На бічній ноті порівняння приблизних значень сама є приблизною операцією, тому вам слід розглянути випадки використання для вашого типу даних; ви тільки збираєтесь використовувати порівняння, щоб визначити, коли діапазони не перетинаються? Це дійсно залежить від значення вашого типу. Чи передбачається це представляти точку даних з нормально розподіленого набору даних, де невизначеність є деякою кількістю стандартних відхилень для вибірки? Якщо це так, то для операції порівняння може бути більше сенсу повернути числову вірогідність (яку, звичайно, не можна викликати через оператор порівняння).

1
додано
Хороша відповідь, я думаю, що це найкращий висвітлення теми та найбільший обсяг питань, які слід розглянути. Дякую!
додано Автор Guillaume, джерело

Мені здається, що ви намагаєтесь запровадити деяку форму Ternary Logic , тому що ви хочете результат застосування операторів як True, False або Indeterminate. Проблема в тому, що ви дійсно не можете поєднати вбудовані логічні значення з вашим неопределенним значенням. Тому, хоча ви могли б зробити деякий обмежений спосіб порівняння двох ApproximateValues ​​, я думаю, що це неприйнятне використання bool в результаті цих порівнянь, оскільки це означає, що результат порівняння може вільно поєднуватися з іншими виразами, що призводять до значень bool, але можливість цього невизначеного значення підриває це. Наприклад, немає сенсу робити наступне, коли результат операції ліворуч від ОР є невизначеним.

ApproximateValue approx1 = ...;
ApproximateValue approx2 = ...;
bool result = ...;

bool result = approx1 > approx2 || someBool; 

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

1
додано
Порівняння з іншими булевими значеннями є хорошим пунктом ...
додано Автор Guillaume, джерело
var chat = new Chat();
var chat = new Chat();
642 учасників

Обсуждение вопросов по C# / .NET / .NET Core / .NET Standard / Azure Сообщества-организаторы: — @itkpi — @dncuug