【问题标题】:Using Double data type to transport Money values使用 Double 数据类型传输 Money 值
【发布时间】:2012-05-03 04:26:20
【问题描述】:

我知道使用 Double 数据类型进行 Money 计算是 asking for trouble 所以应该使用 Decimal。

我觉得这个问题很愚蠢,但是使用 Double 数据类型来存储或传输 Money 值是否存在潜在问题,只要在进行计算时将其转换为 Decimal 即可?

我问这个是因为我手头有一个旧的应用程序要维护,而且它到处都在使用 Double。为了节省工作,我只想重构实际进行计算的部分,使用 Decimal 而不是 Double。我想把剩下的部分放在一边,它只是用于数据传输、序列化等的管道代码。

【问题讨论】:

    标签: c# refactoring currency


    【解决方案1】:

    将数据存储在double 中时会损失精度,而不仅仅是在检索数据时。所以不,这不能解决你的问题。您无法神奇地找回丢失的精度。

    【讨论】:

    • 如果存储的值应该表示精确到一美分的值,并且如果值在检索时四舍五入到最接近的美分,那么除非使用非常大的数字,否则所有值将是精确的。请注意,无论使用何种格式,定义值舍入的程度都很重要。即使在decimal 中,(1.0m/7.0m)*7.0m 也不等于 1.0m。
    【解决方案2】:

    答案取决于您需要“传输”多少有效数字。 Decimal 为您提供 28 位数字,而 Double 为您提供大约 15 位左右。因此,如果您的值在 +/- 10 万亿范围内(假设有 2 个小数位),您应该没问题。如果您使用其他货币,您可能需要更多的小数位,因此范围将减少到例如+/- 1000 亿,小数点后 4 位。

    【讨论】:

      【解决方案3】:

      您不应该使用浮点值来存储货币值..

      也许使用 BigDecimal..https://blogs.oracle.com/CoreJavaTechTips/entry/the_need_for_bigdecimal

      【讨论】:

        【解决方案4】:

        例如你正在插入一个事务,假设所有的计算都是使用十进制数据类型来执行的

        Amount : $45.35
         TAX   : $ 1.72
        -----------------
        Total  : $47.07
        

        现在我们假设您制作了一张销售凭证并存储了所有三个值。在存储时,您将所有三个值都转换为双倍。所以它变成了二进制浮点值。

        如果用户再次尝试打开旧的销售凭证,您尝试检索三个值;这可能是由于四舍五入和转换(从双精度到十进制)您收到不同的值,可能如下所示

        Amount : $45.36 (//changed)
         TAX   : $ 1.72
        -----------------
        Total  : $47.07 (//Total sum is as stored, but when you sum 
                         //actual values retrieved, they are different.)
        

        这是基于我的经验,目前我无法从技术上解释这种情况。

        您也可能只存储AmountTax Rate,但是当您添加它们时,总和将比客户拥有的实际销售凭证多 1 美分:

        Amount : $45.36  /*View after sales*/         Amount : $45.35  /*What customer's*/
         TAX   : $ 1.72                                TAX   : $ 1.72  /*voucher says:*/
        -----------------                            -----------------
        Total  : $47.07                               Total  : $47.07
        

        【讨论】:

        • 啊 - 不,对不起。严重地。双精度数可能不准确,但如果您存储一个 4 位有效数字并重新加载它,并且它在第 4 位数字舍入错误 - 而双精度数存储 15 位数字 - 出现严重错误。就像你总是围起来一样。这个例子很糟糕。
        • @TomTom:我们不知道开发人员使用什么精确的舍入和转换方法。这是要照顾的。虽然我说过,但我在技术上无法解释这个错误。但只有当我们尝试将浮点数存储为十进制类型并在显示时执行舍入、除法、乘法等操作时才会发生这种情况。
        • 我们有。 45.35 到 25.35 是一种破路由方式。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多