Beginner JAVA arithmetics help

Status
Not open for further replies.

ZKR

Honorable
Mar 12, 2012
35
0
10,580
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
 

ricardois

Distinguished
Dec 21, 2011
14
0
18,570
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;
 

ZKR

Honorable
Mar 12, 2012
35
0
10,580


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.
 

randomizer

Distinguished
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.
 

ricardois

Distinguished
Dec 21, 2011
14
0
18,570
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);

 

ZKR

Honorable
Mar 12, 2012
35
0
10,580
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... ?
 

ricardois

Distinguished
Dec 21, 2011
14
0
18,570
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);
}
}
 

ZKR

Honorable
Mar 12, 2012
35
0
10,580
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
 

ricardois

Distinguished
Dec 21, 2011
14
0
18,570
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);
}
}
 

ZKR

Honorable
Mar 12, 2012
35
0
10,580
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.
 
Status
Not open for further replies.