【发布时间】: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#中
double tmp = 3.0 * 0.05;
tmp = 0.15000000000000002
这与金钱有关。该值实际上是 0.15 美元,但系统希望将其四舍五入到 0.16 美元。 0.151 可能应该四舍五入到 0.16,但不是 0.15000000000000002
有哪些方法可以获得正确的数字(即 0.15,如果小数足够高,则为 0.16)。
【问题讨论】:
使用定点变量类型,或十进制浮点类型,如 Decimal。浮点数总是有些不准确,而二进制浮点表示在与基数 2 进行转换时又增加了一层不准确性。
【讨论】:
钱应存储为decimal,即floating decimal point type。其他数据也是如此,这些数据实际上是离散的而不是连续的,并且在逻辑上本质上是十进制的。
由于显而易见的原因,人类对小数有偏见,因此货币等“人造”数量往往更适合小数形式。 “自然”量(质量、高度)具有更连续的尺度,这意味着float/double(即floating binary point types)通常(但并非总是)更合适。
【讨论】:
在企业应用架构模式中,Martin Fowler 建议使用 Money 抽象
http://martinfowler.com/eaaCatalog/money.html
他这样做主要是为了处理货币,但也是为了精确。
您可以在此 Google 图书搜索结果中看到一些内容:
【讨论】:
'decimal' 类型是专门为此设计的
【讨论】:
decimal 数据类型可以很好地工作,并且可能是您的选择。
但是,在过去,我已经能够使用定点整数以优化的方式做到这一点。它非常适合decimal 陷入困境并且您不能有float 的小精度误差的高性能计算。
从Int32 开始,然后分成两半。前半部分是整数部分,后半部分是小数部分。你得到 16 位有符号整数加上 16 位小数精度。例如1.5 作为 16:16 的固定点将表示为 0x00018000。或者,更改位的分布以满足您的需要。
定点数通常可以像任何其他整数一样添加/sub/mul/div,在 mul/div 周围做一些工作以避免溢出。
【讨论】:
【讨论】: