【发布时间】:2017-03-16 09:26:15
【问题描述】:
我编写测试并希望将 BigDecimal 结果与预期值进行比较。
我想使用 Assert.assertEquals(BigDecimal, BigDecimal) 方法,因为如果删除它会显示精确的比较值,并且在 Eclipse 中我可以显示比较窗口。
所以在代码中我有返回 BigDecimal 的方法,四舍五入到小数点后 2 位。 在测试用例中,我现在返回没有非零十进制数字的数字。所以我想创建比例为 0 的 BigDecimal 并将返回的 BigDecimal 修剪为相同的比例。
为了更复杂,我现在有方法 getDecimal(Object [,Optionaly int scale]) 从任何具有正确 toString() 值且默认比例为 99 的对象创建 BigDecimal。我在主要的“重”代码中使用它,所以这个方法必须非常快(不需要创建另一个对象,不要使用正则表达式等)。
这么简单的问题是:如何修改 BigDecimal 实例以通过最小负载修剪结束的十进制零。
想要这样的srip
0.010 -> 0.01
5.000 -> 5
100 -> 100 not 1E+2
回复:
someTrim(new BigDecimal("100.00")).equals(new BigDecimal(100))
做数学之类的事情
100.00 / (2, 99, DOWN) * 50.00 -> 2500
我的代码看起来像
public static BigDecimal getDecimal( Object value ) {
// null here probably work beter, but dont want number longer then 99 decimal digits
return getDecimal( value, 99 );
}
public static BigDecimal getDecimal( Object value, Integer scale ) {
if ( value == null )
return null;
BigDecimal result = ( value instanceof BigDecimal ) ? ( BigDecimal ) value : new BigDecimal( value.toString() );
if ( scale == null )
return result;
return result.setScale( scale, DOWN );
}
// Main heavy method could call this 100 000 times per tenant (cca 1500 tenants), of course not expect all in same time, but can severals
public static myModify(E entity){
return myModify( entity.getValue(), entity.getDivisor(), entity.getMultiplicator() );
}
public static myModify( BigDecimal value, Integer divisor, BigDecimal multiplicator){
return value.divide( getDecimal(divisor), 99, RoundingMode.DOWN ).multiply( multiplicator );
}
@Test
public void myModifyTest(){
// Constructor have param: value, divisor, multiplicator
E entity = new E(new BigDecimal("100.00"), 2, new BigDecimal("50.00"));
// Should pass
Assert.assertEquals(getDecimal(100), entity);
// Should drop: java.lang.AssertionError: expected:<50> but was:<100>
Assert.assertEquals(getDecimal(50), entity);
// Not want: java.lang.AssertionError: expected:<5E+1> but was:<1E+2>
}
也许存在另一个junit比较方法,它会抛出同样的错误,但我不知道
感谢您的帮助。帕维尔
【问题讨论】:
-
这段代码非常脆弱。您应该编写两个
getDecimal方法,一个采用BigDecimal,另一个采用String。然后您将大大简化您的代码,并减少可能出现的错误。 -
BigDecimals 最好在未缩放时使用,除非转换为不同的类型。您不应该将代码限制为任意小数位数。你也应该使用
compareTo()而不是equals()。 -
对,更好。但不确定 PostgeSql 中的 Numeric 可以有多大,并且我们在 java 中的大多数数字都限制为精度 (17,2) 和 (15,2)。几个(?,4),所以由于乘法/除法运算,我需要一些小数保留,但不一定要有所有数字(不确定粗麻布如何处理序列化->传输多少数据)
-
创建更多带有必要参数的方法会起作用,可能没有错误更好,但是对于每个原始类型 + 所有其他数字类型 + 所有 CharSequence 类型都有方法看起来并不好
-
您只需要 long、double 和 String -- 其他所有内容都可以由 lib 的用户转换或由 jvm 自动转换。那是 3 种方法——几乎没有矫枉过正。另外,你并不真的需要这些方法——就像我说的那样,你不应该担心内部的有效数字,直到你需要以某种方式输出一个值,然后你应该舍入/截断它。例如。如果您进行除法,然后将结果乘以一个非常大的数字,则数字会根据被乘数的大小变得重要,过早截断数字可能会改变结果。