如何在Java中自定义舍入模式?
How to customize rounding mode in Java?
我正试图在 Java 中四舍五入。我将它发送到定义了一些舍入参数的 Fiscal 打印机。
有一个数字定义小数位数...例如x = 0.0100;
第二个数字是舍入的一些系数。例如y = 0.0050;所有大于 0.0050 的都应四舍五入为 0.01 所有小于 0.0050 的应四舍五入为 0.00。 BigDecimal 不是解决方案,因为这个数字定义了舍入模式。
在打印机的文档中,我有一些 table 带有舍入数字的示例...
- 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" ...我尝试了一些解决方案,但对于某些变量组合,我仍然得到错误的值。
我也检查了这个,但效果不佳...
尝试将 0.0050 添加到数字中。逻辑是,如果它小于 0.50,则将保持小于 1,当切碎时,其余部分将自动变为 0。如果更大,将高于 1,所以当切碎时,将保持 1。
这匹配除 x = 0.0100; y = 0.0100
以外的所有示例,其中 returns 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
示例)
在没有解释为什么第三个示例不一致的情况下,这是我所能得到的最接近的结果。仅为该示例添加 special-case 代码可能无法准确反映其背后的规则,并且可能会为相似的值提供错误的结果。
另请注意,在与金钱打交道时切勿使用浮点 (float/double) 值,误差会很快累积。 BigDecimal
实例应直接从值的 String
创建,并且应使用 DecimalFormat
.
将它们转换回 String
我做了这样的功能...值似乎没问题,但仍然有一个错误... x = 0.0100; y = 0.0100; 15.0009 = 15.01 应该是15.00
@SeanVanGorder 创建的代码不是很好,因为如果 x = 0.0200 ... 值是错误的。我的函数使得 x = 0.0200; y = 0.0030; 15.2241 = 15.24 应该是这样的...四舍五入到第一个 2.
Return 类型是 double,因为我没能用 BigDecimal 对变量 x 进行良好的舍入。我将只使用 return 值来写入打印机,所以浮点数等不应该有问题,但如果有人知道解决方案,请随时 post 它。这可能是我做的最好的解决方案,但它仍然不是 100% 好。
更新: 我更新了代码...现在它与 BigDecimal 完全兼容,它可能是解决这个问题的最佳方法。我给打印机制造商写了一封电子邮件,得到的回复与程序员手册中的描述相冲突。所以,这不是 100% 好的解决方案,一个值仍然是错误的 value = 15.0009; x = 0.0100; y = 0.0100;
应该是 15.00
(手动),但是制造商写了 15.01
而我的代码 returns 15.01
.
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(他的代码也帮助了我)
我正试图在 Java 中四舍五入。我将它发送到定义了一些舍入参数的 Fiscal 打印机。
有一个数字定义小数位数...例如x = 0.0100; 第二个数字是舍入的一些系数。例如y = 0.0050;所有大于 0.0050 的都应四舍五入为 0.01 所有小于 0.0050 的应四舍五入为 0.00。 BigDecimal 不是解决方案,因为这个数字定义了舍入模式。
在打印机的文档中,我有一些 table 带有舍入数字的示例...
- 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" ...我尝试了一些解决方案,但对于某些变量组合,我仍然得到错误的值。
我也检查了这个,但效果不佳...
尝试将 0.0050 添加到数字中。逻辑是,如果它小于 0.50,则将保持小于 1,当切碎时,其余部分将自动变为 0。如果更大,将高于 1,所以当切碎时,将保持 1。
这匹配除 x = 0.0100; y = 0.0100
以外的所有示例,其中 returns 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
示例)
在没有解释为什么第三个示例不一致的情况下,这是我所能得到的最接近的结果。仅为该示例添加 special-case 代码可能无法准确反映其背后的规则,并且可能会为相似的值提供错误的结果。
另请注意,在与金钱打交道时切勿使用浮点 (float/double) 值,误差会很快累积。 BigDecimal
实例应直接从值的 String
创建,并且应使用 DecimalFormat
.
String
我做了这样的功能...值似乎没问题,但仍然有一个错误... x = 0.0100; y = 0.0100; 15.0009 = 15.01 应该是15.00
@SeanVanGorder 创建的代码不是很好,因为如果 x = 0.0200 ... 值是错误的。我的函数使得 x = 0.0200; y = 0.0030; 15.2241 = 15.24 应该是这样的...四舍五入到第一个 2.
Return 类型是 double,因为我没能用 BigDecimal 对变量 x 进行良好的舍入。我将只使用 return 值来写入打印机,所以浮点数等不应该有问题,但如果有人知道解决方案,请随时 post 它。这可能是我做的最好的解决方案,但它仍然不是 100% 好。
更新: 我更新了代码...现在它与 BigDecimal 完全兼容,它可能是解决这个问题的最佳方法。我给打印机制造商写了一封电子邮件,得到的回复与程序员手册中的描述相冲突。所以,这不是 100% 好的解决方案,一个值仍然是错误的 value = 15.0009; x = 0.0100; y = 0.0100;
应该是 15.00
(手动),但是制造商写了 15.01
而我的代码 returns 15.01
.
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(他的代码也帮助了我)