【问题标题】:Behind the scenes, what's happening with decimal value type in C#/.NET?在幕后,C#/.NET 中的十进制值类型发生了什么?
【发布时间】:2011-03-18 16:09:48
【问题描述】:

decimal 类型是如何实现的?

更新

  • 它是一个 128 位值类型(16 字节)
  • 1 个符号位
  • 尾数为 96 位(12 字节)
  • 8 位的指数
  • 剩余位(其中 23 个!)设置为 0

谢谢!我会坚持使用 64 位长度和我自己的隐含比例。

【问题讨论】:

    标签: c# types decimal primitive


    【解决方案1】:

    来自 J.Richter 的“CLR via C#”第三版:

    128 位高精度 常用的浮点值 财务计算,其中 舍入误差是不能容忍的。的 128位,1位代表 值的符号,96位代表 值本身,8位代表 10 的幂除以 96 位 值(可以是从 0 到 28).其余位未使用。

    【讨论】:

      【解决方案2】:

      如 MSDN 的十进制结构页面 http://msdn.microsoft.com/en-us/library/system.decimal(VS.80).aspx 所述:

      十进制的二进制表示 值由一个 1 位符号组成,一个 96 位整数和缩放 用于划分 96 位的因子 整数并指定它的哪一部分 是一个小数。缩放 factor 隐含地是数字 10, 提高到从 0 的指数 到 28. 因此,二进制 十进制值的表示是 形式为 ((-296 到 296) / 10(0 到 28)),其中 -296-1 等于 MinValue,并且 296-1 等于 最大值。

      缩放因子还保留任何 十进制数中的尾随零。 尾随零不影响 十进制数的值 算术或比较操作。 但是,尾随零可以是 ToString 方法显示,如果 应用了适当的格式字符串。

      【讨论】:

        【解决方案3】:

        decimal 关键字表示 128 位数据类型。

        Source

        Decimal 值的二进制表示由 1 位符号、96 位整数和用于划分 96 位整数并指定它的哪一部分是小数部分的比例因子组成。比例因子是隐含的数字 10,指数范围从 0 到 28。因此,十进制值的二进制表示形式为 ((-296 到 296) / 10(0 到 28)),其中-296-1 等于 MinValue,296-1 等于 MaxValue。

        Source

        【讨论】:

          【解决方案4】:

          Decimal Floating Point 维基百科上的文章,带有指向这篇关于 System.Decimal 的文章的特定链接。

          十进制以 128 位存储,尽管只有 102 位是绝对必要的。很方便将小数视为三个 32 位整数表示尾数,然后一个整数表示符号和指数。最后一个整数的最高位是符号位(以正常方式,该位设置为 (1) 用于负数)和位 16-23(高 16 位字的低位)包含指数。其他位必须全部清零 (0)。这种表示是由 decimal.GetBits(decimal) 给出的,它返回一个 4 个整数的数组。

          【讨论】:

          • 链接的文章很有帮助;这位 Skeet 先生似乎是 C# 相关问题的可靠来源。他有很多有见地的文章。
          【解决方案5】:

          来自C# Language Specifications

          decimal 类型是一种 128 位数据类型,适用于金融和货币计算。
          decimal 类型可以表示从 1.0 × 10−28 到大约 7.9 × 1028 的值,有效数字为 28-29。

          decimal 类型的有限值集的形式为 (–1)s × c × 10 -e,其中符号s为0或1,系数c为0≤c 96,并且标度 e 使得 0 ≤ e ≤ 28。
          decimal 类型不支持有符号零、无穷大或 NaN。 decimal 表示为一个 96 位整数,按 10 的幂进行缩放。对于绝对值小于 1.0m 的小数,该值精确到小数点后 28th 位,但不能再进一步。

          对于绝对值大于或等于 1.0m 的小数,该值精确到 28 或 29 位。与 floatdouble 数据类型相反,十进制小数(例如 0.1)可以精确地以十进制表示形式表示。 在floatdouble 表示中,这些数字通常是无限小数,这使得这些表示更容易出现舍入错误。

          如果二元运算符的一个操作数是decimal 类型,那么另一个操作数必须是整数类型或decimal 类型。如果存在整型操作数,则在执行操作之前将其转换为decimal

          decimal 类型的值进行运算的结果是通过计算精确结果(保留为每个运算符定义的比例)然后四舍五入以适应表示的结果。结果四舍五入到最接近的可表示值,并且当结果同样接近两个可表示值时,四舍五入到在最低有效数字位置具有偶数的值(这称为“银行家四舍五入”)。零结果的符号始终为 0,标度为 0。

          如果十进制算术运算产生的绝对值小于或等于 5 × 10-29,则运算结果为零。如果十进制算术运算产生的结果对于decimal 格式来说太大,则会抛出System.OverflowException

          decimal 类型比浮点类型具有更高的精度但范围更小。因此,从浮点类型到decimal 的转换可能会产生溢出异常,而从decimal 到浮点类型的转换可能会导致精度损失。由于这些原因,浮点类型和decimal 之间不存在隐式转换,并且如果没有显式转换,就不可能在同一个表达式中混合浮点和decimal 操作数。

          【讨论】:

            【解决方案6】:

            十进制类型只是另一种形式 浮点数 - 但不像 float 和 double,使用的底数是 10。

            简单的解释在这里http://csharpindepth.com/Articles/General/Decimal.aspx

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-10-19
              • 1970-01-01
              • 2011-07-17
              • 1970-01-01
              • 2011-07-12
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多