# Beginner JAVA arithmetics help

#### ZKR

##### Honorable
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.

Yakov

#### ricardois

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

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
Moderator
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
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
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
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
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
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);
}
}

#### randomizer

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

#### Rusting In Peace

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

#### ZKR

##### Honorable
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.

Apps General Discussion 23
Apps General Discussion 2
Apps General Discussion 2
Apps General Discussion 3
G Apps General Discussion 14
Apps General Discussion 1
Apps General Discussion 9
Apps General Discussion 6
Apps General Discussion 8
Apps General Discussion 4
Apps General Discussion 1
Apps General Discussion 3
Apps General Discussion 4
Apps General Discussion 3
Apps General Discussion 8
Apps General Discussion 3
Apps General Discussion 0
Apps General Discussion 0
Apps General Discussion 0
Apps General Discussion 3