如何在Java中对货币值进行四舍五入?

12

好的,这是我的问题。 基本上,我有这个问题。

我有一个数字像.53999999。 如何将其四舍五入到54而不使用任何Math函数?

我猜我必须乘以100来缩放它,然后除以什么吗? 类似这样的东西?


问题出在钱上。假设我有50.5399999美元,我知道如何获得50美元,但我不知道如何获得美分。我可以得到.539999部分,但我不知道如何将其变为54美分。


我建议将标题更改为类似于:“如何在Java中四舍五入货币值?”这样问题更适合搜索答案的人 - 你会得到我的赞成票 ;) - Elijah
10个回答

20
我会使用类似这样的东西:
BigDecimal result = new BigDecimal("50.5399999").setScale(2, BigDecimal.ROUND_HALF_UP);

有一篇很棒的文章叫做使用BigDecimal计算小数点,你应该去JavaWorld看看。


我更喜欢你的第一次回答。 - Sean Bright
BigDecimal确实是答案。 - chburd
第一个答案的交易是什么?:int i = (int) (x + .5) - OscarRyz
我不确定你在问什么?我改变了我的答案,因为问题被编辑了。 - cgreeno

16

您应该使用十进制或货币类型来表示金钱,而不是浮点数。


是的,浮点货币存储在进行一些计算后可能会导致非常糟糕的结果。 - Chris Ballance
4
非常重要!在货币计算中切勿使用浮点数!否则会发生糟糕的事情! - Svante
将货币存储为长整型(以分为单位的数字)。 - basszero
关于零头分(涉及货币百分比的计算可能会产生零头分)。 - Albert
@Albert:大多数货币类型都可以处理这个问题。否则,请使用另一种小数类型或1/100美分的长数字。 - recursive

8

数学与货币比大多数工程师想象的更加复杂(过度概括)

如果你在进行货币计算,我认为你可能会涉及到表面上看起来简单但实际上相当复杂的问题。例如,由业务逻辑决策产生的舍入方法经常会极大地影响计算的总数。

如果这是一份作业,向老师展示你已经思考了现实世界的问题而不仅仅是把一堆代码组合在一起“运行”-肯定会更令人印象深刻。

顺便说一下,我最初想建议查看Java源代码中的Java数学方法的实现,所以我看了一眼。我注意到Java在其舍入方法中使用本机方法-就像它应该做的那样。

然而,BigDecimal显示,Java中有可用于舍入的Java源代码。因此,我建议你查看Java源代码中的BigDecimal私有方法doRound(MathContext mc)。


1
Currency类实际上不执行任何格式化,也不存储任何货币值;它只是保存有关货币属性的一些信息,其中getDefaultFractionDigits()是唯一真正相关的一个(并且在此问题中重复了信息)。 - Andrzej Doyle

7

如果50.54在双精度浮点数中无法表示,则四舍五入也无法解决。

如果你想将50.53999999转换为整数美元和整数美分,请按照以下步骤操作:

double d = 50.539999; // or however many 9's, it doesn't matter
int dollars = (int)d;
double frac = d - dollars;
int cents = (int)((frac * 100) + 0.5);

请注意,最后一步中加0.5是为了将其四舍五入到最接近的整分。如果您希望始终向上舍入,请将其更改为添加0.9999999而不是0.5。

6

问题在于我们还没有涉及到“静态”和“四舍五入”的内容。问题出在钱上。 假设我有50.5399999美元。 我知道如何得到50美元,但我不知道如何得到分。 我可以得到0.539999部分,但我不知道如何将其变成54分。 - Faheed Rahem
我添加了一条关于用Java表示货币的注释。 - Chris Ballance

3
尝试将您的货币存储为分的数量(您可以将其抽象为基本货币单位的数量),使用长整型进行存储。
编辑:由于这是作业,您可能无法控制类型。请将其视为未来项目的教训。
long money = 5054;

long cents = money % 100;
long dollars = money / 100; // this works due to integer/long truncation

System.out.printf("$%d.%02.d", dollars, cents);

1
你需要将数字变为.535并将其与原始数字进行比较,以确定是向上舍入还是向下舍入。以下是如何从.53999999获取.535的方法(适用于任何数字):
num = .53999999;
int_num = (int)(num * 100); // cast to integer, however you do it in Java
compare_num = (int_num + 0.5) / 100;

compare_num 在这种情况下将是 .535。如果 num 大于或等于 compare_num,则向上舍入到 int_num + 1。否则,只需向下舍入到 int_num


对于那些认为“四舍五入”意味着“总是四舍五入”的人...这可能是情况,是的。只需将@Ruten示例中的0.5替换为0.9999999...或否定并向下舍入,然后再否定。 - strager

0

肖恩似乎已经掌握了这个,但是如果你想强制执行适当的规则,那么你可能需要加入一个像这样的 if 语句:

double value = .539999;
int result = (int) (value*100);
if(((value*100)%result)>.5)
    result++;

我希望人们能够评论为什么他们要踩我的代码,我不明白这段代码为什么不被接受... - gnomed
@gnomed: 同意:应该对downvote进行评论。我认为它看起来很好,所以点赞。唯一的改进是将其打包为一个带有传递精度参数的函数。 - Clayton

0

我建议您在将double值四舍五入时使用long。这对于小数没有影响,但可能会有所不同。

double d = 50.539999;
long cents = (long)(d * 100 + 0.5);
double rounded = cents/100;

-1

你到底想做什么?你总是试图去两位数吗?还是无论如何都要修复像99999这样的结尾?

根据评论,实际上是前者:四舍五入到美分。所以确实只需要round(100*a)/100就可以了。(后者会更加复杂...)

最后,如果你只想提取美分部分,以下方法可以实现:

dollars_and_cents = round(100*a)/100
cents = (dollars_and_cents-(int)dollars_and_cents)*100

(或者Java只有frac吗?如果是这样,最后一行就只需要frac(dollars_and_cents)*100。)


我在第一条回复中评论了我要做什么。问题出在钱上。比如说我有50.5399999美元,我知道如何得到50美元,但我不知道如何得到零头。我可以得到0.539999部分,但我不知道如何将其变成54美分。 - Faheed Rahem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接