43

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

Does anyone know why?

Ralph Willgoss
  • 11,750
  • 4
  • 64
  • 67
Amit Raz
  • 5,370
  • 8
  • 36
  • 63
  • 3
    Not really a duplicate since [that question](http://stackoverflow.com/questions/2523025/unsigned-double-in-c) is about C++, but it's the same reason. – Tim Pietzcker Sep 05 '11 at 08:55
  • 6
    why did this get downvoted? It's a valid question. +1 from me – Isak Savo Sep 05 '11 at 08:57
  • So you want [this sort of thing](http://stackoverflow.com/questions/3696326/how-can-the-allowed-range-of-an-integer-be-restricted-with-compile-time-errors), but for doubles rather than integers, and C# rather than C++ ? – AakashM Sep 05 '11 at 09:03

4 Answers4

23

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
}
Isak Savo
  • 34,957
  • 11
  • 60
  • 92
  • 3
    +1 for listing multiple ways to implement the desired behavior – ford Mar 19 '13 at 00:19
  • 1
    Why is it important to make the "unsafe" conversion operator explicit? (I've posted this question [here](http://stackoverflow.com/questions/26046700/why-when-is-it-important-to-specify-an-operator-as-explicit).) – kmote Sep 25 '14 at 19:40
  • Does the implicit operator eliminate the need to implement comparison operators? –  Mar 27 '17 at 02:34
  • @JamesM No, it only removes the need to make the typecast explicit (the following is ok with implicit: `PositiveDouble pd = ...; double d = pd`. Structs have a default equality implementation though if that's what you're asking, but that's completely separate from typecasting – Isak Savo Mar 27 '17 at 11:06
21

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?

Anders Forsgren
  • 10,827
  • 4
  • 40
  • 77
  • 5
    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. – Amit Raz Sep 05 '11 at 08:58
  • 6
    Use a runtime check, or discard the sign (use Math.Abs(arg)) or try code contracts, or change the argument type to a class/struct that enforces the constraint. I recommend either to throw an exception when a negative argument is passed (contractexception is a good idea), or to simply discard the sign if that can be made safely, e.g. – Anders Forsgren Sep 05 '11 at 09:06
  • 6
    if there is a uint etc, why did htey not make an unsigned double? Then you wouldn't have to do all that you mention in the above comment @AndersForsgren – David Klempfner Jul 31 '15 at 06:49
  • 16
    @Backwards_Dave that's a good question. I'm not responsible, i was 7 at the time :D – Anders Forsgren Jul 31 '15 at 21:00
4

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

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.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490