【问题标题】:Best method to round up to the nearest 0.05 in java在java中四舍五入到最接近的0.05的最佳方法
【发布时间】:2012-08-05 08:51:54
【问题描述】:

考虑到 10% 的税适用于除食品以外的所有物品。此外,对进口商品征收 5% 的附加税。

如果音乐 CD 的成本是 12.49。该项目的税为 1.499。 如果一瓶进口香水的成本是 47.50,则该物品的税为 7.125

有一项政策规定,一件商品的税款应四舍五入到最接近的 0.05。因此,1.499 应四舍五入为 1.5,7.125 应四舍五入为 7.25。

上述四舍五入的要求可以通过以下逻辑实现:

    (float) Math.ceil(taxAmount / 0.05f) * 0.05f;

将税收添加到物品的成本中:

音乐 CD:12.49 + 1.5 = 13.99 进口巧克力盒:47.50 + 7.25 = 54.65。

我面临以下输入的问题:

如果进口一盒巧克力的成本是11.85,那么税就是0.5925

使用四舍五入政策,四舍五入后的税金为0.6。

当我们添加 11.85 + 0.6 这两个浮点数时,我们得到的结果是 12.450001。与其他输入不同,此特定输入提供了很多小数位,而不是其他输出中的 2 个小数位。

我尝试使用 BigDecimal 而不是 float 来存储所有数值,并将刻度设置为 2 位小数。这种方法的问题在于,如果未指定舍入策略,bigDecimal 将在某些情况下抛出异常。为 BigDecimal 提供舍入策略会导致使用提供给 BigDecimal 的舍入策略对项目成本和适用税费的总和进行舍入,从而改变所需的输出。

【问题讨论】:

  • 回复:BigDecimal 的“问题”,是的,提供舍入策略的全部意义在于应该使用它。显然它会改变结果。您的问题很可能是您提供了错误的政策。
  • AFAIK,BigDecimal 提供的所有政策都不符合我的要求。
  • 您是否使用了正确的缩放比例?如果你是,那么 ROUND_HALF_XXX 模式之一就是你想要的。
  • 我使用的是 2 的比例。正确吗?
  • 令人惊讶的是,使用任何 ROUND_HALF_XXX 方法和 2 的比例都可以解决问题。

标签: java bigdecimal rounding


【解决方案1】:

您可以使用long 而不是double 来使用您可以做到的双倍

double d = Math.round(d * 20) / 20.0; // round up to multiple of 0.05

使用多头(如美分)

long l = (l + 3) / 5 * 5;

尽管使用intlongBigDecimal 通常被认为是最佳实践,但大多数投资银行和基金使用double,因为一旦您了解如何安全使用它们,它们会更简单(比长)和更快(比 BigDecimal)来使用。

【讨论】:

  • 如何从 long 转换回 float 并知道小数点的确切位置?输出需要以十进制而不是长显示。
  • 我假设一美元有 100 美分。即在打印之前除以 100.0 即可。就个人而言,我对使用双精度没有问题。除非真的别无选择,否则我不会使用float
  • 要将十进制值转换为 long 或 int,我必须将其乘以 100?商品价格小数点后多于两位怎么办?
  • 这是什么意思:once you understand how to use them safely?如何安全使用它们?
  • 我对“大多数投行和基金使用双重”的说法提出质疑。请提供一些证据。
【解决方案2】:

将货币金额存储为整数(例如美分)。

这是一个常见的问题 - 谷歌会给你很多很好的解释。

这是一个:Why not use Double or Float to represent currency?

【讨论】:

  • 这更像是一个回答如何。否则它更像是一个评论。
  • 怎么做?如何使用整数来存储货币金额?
  • 如何Best method to round up to the nearest 0.05 in java
  • 我的观点是,在担心关于舍入的原始问题之前,OP 的代码中有一个基本问题需要纠正。不确定评论是否有足够的分量来传达这一点。
  • 没错,但指出它的容易程度也可能会有所帮助。 ;)
【解决方案3】:

这似乎是一个著名的技术面试问题的一部分 关键是要了解您必须计算税款并将该金额四舍五入到上限 0.05 为了计算舍入,我使用了这个 groovy 脚本

import java.math.*

def myRound(BigDecimal d){ 
    def scale = new BigDecimal("0.05")
    def y = d.divide(scale)
    println "y :$y"
//    def q = y.round(new MathContext(0,RoundingMode.UP))
    def q = y.setScale(0,BigDecimal.ROUND_UP)
    println "q :$q (intero)"
    def z = q.multiply(scale)
    println "z :$z"
    return z
}

def taxBy(BigDecimal d,BigDecimal t){ 
    return myRound(d.multiply(t))
}
def importTax(BigDecimal d){ 
    return taxBy(d,new BigDecimal("0.15"))
}

def importBaseTax(BigDecimal b){ 
    return taxBy(d,new BigDecimal("0.05"))
}

ip = new BigDecimal("27.99")
ipt = importTax(ip)

println "${ip}-->${ipt} = ${ip+ipt}"

希望对你有用!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-20
    • 1970-01-01
    • 2012-04-22
    相关资源
    最近更新 更多