如何在Java中自定义舍入模式?

时间:2018-03-23 17:08:43

标签: java currency rounding

我正试图在Java中进行一些舍入。我把它发送到Fiscal打印机,它已经定义了一些舍入参数。

有一个数字定义小数位数...例如 x = 0.0100 ; 第二个数字是舍入的一些系数。例如 y = 0.0050 ;所有大于 0.0050 应四舍五入至 0.01 且所有小于 0.0050 应四舍五入至 0.00 。 BigDecimal不是解决方案,因为这个数字定义了舍入模式。

在打印机的文档中,我有一些表格包含舍入数字的例子......

  • x = 0.0100; y = 0.0001; 15.2241 = 15.23; 15.0009 = 15.01
  • x = 0.0100; y = 0.0010; 15.2241 = 15.23; 15.0009 = 15.00
  • x = 0.0100; y = 0.0100; 15.2241 = 15.23; 15.0009 = 15.00
  • x = 0.0100; y = 0.0040; 15.2241 = 15.23
  • x = 0.0100; y = 0.0041; 15.2241 = 15.23
  • x = 0.0100; y = 0.0042; 15.2241 = 15.22
  • x = 0.1000; y = 0.0100; 15.2241 = 15.30; 0.0010 = 0.00
  • x = 1.0000; y = 0.5000; 15.2241 = 15.00; 0.0010 = 0.00
  • x = 1.0000; y = 0.0010; 15.2241 = 16.00; 0.0010 = 1.00

我试图解决这个问题几个小时,我找不到解决方案。这是我当前的代码...处理带有数字x的小数点。

Math.round(value / x) * x;

我应该如何添加数字“y”...我尝试了一些解决方案,但我仍然会对某些变量组合得到错误的值。

我也检查了这一点,但它没有正常工作...... How to customize the form of rounding

3 个答案:

答案 0 :(得分:1)

这匹配除x = 0.0100; y = 0.0100之外的所有示例,其中15.2241 = 15.22; 15.0009 = 15.00而不是15.23。根据描述,这应该是正确的结果。

static BigDecimal round(BigDecimal val, BigDecimal x, BigDecimal y) {
    BigDecimal remainder = val.remainder(x);
    BigDecimal base = val.subtract(remainder);
    return remainder.compareTo(y) < 0 ? base : base.add(x);
}

(编辑:已更新以处理x = 0.0200示例)

这是我能得到的尽可能接近,但没有解释为什么第三个例子不一致。仅为该示例添加特殊情况代码可能无法准确反映其背后的规则,并且可能会为类似值提供不正确的结果。

另请注意,在处理资金时,绝不应使用浮点(浮点数/双数)值,不准确可能会迅速增加。 BigDecimal个实例应直接从String的值创建,并且应使用String将其转换回DecimalFormat

答案 1 :(得分:0)

我做了这样的功能...值似乎没问题,但仍有一个错误... x = 0.0100; y = 0.0100; 15.0009 = 15.01 应该 15.00

由@SeanVanGorder创建的代码不是很好,因为如果x = 0.0200 ... value是错误的。我的函数使 x = 0.0200; y = 0.0030; 15.2241 = 15.24 ,它应该是这样的...四舍五入到第一个 2

返回类型是double,因为我没有设法使用BigDecimal将变量x依赖于变量x。我将仅使用返回值写入打印机,因此浮点数不应该有问题,但如果有人知道解决方案,请随意发布。这可能是我做的最好的解决方案,但它仍然不是100%罚款。

更新:我更新了代码...现在它完全使用BigDecimal,它可能是解决此问题的最佳解决方案。我给打印机制造商写了一封电子邮件,我得到了一些与程序员手册中的描述相冲突的回复。所以,这不是100%精细的解决方案,而且一个值仍然是错误的value = 15.0009; x = 0.0100; y = 0.0100;应该是15.00(手动),但制造商写了15.01,我的代码返回15.01。< / p>

static BigDecimal roundVaros(BigDecimal value, BigDecimal x, BigDecimal y) {
    BigDecimal a = value.divide(x, RoundingMode.HALF_UP);
    BigDecimal b = y.divide(x, RoundingMode.HALF_UP);

    a = a.subtract(BigDecimal.valueOf(a.longValue()));
    b = b.subtract(BigDecimal.valueOf(b.longValue()));

    if (a.compareTo(b) >= 0) {
        return value.divide(x, RoundingMode.HALF_UP).setScale(0, RoundingMode.CEILING).multiply(x);
    } else {
        return value.divide(x, RoundingMode.HALF_UP).setScale(0, RoundingMode.FLOOR).multiply(x);
    }
}

感谢@SeanVanGoder(他的代码也帮助了我)

答案 2 :(得分:-1)

尝试将此数字添加0.0050。逻辑是,如果它小于0.50则保持小于1,当切断其余时它会自动变为0.如果大于1将如此,因此当切断时将保持为1。