【问题标题】:Does C# have an Unsigned Double?C# 有无符号双精度数吗?
【发布时间】:2019-06-07 23:16:56
【问题描述】:

我需要使用 unsigned double,但事实证明 C# 不提供这种类型。

有人知道为什么吗?

【问题讨论】:

  • 不是真正的重复,因为that question 是关于 C++ 的,但原因相同。
  • 为什么这被否决了?这是一个有效的问题。来自我的 +1
  • 所以你想要this sort of thing,但是对于双精度数而不是整数,以及 C# 而不是 C++?

标签: c# double unsigned


【解决方案1】:

浮点数只是 IEEE 754 规范的实现。据我所知,那里没有无符号双精度数。

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

为什么需要无符号浮点数?

【讨论】:

  • 我需要能够传递一个可以是分数且必须为正数的变量。我想在我的函数签名中使用它来强制执行它。
  • 使用运行时检查,或丢弃符号(使用 Math.Abs​​(arg))或尝试代码协定,或将参数类型更改为强制约束的类/结构。我建议在传递否定参数时抛出异常(合同异常是个好主意),或者如果可以安全地制作,则简单地丢弃该符号,例如
  • 如果有一个 uint 等,为什么 htey 不做一个无符号双精度数?那么你就不必做你在上面的评论@AndersForsgren 中提到的所有事情了
  • @Backwards_Dave 这是个好问题。我不负责,我当时 7 岁:D
【解决方案2】:

在我听说过的任何语言或系统中都没有无符号双精度数。

我需要能够传递一个可以是分数且必须为正数的变量。我想在我的函数签名中使用它来强制执行它。

如果要强制执行参数为正的约束,则需要通过运行时检查来执行此操作。

【讨论】:

    【解决方案3】:

    正如 Anders Forsgren 所指出的,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
    }
    

    【讨论】:

    • +1 用于列出实现所需行为的多种方法
    • 为什么明确“不安全”转换运算符很重要? (我已经发布了这个问题here。)
    • 隐式运算符是否消除了实现比较运算符的需要?
    • @JamesM 不,它只消除了使类型转换显式的需要(以下可以使用隐式:PositiveDouble pd = ...; double d = pd。结构具有默认的相等实现,但如果这是你要的,但是这与类型转换完全不同
    【解决方案4】:

    我推出了一个更详细的@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 常量只是 @ 987654330@。另外,Epsilon 是肯定的,不过,我不确定在与无符号数字相同的上下文中使用是否合乎逻辑。

    请注意,如果您尝试设置为 NegativeInfinity,此实现会自动截断负数并引发异常。

    【讨论】:

      猜你喜欢
      • 2011-02-01
      • 2015-12-02
      • 2015-05-17
      • 2017-10-17
      • 2015-02-21
      • 2014-02-04
      • 2017-03-08
      • 1970-01-01
      相关资源
      最近更新 更多