Sign in with
Sign up | Sign in
Your question

Beginner JAVA arithmetics help

Last response: in Apps General Discussion
Share
March 12, 2012 1:14:49 PM

Hello.
I`m a beginner to JAVA.
Have an exercise to write a program that converts money sum to number of bills and coins and prints it. f.e.:
47.63 =
4 ten dollar bills
1 five dollar bills
2 one dollar bills
2 quarters
1 dimes
0 nickles
3 pennies

I wrote it in different ways but the MONEY value seems to lose precision after arithmetic operations on it.

whether I do it like that :

DOLLAR_100 = (int) MONEY / 100;
MONEY = MONEY % 100;

or even without changing the value of money:
DOLLAR_100 = (int) MONEY /100;
DOLLAR_50 = (int) MONEY %100 / 50;

It loses precision as seen in the images.




Please help,
Thanks in advance,
Yakov

More about : beginner java arithmetics

March 12, 2012 3:39:01 PM

sorry can't see images.

to work with java, always convert all variables to double before the operation.

if any variable is int the precision will be lost.

double DOLLAR_100 = (double) MONEY /100;
m
0
l
March 12, 2012 9:35:14 PM

ricardois said:
always convert all variables to double before the operation.

if any variable is int the precision will be lost.

double DOLLAR_100 = (double) MONEY /100;


Even if I call it a double (and add .00 to the divider), it loses precision.

double MONEY, DOLLAR_100;

Scanner Scan = new Scanner (System.in);

System.out.print ("Enter the monetary amount in xx.xx: ");
MONEY = Scan.nextDouble();

DOLLAR_100 = MONEY / 100.00;
MONEY = MONEY % 100.00;
System.out.println ("Hundred dollar bills: " + (int) DOLLAR_100);
System.out.println ("Money left: " + MONEY);

By saying loses precision I mean that the result looks like that :

Enter the monetary amount in xx.xx: 100.11
Hundred dollar bills: 1
Money left: 0.10999999999999943

WHY 0.109999999... money left, why not 0.11. The greater the number the worse it becomes.
m
0
l
Related resources
a b L Programming
March 13, 2012 10:50:42 AM

Because the result of 100.11 % 100 is a number that cannot be precisely represented as a double precision (64-bit) floating-point number, therefore it is rounded to give an approximate value. For financial calculations, you might want to look at java.math.BigDecimal

The problem can be most simply understood by trying to write out the precise decimal representation of 1/3. No amount of paper and ink in the universe will allow you to do so, although you will be able to get (theoretically, and if you don't get RSI from all the writing) infinitely close.
m
0
l
March 13, 2012 11:43:49 AM

just like randomizer said you could try BigDecimal:

BigDecimal hundred = BigDecimal.valueOf(100);
BigDecimal MONEY, DOLLAR_100;

Scanner Scan = new Scanner (System.in);

System.out.print ("Enter the monetary amount in xx.xx: " );
MONEY = BigDecimal.valueOf(Scan.nextDouble());

DOLLAR_100 = MONEY.divide(hundred);
MONEY = MONEY.remainder(hundred);
System.out.println ("Hundred dollar bills: " + DOLLAR_100.toBigInteger());
System.out.println ("Money left: " + MONEY);

m
0
l
March 13, 2012 8:19:18 PM

1. Even if I cast convert " (int) MONEY " then %100 it does that.
Then it`s like saying:
MONEY = 107.11%
(int) MONEY %100 is like 107% 100 still get the problem at the end.

2. It`s an exercise from a book and it hasn`t introduced the BigDecimal.valueOf method yet. Only Byte - Double, conversions and basic arithmetics + - / * %.

3. Here`s a version of a full program and it`s results:

import java.util.Scanner;

public class TRY
{
public static void main (String[] args)
{
double MONEY, QUARTERS, DIMES, NICKELS, PENNIES;
int DOLLAR_100, DOLLAR_50, DOLLAR_20, DOLLAR_10, DOLLAR_5, DOLLAR_1;

Scanner Scan = new Scanner (System.in);

System.out.print ("Enter the monetary amount in xx.xx: ");
MONEY = Scan.nextDouble();

DOLLAR_100 =MONEY /100;
DOLLAR_50 = MONEY %100 / 50;
DOLLAR_20 = MONEY %100 %50 / 20;
DOLLAR_10 = MONEY %100 %50 % 20 /10;
DOLLAR_5 = MONEY %100 %50 %20 %10 /5;
DOLLAR_1 = MONEY %100 %50 %20 %10 %5;
QUARTERS = MONEY %100 %50 %20 %10 %5 %1 /0.25;
DIMES = MONEY %100 %50 %20 %10 %5 %1 %0.25 /0.10;
NICKELS = MONEY %100 %50 %20 %10 %5 %1 %0.25 %0.10 /.05;
PENNIES = MONEY %100 %50 %20 %10 %5 %1 %0.25 %0.10 %.05 /.01;

System.out.println (DOLLAR_100 + " hundred dollar bills");
System.out.println (DOLLAR_50 + " fifty dollar bills");
System.out.println (DOLLAR_20 + " twenty dollar bills");
System.out.println (DOLLAR_10 + " ten dollar bills");
System.out.println (DOLLAR_5 + " five dollar bills");
System.out.println (DOLLAR_1 + " one dollar bills");
System.out.println ((int) QUARTERS + " quarters");
System.out.println ((int) DIMES + " dimes");
System.out.println ((int) NICKELS + " nickels");
System.out.println ((int) PENNIES + " pennies");
System.out.println ("Money left after % by 100: " + MONEY %100 );
}
}

RESULT:

Enter the monetary amount in xx.xx: 101.11
1 hundred dollar bills
0 fifty dollar bills
0 twenty dollar bills
0 ten dollar bills
0 five dollar bills
1 one dollar bills
0 quarters
1 dimes
0 nickels
0 pennies
Money left after % by 100: 1.1099999999999994

No pennies?
Money left after % by 100 is 1.10999999... ?
m
0
l
March 14, 2012 2:35:07 AM

instead of double use float, this is a common problem with programming the value is not exacly due to binary operations being different in each type. with float i think you get "closer" to your wanted result.


this worked...

import java.util.Scanner;

public class Test {
public static void main(String[] args) {
float MONEY, QUARTERS, DIMES, NICKELS, PENNIES;
int DOLLAR_100, DOLLAR_50, DOLLAR_20, DOLLAR_10, DOLLAR_5, DOLLAR_1;

Scanner Scan = new Scanner(System.in);

System.out.print("Enter the monetary amount in xx.xx: ");
MONEY = Scan.nextFloat();

DOLLAR_100 = (int) (MONEY / 100);
DOLLAR_50 = (int) (MONEY % 100 / 50);
DOLLAR_20 = (int) (MONEY % 100 % 50 / 20);
DOLLAR_10 = (int) (MONEY % 100 % 50 % 20 / 10);
DOLLAR_5 = (int) (MONEY % 100 % 50 % 20 % 10 / 5);
DOLLAR_1 = (int) (MONEY % 100 % 50 % 20 % 10 % 5);
QUARTERS = (float) (MONEY % 100 % 50 % 20 % 10 % 5 % 1 / 0.25);
DIMES = (float) (MONEY % 100 % 50 % 20 % 10 % 5 % 1 % 0.25 / 0.10);
NICKELS = (float) (MONEY % 100 % 50 % 20 % 10 % 5 % 1 % 0.25 % 0.10 / .05);
PENNIES = (float) (MONEY % 100 % 50 % 20 % 10 % 5 % 1 % 0.25 % 0.10
% .05 / .01);

System.out.println(DOLLAR_100 + " hundred dollar bills");
System.out.println(DOLLAR_50 + " fifty dollar bills");
System.out.println(DOLLAR_20 + " twenty dollar bills");
System.out.println(DOLLAR_10 + " ten dollar bills");
System.out.println(DOLLAR_5 + " five dollar bills");
System.out.println(DOLLAR_1 + " one dollar bills");
System.out.println((int) QUARTERS + " quarters");
System.out.println((int) DIMES + " dimes");
System.out.println((int) NICKELS + " nickels");
System.out.println((int) PENNIES + " pennies");
System.out.println("Money left after % by 100: " + MONEY % 100);
}
}
m
0
l
March 14, 2012 8:39:53 AM

Thanks, it was more accurate up to 255.
However the book states explicitly:
"
Write an application that prompts for and reads a double value
representing a monetary amount. Then determine the fewest
number of each bill and coin needed to represent that amount,
starting with the highest (assume that a ten-dollar bill is the maxi-mum size needed). For example, if the value entered is 47.63
(forty-seven dollars and sixty-three cents), then the program
should print the equivalent amount as:

4 ten dollar bills
1 five dollar bills
2 one dollar bills
2 quarters
1 dimes
0 nickles
3 pennies
"
While reading that again I thought - maybe the book wants me to read values of up to 49.99$ : " (assume that a ten-dollar bill is the maxi-mum size needed) ". I thought it was just an example, but maybe not.

Considering you code , I proposed with myself that the "breaking point" might be at 256. And I found it actually was.
I don`t really know why but I can think it might be related to the "256-bit" in the JAVA / machine language.

Enter the monetary amount in xx.xx: 255.11
2 hundred dollar bills
1 fifty dollar bills
0 twenty dollar bills
0 ten dollar bills
1 five dollar bills
0 one dollar bills
0 quarters
1 dimes
0 nickels
1 pennies
Money left after % by 100: 55.11000061035156

BUT:

Enter the monetary amount in xx.xx: 256.11
2 hundred dollar bills
1 fifty dollar bills
0 twenty dollar bills
0 ten dollar bills
1 five dollar bills
1 one dollar bills
0 quarters
1 dimes
0 nickels
0 pennies
Money left after % by 100: 56.1099853515625
m
0
l
March 14, 2012 10:51:10 AM

Try that one, using DOUBLE and using Math.Round for the right number Round value;

public class TRY{
public static void main(String[] args) {

double MONEY, QUARTERS, DIMES, NICKELS, PENNIES;
int DOLLAR_100, DOLLAR_50, DOLLAR_20, DOLLAR_10, DOLLAR_5, DOLLAR_1;

Scanner Scan = new Scanner(System.in);

System.out.print("Enter the monetary amount in xx.xx: " );
MONEY = Scan.nextFloat();

DOLLAR_100 = (int) (MONEY / 100);
DOLLAR_50 = (int) (MONEY % 100 / 50);
DOLLAR_20 = (int) (MONEY % 100 % 50 / 20);
DOLLAR_10 = (int) (MONEY % 100 % 50 % 20 / 10);
DOLLAR_5 = (int) (MONEY % 100 % 50 % 20 % 10 / 5);
DOLLAR_1 = (int) (MONEY % 100 % 50 % 20 % 10 % 5);
QUARTERS = Math.round( (MONEY % 100 % 50 % 20 % 10 % 5 % 1 / 0.25));
DIMES = Math.round((MONEY % 100 % 50 % 20 % 10 % 5 % 1 % 0.25 / 0.10));
NICKELS = Math.round((MONEY % 100 % 50 % 20 % 10 % 5 % 1 % 0.25 % 0.10 / .05));
PENNIES = Math.round((MONEY % 100 % 50 % 20 % 10 % 5 % 1 % 0.25 % 0.10
% .05 / .01));

System.out.println(DOLLAR_100 + " hundred dollar bills" );
System.out.println(DOLLAR_50 + " fifty dollar bills" );
System.out.println(DOLLAR_20 + " twenty dollar bills" );
System.out.println(DOLLAR_10 + " ten dollar bills" );
System.out.println(DOLLAR_5 + " five dollar bills" );
System.out.println(DOLLAR_1 + " one dollar bills" );
System.out.println((int) QUARTERS + " quarters" );
System.out.println((int) DIMES + " dimes" );
System.out.println((int) NICKELS + " nickels" );
System.out.println((int) PENNIES + " pennies" );
System.out.println("Money left after % by 100: " + MONEY % 100);
}
}
m
0
l
a b L Programming
March 14, 2012 11:08:06 AM

Rounding is going to be necessary if you're using a double. Since cash is only ever precise to 2 decimal places this is fine. You always round with cash in the real world.
m
0
l
a b L Programming
March 16, 2012 10:43:00 AM

Not in banking randomizer otherwise plenty of money would go missing from rounding errors. So in the real world 2 decimal places is not good enough but ok for this program.

Also ricardois you should take a look at Java coding conventions because there is no way you should be giving a beginner examples where variable names are capitalised.
m
0
l
March 19, 2012 3:41:04 PM

Yes that Math.round solved the problem for rounding Ricardo, but the book hasn`t introduced this method yet. As I mentioned, my proposition is that the book meant up to 10$ bills :
"Write an application that prompts for and reads a double value
representing a monetary amount. Then determine the fewest
number of each bill and coin needed to represent that amount,
starting with the highest (assume that a ten-dollar bill is the maxi-mum size needed)."
Because up to 255 the problem won`t occure, as the amount is not large enough to corrupt the .00 digits.
Thanks all for the help.
m
0
l
!