[SOLVED] Rounding floats

Hello to all jmonkey users,
I have one question for you. Is there a way to round float numbers?
My problem is: Money which I have in game is float value and it’s showing numbers on hundredth (for dummies like me: it’s looking like 5.40). And now if I add 20 cents (0.20f) to wallet, value goes 5.60004. This is what nobody wants. I just want only hundredths, not more zeros.
Code that causes it:

 money += 0.2f;

Thank for any advices.

If your currency has atomic values (like everything can be expressed as multiple of 1 Cent, use an Integer and divide by 100.

You can round Floats to n Decimals by using round and some multiplication though, just google for that

1 Like

This is Java after all, so there are approximately 2,000 ways to do that.
You could do:

String.format("%.2f", money);

Option 2:

(double)Math.round(money * 100d) / 100d

Option 3:

DecimalFormat d = new DecimalFormat("#.##");
d.format((double)money)

I’m no java expert, so I don’t know which one is best, or which one is fastest. I’d recommend testing a couple thousand runs of each to test for speed.

However, the reason you are seeing the extra 0.00004 in the float, is due to floating point precision. You will see this come up in all forms of computer stuff and if you don’t know whats going on, it’s going to be pretty confusing. If you want precision, it may be better to use java’s BigDecimal instead.

3 Likes

Java cant do arithmetic of doubles or floats accurately.
Add ten pennies (.01) together and see what you get.

Use BigDecimal and strings or the easy way and do what Darkchaos said.

Edit: changed the improper use of the word add to arithmetic to clarify.

What @Darkchaos said is usually the best option. Using a long or simmilar with 100x multiplier and format when needed to output with DecimalFormat.

Here’s what I use (well, approximatelly) to format my bank account label so it keeps the zero places behind the dot at all times as well:

	DecimalFormatSymbols sy = new DecimalFormatSymbols(Locale.US); //otherwise you may get a comma in some countries, ruining your gui placement lol
	sy.setDecimalSeparator('.');
	sy.setGroupingSeparator('.'); 
	
	DecimalFormat pts4 = new DecimalFormat("#.######",sy);

	String cash = pts4.format(value/10000d);
	if(!cash.contains("."))
		cash = cash+"."; //keep the decimal places at all times
	
	if(value >= 0)
		while(cash.length() < 6)
			cash = cash+"0";
	else // Negative values have an extra "-" character which we have to account for
		while(cash.length() < 7)
			cash = cash+"0";
	return cash;

I’ve set it to keep 6 decimals, because cryptocurrency. You’d only need 3.

Thank you for your all advices. I was looking for something very light. Now it seems to work one of 8Keep123’s methods.

I change it little bit to:

money = (float)Math.round(money * 100f) / 100f;

Now it is working perfectly :slight_smile:

@Darkchaos’s Integer dividing works longer then my floats, but again a lot of zeros and number two in the end appeared.

The most common practise with money handling is to use integer as computation is lighter than using float.
And then for display purpose, make sure are only showing two decimal values.

2 Likes

well, using integers won’t solve that problem. It does however solve a bigger one : Not having to deal with float impressions.
You said that adding 20 cents (0.20f) to a wallet containing 5.40 caused it to contain 5.60004.
That means that the user suddenly has 0.00004 more. This may not look like a problem but it means that every time you want to do something with the money of a player you have a chance to add extra or maybe remove money from him. And though you can round it now, maybe you will eventually get an error that is so big that rounding won’t solve it.

Additionally that means that you need to round it every time you want to do something with it, forget it once and you are in trouble.

To fix all of this you just simply store the money internally as integers. Then only when you want to display the values you need to worry about rounding it and even if there is an error shown due to floats it is only in what the user sees and thus won’t result in an exploit that can result in infinite money.

You have true that work with Integer is better. But I failed in rounding Integer again because dividing Integer by 100 isn’t possible. You actually can make an Integer with two zeros behind point, mult it by * 0.01, but there a lot of inaccuracy are made.

pretty sure that something like

int money = 123; //the amount someone has
float displayMoney = (float)money/100; //the value that you want to display

should work. I don’t work often with java so syntax may contain issues but I hope you get the idea. Just cast the int to a float while you are dividing.

1 Like

Yeaa, I get the idea. Thank to all who wrote :slight_smile:

1 Like