比较c#4.0中的近似值?

时间:2011-10-28 16:25:18

标签: c#

首先,请原谅任何错字,英语不是我的母语。

这是我的问题。我正在创建一个代表近似值的类:

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,并对这些值进行计算。

我想重载此类中的运算符。我不知道如何实现&gt;,&gt; =,&lt; =和&lt;运营商...我想到的第一件事是这样的:

    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; }
    }

然而,在最后一种情况下,我对这个'null'不满意,因为准确的结果不是'null'。它可能是“真实的”,也可能是“假的”。

.Net 4中是否有任何对象可以帮助实现我不知道的这个功能,或者我是否采用了正确的方法?我还在考虑使用一个对象而不是一个布尔值来定义在什么情况下值优于或不在另一个上而不是实现比较运算符但是我觉得它对于我想要实现的东西来说有点过于复杂。

5 个答案:

答案 0 :(得分:3)

我可能会做这样的事情。我实施IComparable<ApproximateValue>然后根据CompareTo()的结果定义&lt ;,&gt;,&lt; =和&gt; =:

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;
}

答案 1 :(得分:1)

在我看来,您需要检查a.MaxValue == b.MinValue是否也会在当前实现中返回null,这似乎不正确,它应该返回true或{{1根据您希望规范实际工作的方式。我不确定是否有任何内置的.net功能,所以我相信你正确的方法。

答案 2 :(得分:1)

这是极少数情况下,定义值类型(struct)可能更有意义,然后消除null case问题。您还可以将MinValue和MaxValue修改为计算属性(只需实现计算结果的get方法),而不是在构造时存储它们。

另一方面,近似值的比较本身就是一个近似操作,因此您需要考虑数据类型的用例;您是否只打算使用比较来确定范围何时不重叠?这实际上取决于你的类型的含义。这是否表示来自正态分布数据集的数据点,其中不确定性是采样的一些标准偏差?如果是这样,比较操作返回数值概率(当然不能通过比较运算符调用)可能更有意义。)

答案 3 :(得分:1)

return a.Value - a.Uncertainty > b.Value + b.Uncertainty

我不会真正弄乱>语义:我认为bool?在这里是一种危险的返回类型。也就是说,如果不确定,您可以返回true,如果a 更可能> b

答案 4 :(得分:1)

在我看来,您正在尝试实现某种形式的Ternary Logic,因为您希望应用运算符的结果为True,False或Indeterminate。这样做的问题是你真的无法将内置布尔值与不确定值组合在一起。因此,虽然您可以对两个ApproximateValues做一些有限的比较,但我认为使用bool作为这些比较的结果是不合适的,因为这意味着比较的结果可以自由地与其他结果相结合导致bool值的表达式,但是不确定值的可能性会破坏它。例如,当OR左侧的操作结果不确定时,执行以下操作是没有意义的。

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

bool result = approx1 > approx2 || someBool; 

所以,在我看来,我不认为将比较作为操作符实现是一个好主意如果你想要保留不确定性。这里提供的解决方案消除了不确定性,这很好,但不是最初指定的。