Im doing a monthly payment project and I cant get the dollar amount to go to two decimals. I'm new to coding and dont know if theres something obvious I'm missing here.
Heres my code:
double monthlyP = (1 + monthlyRate);//P = Payment
double power = Math.pow(monthlyP, numMonths);
monthlyP = power * monthlyRate;
double monthlyP2 = power - 1;
double FmonthlyP = (monthlyP/monthlyP2) * principle;//F = final
FmonthlyP = (FmonthlyP * 100)/Math.round(100);
It keeps outputting 1319.0 insted .23. I've tried putting the Math.round in the front of the multiplication part and behind it and I cant get it to work.
Computers use 64 bits to represent a double
. 64-bits, so that can hold exactly 2^64
different values.
Uhoh.
Because there are an infinite number of numbers, that's a big problem. It means that most (in fact, an infinite amount of them) numbers are not representable by double at all. So what does java do? It will simply silently round things to the nearest of the blessed numbers that it can represent.
The upshot of this is that using double
for currency is a big mistake.
Don't do that.
The easy thing to do is to use a long
, and represent the atomic unit for the monetary amount you're working with. cents for dollars and euros. satoshi's for bitcoin.
Your code then does all operations in terms of 'cents' (or satoshis or whatnot). When you 'render' your cents to the user, throw it through a formatting function. Now the whole 'how do I round' issue is moot.
Example formatting function:
public static String printEuro(long cents) {
boolean negative = cents < 0;
if (negative) cents = -cents;
int wholes = cents / 100;
int parts = cents % 100;
return String.format("%s€%d.%02d", negative ? "-" : "", wholes, parts);
}
NB: longs are 64 bit too, but double needs to be able to represent, say, 1e300
, or 0.000123
, and long doesn't. If we're talking euros, a long can cover every amount of cents as long as the total euro amount has 18 digits or less. Even entire country GDPs per century doesn't get that high. If you really need to go that far, try BigInteger
.