Есть ли в C# беззнаковый двойник?

Мне нужно использовать двойник без знака, но оказалось, что C# не предоставляет такой тип.

Кто-нибудь знает, почему?


person Amit Raz    schedule 05.09.2011    source источник
comment
На самом деле это не дубликат, поскольку этот вопрос касается C++, но причина та же.   -  person Tim Pietzcker    schedule 05.09.2011
comment
почему за это проголосовали? Это правильный вопрос. +1 от меня   -  person Isak Savo    schedule 05.09.2011
comment
Итак, вы хотите это типа вещи, но для двойных, а не целых чисел, и C#, а не C++?   -  person AakashM    schedule 05.09.2011


Ответы (4)


Числа с плавающей запятой — это просто реализация спецификации IEEE 754. Насколько я знаю, там нет такого понятия, как беззнаковый двойник.

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

Зачем вам беззнаковое число с плавающей запятой?

person Anders Forsgren    schedule 05.09.2011
comment
Мне нужно дать возможность передавать переменную, которая может быть дробной и должна быть положительной. Я хотел использовать его в своей сигнатуре функции, чтобы обеспечить его соблюдение. - person Amit Raz; 05.09.2011
comment
Используйте проверку во время выполнения, или отмените знак (используйте Math.Abs(arg)), или попробуйте контракты кода, или измените тип аргумента на класс/структуру, обеспечивающую соблюдение ограничения. Я рекомендую либо генерировать исключение при передаче отрицательного аргумента (contractexception — хорошая идея), либо просто отбросить знак, если это можно сделать безопасно, например. - person Anders Forsgren; 05.09.2011
comment
если есть uint и т.д., то почему htey не сделал unsigned double? Тогда вам не нужно было бы делать все, что вы упоминаете в комментарии выше @AndersForsgren. - person David Klempfner; 31.07.2015
comment
@Backwards_Dave, это хороший вопрос. Я не несу ответственности, мне тогда было 7 :D - person Anders Forsgren; 01.08.2015

Как указал Андерс Форсгрен, в спецификации 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
}
person Isak Savo    schedule 05.09.2011

Ни в одном языке или системе, о которых я когда-либо слышал, нет такой вещи, как беззнаковый двойник.

Мне нужно дать возможность передавать переменную, которая может быть дробной и должна быть положительной. Я хотел использовать его в своей сигнатуре функции, чтобы обеспечить его соблюдение.

Если вы хотите применить ограничение, что параметр является положительным, вам нужно сделать это с проверкой во время выполнения.

person David Heffernan    schedule 05.09.2011

Я развернул более подробную реализацию @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, возникнет исключение.

person Community    schedule 27.03.2017