我有一个程序可以使用标准数学运算符在doubles
上进行数学运算的Java代码片段,如下所示:
double someVal = 25.03;
return (someVal * 3) - 50;
对于原因(主要是舍入错误),我想更改所有这些片段以使用BigDecimal
而不是double
,修改数学函数,如下所示:
MathContext mc = MathContext.DECIMAL32;
BigDecimal someVal = new BigDecimal("25.03", mc);
return someVal.multiply(BigDecimal.valueOf(3), mc).subtract(BigDecimal.valueOf(50), mc);
这些片段大多非常简单,但如果可以,我宁愿避免使用脆弱的解决方案(例如正则表达式)。是否有相对简单的方法来做到这一点?
注意我想让程序或代码执行这些修改(元编程)。很明显,我能够手工改变,但生命太短暂。
答案 0 :(得分:0)
你可以试试Google的“Refaster”,根据the paper,它是“使用普通的,可编译的前后Java代码示例来指定Java重构的工具。”
代码位于Google core/src/main/java/com/google/errorprone/refaster
的error-prone
github project下。 (它曾经生活在自己的github project。)
这更像是一个提示,而不是一个答案,因为我从未直接使用过Refaster,也不知道它对原始表达式的效果如何,就像你的例子中那样。我也不知道像你这样的工具链使用它有多适合,而不是一次性重构(Google倾向于使用它)。但是它得到了积极的维护,而且我看到它在过去使用得非常有效。
答案 1 :(得分:0)
我们使用BigDecimal进行财务计算。根据其他评论,您将会有一些性能下降,代码将很难阅读。性能影响取决于您将拥有多少操作。通常,当计算链很长时,您会面临双打的舍入问题。如果您执行c=a+b
,则不会有很多问题,但如果您有c+=a+b
百万次,则会遇到很多问题。通过一千次操作,您会注意到bigDecimal的速度比double慢,因此性能测试也是如此。
在更改代码时要小心,特别是在划分时,您必须指定舍入模式和结果的比例,这是人们通常不会做的,并且会导致错误。
我认为不仅要更换计算逻辑,而且还需要更改域模型,所以我怀疑你能否在合理的时间内完成一个脚本,所以请亲自动手。好的IDE会对你有所帮助。
无论您如何转换代码,我建议首先确保所有计算逻辑都包含在单元测试中,并在更改逻辑之前进行单元测试转换。即通过用bigDecimals包装来替换值的断言。在这种情况下,您将避免愚蠢的输入/算法错误。
我不会回答你的问题如何从double转换为BigDecimal只想分享一些注释到
答案 2 :(得分:-2)
不要这样做。
double
或long
作为分数。它足够精确,只是一个正确编程的问题,以避免舍入错误:What to do with Java BigDecimal performance? 此处介绍了以编程方式操作Java源代码:Automatically generating Java source code
你不需要接受这个答案,但我相信我的建议是正确的,并认为这个问题的其他读者需要预先看到不进行这种转换的情况,这是我的发布这个有点非慷慨的理由。