【问题标题】:How to fix precision of variable如何固定变量的精度
【发布时间】:2008-10-07 16:38:05
【问题描述】:

在c#中

double tmp = 3.0 * 0.05;

tmp = 0.15000000000000002

这与金钱有关。该值实际上是 0.15 美元,但系统希望将其四舍五入到 0.16 美元。 0.151 可能应该四舍五入到 0.16,但不是 0.15000000000000002

有哪些方法可以获得正确的数字(即 0.15,如果小数足够高,则为 0.16)。

【问题讨论】:

    标签: c# .net math


    【解决方案1】:

    使用定点变量类型,或十进制浮点类型,如 Decimal。浮点数总是有些不准确,而二进制浮点表示在与基数 2 进行转换时又增加了一层不准确性。

    【讨论】:

    • 十进制也是浮点类型。它只是一个浮动小数点。
    • 很高兴知道。编辑希望能更准确一点。
    • 次要的挑剔是它们不是“不准确”,而是它们具有给定的精度。只是我们更自然地考虑十进制精度而不是二进制精度:D
    • sixlettervariables - 我打算提出同样的观点,但我觉得我最近吹毛求疵了。基本上 float/double 有一组完全可表示的值 - 它并不总是开发人员期望的那样。
    • 也许我应该说任意数学运算总是有点不准确(由于可表示值的别名,以及我们倾向于使用以十为基数而不是二进制的数字)?不过,它已经足够近了,可以让它骑行:)
    【解决方案2】:

    钱应存储为decimal,即floating decimal point type。其他数据也是如此,这些数据实际上是离散的而不是连续的,并且在逻辑上本质上是十进制的。

    由于显而易见的原因,人类对小数有偏见,因此货币等“人造”数量往往更适合小数形式。 “自然”量(质量、高度)具有更连续的尺度,这意味着float/double(即floating binary point types)通常(但并非总是)更合适。

    【讨论】:

      【解决方案3】:

      在企业应用架构模式中,Martin Fowler 建议使用 Money 抽象

      http://martinfowler.com/eaaCatalog/money.html

      他这样做主要是为了处理货币,但也是为了精确。

      您可以在此 Google 图书搜索结果中看到一些内容:

      http://books.google.com/books?id=FyWZt5DdvFkC&pg=PT520&lpg=PT520&dq=money+martin+fowler&source=web&ots=eEys-C_vdA&sig=jckdxgMLSRJtGDYZtcbYST1ak8M&hl=en&sa=X&oi=book_result&resnum=6&ct=result

      【讨论】:

      • 我喜欢 Fowler 的 Money 模式的一点是它使实际存储类型成为实现细节。干杯
      【解决方案4】:

      'decimal' 类型是专门为此设计的

      【讨论】:

        【解决方案5】:

        decimal 数据类型可以很好地工作,并且可能是您的选择。

        但是,在过去,我已经能够使用定点整数以优化的方式做到这一点。它非常适合decimal 陷入困境并且您不能有float 的小精度误差的高性能计算。

        Int32 开始,然后分成两半。前半部分是整数部分,后半部分是小数部分。你得到 16 位有符号整数加上 16 位小数精度。例如1.5 作为 16:16 的固定点将表示为 0x00018000。或者,更改位的分布以满足您的需要。

        定点数通常可以像任何其他整数一样添加/sub/mul/div,在 mul/div 周围做一些工作以避免溢出。

        【讨论】:

          【解决方案6】:

          你面临的是一个舍入问题,我之前在另一篇文章中提到过

          Can I use “System.Currency” in .NET?

          也可以参考Rounding

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-04-21
            • 1970-01-01
            • 2013-09-06
            • 1970-01-01
            • 2014-07-21
            相关资源
            最近更新 更多