Java BigDecimal与The Financial Mans – “1美分问题”

我有这个问题: 财务人员说:“你的程序错误”

财务的官方价值表和最终计算表是

基数%总值667.63  -  1.5(0.015)= 657.62 705.98  -  1.5(0.015)= 695.39 687.77  -  1.5(0.015)= 677.45 844.62  -  1.5(0.015)= 831.95 743.23  -  1.5(0.015)= 732.08 775.15  -  1.5(0.015) = 763.52 874.82  -  1.5(0.015)= 861.70 949.63  -  1.5(0.015)= 935.39 987.18  -  1.5(0.015)= 972.37 1040.28  -  1.5(0.015)= 1024.68 1077.70  -  1.5(0.015)= 1061.54 995.68  -  1.5(0.015)= 980.74 1280.55  -  1.5(0.015)= 1261.35 1140.56  -  1.5(0.015)= 1123.45 653.23  -  1.5(0.015)= 643.43 847.49  -  1.5(0.015)= 834.78 995.68  -  1.5(0.015)= 980.74 

我的函数的返回值必须与该表中的总值匹配:

public static void main(String[] args) { BigDecimal[] valorbase= { new BigDecimal("667.63"), new BigDecimal("705.98"), new BigDecimal("687.77"), new BigDecimal("844.62"), new BigDecimal("743.23"), new BigDecimal("775.15"), new BigDecimal("874.82"), new BigDecimal("949.63"), new BigDecimal("987.18"), new BigDecimal("1040.28"), new BigDecimal("1077.70"), new BigDecimal("995.68"), new BigDecimal("1280.55"), new BigDecimal("1140.56"), new BigDecimal("653.23"), new BigDecimal("847.49"), new BigDecimal("995.68") }; for (int i = 0; i < valorbase.length; i++) { BigDecimal desconto=new BigDecimal("0.015"); BigDecimal valor_a_descontar=valorbase[i].multiply(desconto); valor_a_descontar=valor_a_descontar.setScale(2,RoundingMode.HALF_UP); //desconto=desconto.setScale(2,RoundingMode.HALF_UP); BigDecimal valortotal=valorbase[i].subtract(valor_a_descontar); valortotal.setScale(3,RoundingMode.HALF_UP); valortotal.setScale(2,RoundingMode.HALF_UP); System.out.println("BASE=" + valorbase[i] + " - descount=" + valor_a_descontar + " totalvalue=" + valortotal); } } 

系统输出: BASE=1077.70 - descount=16.17 totalvalue=1061.53 missing value of table! BASE=1280.55 - descount=19.21 totalvalue=1261.34 missing value of table! BASE=1077.70 - descount=16.17 totalvalue=1061.53 missing value of table! BASE=1280.55 - descount=19.21 totalvalue=1261.34 missing value of table!

差异在某些情况下为0.01美分,但对金融来说这是不可能的因为这个宇宙的人是18.340注册表的差异是18340 x 0.01 x 365 x 2 = 4401,6 ===> R $ 4401,6这个成本一分钱不正确! 谁能帮我? 谢谢JAY ……这是由JAY提出的:

 public static void main(String[] args){ BigDecimal[] valorbase= { new BigDecimal("667.63"), new BigDecimal("705.98"), new BigDecimal("687.77"), new BigDecimal("844.62"), new BigDecimal("743.23"), new BigDecimal("775.15"), new BigDecimal("874.82"), new BigDecimal("949.63"), new BigDecimal("987.18"), new BigDecimal("1040.28"), new BigDecimal("1077.70"), new BigDecimal("995.68"), new BigDecimal("1280.55"), new BigDecimal("1140.56"), new BigDecimal("653.23"), new BigDecimal("847.49"), new BigDecimal("995.68") }; for(int i=0;i=1){ valortotal=valortotal.setScale(8,RoundingMode.HALF_UP); valortotal=valortotal.setScale(7,RoundingMode.HALF_UP); valortotal=valortotal.setScale(6,RoundingMode.HALF_UP); valortotal=valortotal.setScale(5,RoundingMode.HALF_UP); valortotal=valortotal.setScale(4,RoundingMode.HALF_UP); valortotal=valortotal.setScale(3,RoundingMode.HALF_UP); valortotal=valortotal.setScale(2,RoundingMode.HALF_UP); }else{ valortotal=valortotal.setScale(2,RoundingMode.HALF_UP); } System.out.println("BASE="+valorbase[i]+" totalvalue="+valortotal); } } 

基于周杰伦的想法,我做了一些修改,金融家伙说:“好吧,我们永远不能对客户给予折扣。我们需要一些时间来解决这个问题。”

谢谢大家!…

您确定使用的是适当的RoundingMode吗? RoundingMode 1是ROUND_DOWN ,RoundingMode 5是ROUND_HALF_DOWN 。 也许您应该使用ROUND_HALF_EVEN (这在某些财务方案中很常见)?

此外,如果您使用这些枚举常量而不是RoundingMode.valueOf方法,代码将更清晰。

你总是会遇到有关这些问题的确切舍入规则的问题。

比如,我们在减法之前或之后进行舍入。 此外,您可能会说,作为捷径,1.5%的折扣与我们收取98.5%的正常价格相同,因此我们应该能够将原价格乘以98.5%而不必进行额外的减法。 对?

假设价格是667.00。

方法1:667.00 * .015 = 10.005,向上舍入到10.01。 然后667.00 – 10.01 = 656.99。

方法2:667.00 * .015 = 10.005。 667.00 – 10.005 = 656.995。 最高可达657.00。 不同的答案。

方法3:667.00 * .985 = 656.995,最高可达657.00。

此外,Roney提到1077.70的表格是错误的。 1280.55也是错误的。