【问题标题】:Follow-up to BigDecimal new or valueofBigDecimal new 或 valueof 的跟进
【发布时间】:2014-01-03 18:04:52
【问题描述】:

此问题是对问题 (BigDecimal - to use new or valueOf) 及其接受的答案的跟进。

为方便起见,重申问题和答案:

BigDecimal有两种方法:

double d = 0.1;
BigDecimal bd1 = new BigDecimal(d);
BigDecimal bd2 = BigDecimal.valueOf(d);

哪个更好?答案表明这些方法不会产生相同的结果:

System.out.println(bd1);
System.out.println(bd2);

显示:

0.1000000000000000055511151231257827021181583404541015625
0.1

在回答中,回答者说:

一般来说,如果结果相同(即不是在BigDecimal 的情况下,而是在大多数其他情况下),那么应该首选valueOf():它可以缓存常见值(如@ 987654328@),它甚至可以更改缓存行为,而无需更改调用者。 new 将始终实例化一个新值,即使没有必要(最好的例子:new Boolean(true)Boolean.valueOf(true))。

我的问题是:我们能否获得一些实际示例,具体说明何时应该使用BigDecimal.valueOf() 以及何时应该使用new BigDecimal()?回答者说“如果结果相同,请使用 valueOf()”,但这并不能帮助我们知道何时使用它(如果有的话?)BigDecimal

具体来说,哪个更可取:

0.1000000000000000055511151231257827021181583404541015625

0.1

?为什么?

【问题讨论】:

  • 那么你想要哪个结果?他们以明确记录的方式做不同的事情。
  • 你怎么知道你想要哪个?这就是问题的核心。一个会比另一个更好吗?为什么?
  • 在哪种意义上更好?速度还是正确性? 0.1 不能用二进制补码浮点精确表示。
  • @ryvantage 你期待哪一个?没有任何信息,我猜你想要0.1,但只有你知道你的要求是什么。
  • “更好”的那个是导致整个程序为您提供所需结果的那个。而且我们不知道该程序应该做什么。

标签: java bigdecimal


【解决方案1】:

首先,当您从double 转换为BigDecimal 时,您应该退后一步,问问自己一开始您是否真的做对了。例如,如果您通过将String 解析为double 来完成此操作,那么您可能应该直接从String 解析为BigDecimal。我通常对这种转换持谨慎态度,因为它通常表明有人在别处使用了不合适的类型。

除此之外,它们还做了不同的事情:构造函数给出了一个BigDecimal,它表示与double完全相同的数字; valueOf 给出一个 BigDecimal,它表示由 double 值的规范字符串表示形式给出的数字。它们只是不同的东西,当你尝试使用一个时,你应该知道你想要哪一个。

鉴于我一开始会尽量避免陷入这种情况,很难举例说明何时更合适,但如果您不可避免地将文本转换为 @987654332 @,然后丢失了原始文本,但想恢复到那个值,那么使用valueOf可能给你一个更好的结果。如果您对double 值执行了一堆算术运算,那么构造函数可能 更合适。但它确实非常敏感,正如我所说,在大多数情况下,我可能会选择重新设计而不是选择任何一个选项。

【讨论】:

  • 我可以接受“这通常不是一个有效的场景”作为答案。 BigDecimal 适合持有由算术产生的 double,但您有多少次拥有不是由整数的算术运算产生的 original 双精度数?我想我想不出一种情况......所以是的,很好。
  • @ryvantage:不,这并不是真正“适合持有算术结果的double”-double 是!
  • 事实是,当我开始编程时,我使用float 进行所有操作;甚至用于存储货币值(以美元为单位)......甚至用于货币算术!最后,我的计算总是少了几美分。我的客户没有抱怨,但我并不高兴。这些年来我学到了很多东西,我慢慢地将所有代码转换为使用BigDecimal并将货币存储为ints,但很难记住转换为美元进行计算和查看所以我现在所拥有的是一大堆混乱的doubles 用于某些事情,ints 用于其他事情,BigDecimal
  • @ryvantage:为什么不将货币存储为BigDecimal?您所有的货币算术都可以使用BigDecimal 完成,因此您根本不需要乱码。
  • 无论如何,我的代码曾经使用BigDecimal.valueOf(double),但我听到了另一个问题并重新编写了我的代码以使用new BigDecimal(double),但后来我意识到我不确定哪个更好。现在我需要重新评估一切,看看我是否需要将双打传递给这些BigDecimals。但是在我构建的这些仪表板上计算了大量的东西(比率、销售总额等),所以这可能很难..
【解决方案2】:

查看 BigDecimal 的来源,很明显将 double 传递给 valueOf 比调用构造函数效率低

【讨论】:

    猜你喜欢
    • 2011-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-21
    • 2019-10-08
    相关资源
    最近更新 更多