Мне нужно использовать двойник без знака, но оказалось, что C# не предоставляет такой тип.
Кто-нибудь знает, почему?
Мне нужно использовать двойник без знака, но оказалось, что C# не предоставляет такой тип.
Кто-нибудь знает, почему?
Числа с плавающей запятой — это просто реализация спецификации IEEE 754. Насколько я знаю, там нет такого понятия, как беззнаковый двойник.
http://en.wikipedia.org/wiki/IEEE_754-2008
Зачем вам беззнаковое число с плавающей запятой?
Как указал Андерс Форсгрен, в спецификации IEEE (и, следовательно, в C#) нет беззнаковых двойников.
Вы всегда можете получить положительное значение, вызвав Math.Abs(), и вы может обернуть двойник в структуру и применить там ограничение:
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
}
PositiveDouble pd = ...; double d = pd
. Структуры имеют реализацию равенства по умолчанию, хотя, если это то, о чем вы просите, но это полностью отделено от приведения типов
- person Isak Savo; 27.03.2017
Ни в одном языке или системе, о которых я когда-либо слышал, нет такой вещи, как беззнаковый двойник.
Мне нужно дать возможность передавать переменную, которая может быть дробной и должна быть положительной. Я хотел использовать его в своей сигнатуре функции, чтобы обеспечить его соблюдение.
Если вы хотите применить ограничение, что параметр является положительным, вам нужно сделать это с проверкой во время выполнения.
Я развернул более подробную реализацию @Isak Savo с некоторыми изменениями. Не уверен, что это идеально, но это отличное место для начала.
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();
}
}
Что касается того, зачем нужен беззнаковый double
, учтите, что размеры ширины и высоты элементов пользовательского интерфейса не могут быть отрицательными в большинстве приложений, поскольку это было бы нелогично; зачем тогда поддерживать отрицательные числа там, где они не нужны?
Некоторые значения, такие как PositiveInfinity
и NaN
, все еще могут быть применимы; поэтому мы предоставляем интуитивно понятные ссылки на них. Большая разница между double
и UDouble
заключается в том, что UDouble
не нужна константа NegativeInfinity
(по крайней мере, я так предполагаю; в конце концов, я не математик), а константа MinValue
— это просто 0
. Кроме того, Epsilon
является положительным, хотя я не уверен, логично ли его использовать в том же контексте, что и беззнаковые числа.
Обратите внимание, что эта реализация автоматически усекает отрицательные числа, и если вы попытаетесь установить значение NegativeInfinity
, возникнет исключение.