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.
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
}
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?
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.
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
andNaN
may still be applicable; therefore, we provide intuitive references to them. The big difference betweendouble
andUDouble
isUDouble
wouldn't need the constantNegativeInfinity
(or at least I assume this much; I am not a mathematician, after all) andMinValue
constant is simply0
. 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
.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:
There is no such thing as an unsigned double in any language or system that I have ever heard of.
If you want to enforce a constraint that the parameter is positive, then you need to do that with a runtime check.