web-dev-qa-db-ja.com

C#には符号なしダブルがありますか?

nsigned doubleを使用する必要がありますが、C#はそのような型を提供しないことがわかりました。

なぜ誰か知っていますか?

30
Amit Raz

浮動小数点数は、IEEE 754仕様の実装にすぎません。私が知る限り、符号なしのdoubleのようなものはありません。

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

なぜ符号なし浮動小数点数が必要なのですか?

17
Anders Forsgren

Anders Forsgrenが指摘したように、IEEE仕様には符号なしdoubleはありません(したがって、C#にはありません)。

Math.Abs​​() を呼び出すことで常に正の値を取得でき、構造体でdoubleをラップして、そこで制約を適用できます。

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
}
16
Isak Savo

私が聞いたことのあるような言語やシステムでは、符号なしdoubleのようなものはありません。

分数になる可能性があり、正でなければならない変数を渡す機能を与える必要があります。それを強制するために、Functionシグネチャで使用したかったのです。

パラメータが正であるという制約を強制したい場合は、実行時チェックでそれを行う必要があります。

4
David Heffernan

私はあちこちで微調整を加えた@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が必要になる理由については、UI要素の幅と高さの寸法が非論理的であるため、ほとんどのアプリケーションで負になることはないことを考慮してください。では、なぜ必要のない負の数をサポートするのでしょうか。

PositiveInfinityNaNなどの一部の値は引き続き適用可能です。したがって、私たちはそれらに直感的な参照を提供します。 doubleUDoubleの大きな違いはUDoubleが定数NegativeInfinityを必要としないことです(または少なくとも私はこれだけを想定しています。私は数学者ではありません)結局のところ)MinValue定数は単に0。また、Epsilonは正ですが、符号なしの数値と同じコンテキストで使用することが論理的であるかどうかは不明です。

この実装は自動的に負の数を切り捨て、NegativeInfinityに設定しようとすると例外がスローされることに注意してください。

3
James M