【问题标题】:Why is decimal more precise than double if it has a shorter range? C#如果十进制的范围更短,为什么它比双精度更精确? C#
【发布时间】:2018-11-01 19:06:44
【问题描述】:

我正在阅读 Nutshell 书中的 C#,它显示了这张表:

我很难理解这张桌子。它说 double 占用64 bits 的空间,范围从10^-32410^308。 十进制占用128 bits 的空间但也表示它的范围从10^-2810^28。那么我在这里的理解是十进制占用更多空间但提供更短的范围?这在我的脑海中没有多大意义,因为每个人都同意在需要精度时应该使用小数。 同样,在进行像 = (1/3)*3 这样的计算时,期望的结果是1,但只有floatdouble 给我1decimal 给我0.9999... 那为什么是@987654336 @ 更精确?我真的不明白。

【问题讨论】:

  • 粗略地说,小数点右边的位数越多,精度越高。您在小数点右侧跟踪的数字越多,您在小数点左侧的数字就越少。小数点两边都需要适合128位(小数的情况下)。
  • 它的精度不是更高,而是不同。它可以精确地存储十进制数字,并且当您习惯于将这些视为真实值时,它似乎更精确。如果你习惯二进制数,double 会。

标签: c# floating-point double decimal


【解决方案1】:

我在这里的理解是小数占用更多空间但提供更短的范围?

正确。它提供了更高的精度和更小的范围。显然,如果您的位数有限,则只能通过减小范围来提高精度!

每个人都同意在需要精度时应使用小数

由于该陈述是错误的——特别是,我不同意它——你从中得出的任何结论都是不正确的。

使用小数的目的不是为了提高精度。这是较小的表示误差。更高的精度是实现更小的表示误差的一种方法,但十进制并不能通过更高的精度来实现其更小的表示误差。它通过精确地表示小数来实现其较小的表示误差。

Decimal 适用于小数部分的表示误差必须为的场景,例如金融计算。

同样在进行 = (1/3)*3 之类的计算时,期望结果为 1,但只有 float 和 double 给我 1

你很幸运。对于浮点数和双精度数,有很多分数的计算表示错误都是非零的。

让我们快速检查一下有多少。我们将制作一百万个有理数,然后看看:

    var q = from x in Enumerable.Range(1, 1000)
            from y in Enumerable.Range(1, 1000)
            where ((double)x)/y*y != x
            select x + " " + y;
    Console.WriteLine(q.Count()); // 101791

超过 10% 的小数有理数被表示为具有足够大的表示误差的双精度数,以至于当它们乘以分母时不会变回整数!

如果您希望对任意有理数进行精确算术运算,那么 double 或 decimal 都不是合适的类型。 如果您需要精确表示有理数,请使用大有理库。

为什么十进制更精确?

Decimal 比 double 更精确,因为它具有更多位的精度。

但同样,精度实际上并没有那么重要。相关的是对于许多常见分数,十进制的表示错误小于双倍。

它的表示误差比 double 表示分母中小 10 次方的分数要小,因为它是专门设计的,它对于所有分母中的小 10 次方的分数都具有零表示误差分母。

这就是它被称为“十进制”的原因,因为它表示十次方的分数。它代表十进制系统,也就是我们常用的算术系统。

相比之下,Double 的设计显然不是为了具有小的表示错误。 Double 旨在具有适用于物理计算的范围、精度、表示误差和性能。

物理学中不存在对精确小数的偏见。金融界有这样的偏见。 财务使用小数。在物理中使用双打。

【讨论】:

  • 是你写的基本算术,bc我当然不能全部理解
  • @BeginnerTejas:“我无法理解这一切”并没有让我继续下去;我不知道你不明白什么,所以我很难改进答案。 您有具体问题吗? 如果有,请考虑发布;这是一个问答网站。
  • 这毫无疑问。实际上,您在这个特定的答案中已经涵盖了很多内容。编程,数学,物理,金融等。只是跳过去看看要达到那个水平需要什么。这可能是我的问题,你是对的,我应该发布它。您不必在这里回复,但人们肯定需要像您这样的导师。谢谢:)
  • @BeginnerTejas:我学习了 C# 设计,每天 8 小时,每周 5 天,学习了 7 年,而且我受益于在我是经验最少的人的环境中学习在房间里,所以我有导师可以学习。此外,我得到了报酬。如果你学习一件事 14000 小时,你也会很擅长,所以如果这就是你想要的,那就找一份人们付钱让你学习的工作!
【解决方案2】:

Decimal 不使用指数增加范围,它包含所有数字(约 29),其中 double 使用指数,但仅包含约 19 位,其余被丢弃。指数增加范围,但不增加准确度。

【讨论】:

  • 这个答案是正确的,但我想澄清一下:decimal 确实 在内部使用指数。它只是不像 double 那样使用该指数来增加范围。
  • @EricLippert:Decimal 的指数用于增加范围。它不会增加几乎与Double 上的指数一样远的范围,但 16 字节定点类型将被限制为小数点两侧总共 39 位小数,Decimal 超出即,允许左侧最多 29 个,右侧最多 28 个,但以浮点类型为代价并导致此类类型固有的基于范围的舍入错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-17
  • 2023-02-22
相关资源
最近更新 更多