Unsigned Double

2019-01-27 12:04发布

I need to use an unsigned double but it turns out C# does not provide such a type.

Does anyone know why?

4条回答
Luminary・发光体
2楼-- · 2019-01-27 12:35

Floating point numbers are simply the implementation of the IEEE 754 spec. There is no such thing as an unsigned double there as far as i know.

http://en.wikipedia.org/wiki/IEEE_754-2008

Why do you need an unsigned floating point number?

查看更多
家丑人穷心不美
3楼-- · 2019-01-27 12:46

I rolled out a more detailed implementation of @Isak Savo's with tweaks here and there. Not sure if its perfect, but it's a great place to start.

public struct UDouble
{
    /// <summary>
    /// Equivalent to <see cref="double.Epsilon"/>.
    /// </summary>
    public static UDouble Epsilon = double.Epsilon;

    /// <summary>
    /// Represents the smallest possible value of <see cref="UDouble"/> (0).
    /// </summary>
    public static UDouble MinValue = 0d;

    /// <summary>
    /// Represents the largest possible value of <see cref="UDouble"/> (equivalent to <see cref="double.MaxValue"/>).
    /// </summary>
    public static UDouble MaxValue = double.MaxValue;

    /// <summary>
    /// Equivalent to <see cref="double.NaN"/>.
    /// </summary>
    public static UDouble NaN = double.NaN;

    /// <summary>
    /// Equivalent to <see cref="double.PositiveInfinity"/>.
    /// </summary>
    public static UDouble PositiveInfinity = double.PositiveInfinity;

    double value;

    public UDouble(double Value)
    {
        if (double.IsNegativeInfinity(Value))
            throw new NotSupportedException();

        value = Value < 0 ? 0 : Value;
    }

    public static implicit operator double(UDouble d)
    {
        return d.value;
    }

    public static implicit operator UDouble(double d)
    {
        return new UDouble(d);
    }

    public static bool operator <(UDouble a, UDouble b)
    {
        return a.value < b.value;
    }

    public static bool operator >(UDouble a, UDouble b)
    {
        return a.value > b.value;
    }

    public static bool operator ==(UDouble a, UDouble b)
    {
        return a.value == b.value;
    }

    public static bool operator !=(UDouble a, UDouble b)
    {
        return a.value != b.value;
    }

    public static bool operator <=(UDouble a, UDouble b)
    {
        return a.value <= b.value;
    }

    public static bool operator >=(UDouble a, UDouble b)
    {
        return a.value >= b.value;
    }

    public override bool Equals(object a)
    {
        return !(a is UDouble) ? false : this == (UDouble)a;
    }

    public override int GetHashCode()
    {
        return value.GetHashCode();
    }

    public override string ToString()
    {
        return value.ToString();
    }
}

As to why one would need an unsigned double, consider that width and height dimensions of UI elements cannot be negative in most applications as that would be illogical; why, then, support negative numbers where they're not needed?

Some values like PositiveInfinity and NaN may still be applicable; therefore, we provide intuitive references to them. The big difference between double and UDouble is UDouble wouldn't need the constant NegativeInfinity (or at least I assume this much; I am not a mathematician, after all) and MinValue constant is simply 0. Also, Epsilon is positive, though, I am uncertain whether or not it is logical to use in the same context as unsigned numbers.

Note, this implementation automatically truncates negative numbers and an exception is thrown if you attempt to set to NegativeInfinity.

查看更多
乱世女痞
4楼-- · 2019-01-27 12:47

As pointed out by Anders Forsgren, there is no unsigned doubles in the IEEE spec (and therefore not in C#).

You can always get the positive value by calling Math.Abs() and you could wrap a double in a struct and enforce the constraint there:

public struct PositiveDouble 
{
      private double _value;
      public PositiveDouble() {}
      public PositiveDouble(double val) 
      {
          // or truncate/take Abs value automatically?
          if (val < 0)
              throw new ArgumentException("Value needs to be positive");
          _value = val;
      }

      // This conversion is safe, we can make it implicit
      public static implicit operator double(PositiveDouble d)
      {
          return d._value;
      }
      // This conversion is not always safe, so we make it explicit
      public static explicit operator PositiveDouble(double d)
      {
          // or truncate/take Abs value automatically?
          if (d < 0)
              throw new ArgumentOutOfRangeException("Only positive values allowed");
          return new PositiveDouble(d);
      }
      // add more cast operators if needed
}
查看更多
你好瞎i
5楼-- · 2019-01-27 12:57

There is no such thing as an unsigned double in any language or system that I have ever heard of.

I need to give the ability to pass a variable that can be a fraction and must be positive. I wanted to use it in my Function signature to enforce it.

If you want to enforce a constraint that the parameter is positive, then you need to do that with a runtime check.

查看更多
登录 后发表回答