-1 calculation bug in java [duplicate] - java

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 7 years ago.
I took this problem from an experienced programmer to prepare for a programming test.
Problem:
Given the amount of a purchase and the amount given as payment, calculate the number and type of each denomination of currency returned as change. Change is always given with the most of the highest denominations first. The denominations of paper currency used will be $100, $50, $20, $10, $5 and $1. The denominations of the coins will be $0.25, $0.10, $0.05 and $0.01.
INPUT: There will be 5 lines of input. Each line will contain 2 rational numbers representing the amount of a purchase and the amount given as payment.
OUTPUT: For each input line print the change using the number of non-zero denominations used in order of their magnitude from high to low. If no change is due print NONE. Sample Output #1 represents: 1-$5, 2-$1, 1-$.25, 2-$.10 and 2-$.01.
SAMPLE INPUT SAMPLE OUTPUT
1. 12.53, 20.00 1. 121221
2. 11.33, 15.00 2. 32112
3. 35.64, 50.00 3. 14111
4. 72.67, 100.00 4. 112113
5. 106.68, 200.00 5. 123112
I decided to create two programs: a long, easier-to-follow-one and a condensed version.
Here is the long one:
import java.util.*;
public class Prac13CorrectChange {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
for (int A = 1; A <= 5; A++) {
System.out
.println("What is the amount of your purchase and the amount given as your payment?");
String input = in.nextLine();
String[] data = input.split(",");
double $amount = Double.parseDouble(data[0]);
double price = Double.parseDouble(data[1]);
double change = price - $amount;
int ans1 = ((int) (change / 100));
change = change - (ans1 * 100);
int ans2 = ((int) (change / 50));
change = change - (ans2 * 50);
int ans3 = ((int) (change / 20));
change = change - (ans3 * 20);
int ans4 = ((int) (change / 10));
change = change - (ans4 * 10);
int ans5 = ((int) (change / 5));
change = change - (ans5 * 5);
int ans6 = ((int) (change / 1));
change = change - (ans6 * 1);
int ans7 = ((int) (change / .25));
change = change - (ans7 * .25);
int ans8 = ((int) (change / .10));
change = change - (ans8 * .10);
int ans9 = ((int) (change / .05));
change = change - (ans9 * .05);
int ans10 = ((int) (change / .01));
change = change - (ans10 * .01);
String answer = "";
if (ans1 != 0) {
answer = answer + Integer.toString(ans1);
}
if (ans2 != 0) {
answer = answer + Integer.toString(ans2);
}
if (ans3 != 0) {
answer = answer + Integer.toString(ans3);
}
if (ans4 != 0) {
answer = answer + Integer.toString(ans4);
}
if (ans5 != 0) {
answer = answer + Integer.toString(ans5);
}
if (ans6 != 0) {
answer = answer + Integer.toString(ans6);
}
if (ans7 != 0) {
answer = answer + Integer.toString(ans7);
}
if (ans8 != 0) {
answer = answer + Integer.toString(ans8);
}
if (ans9 != 0) {
answer = answer + Integer.toString(ans9);
}
if (ans10 != 0) {
answer = answer + Integer.toString(ans10);
}
System.out.println(answer);
}
}
}
And here is the condensed version.
import java.util.Scanner;
public class Prac15CorrectChangeShort {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
for (int A = 1; A <= 5; A++) {
System.out
.println("What is the amount of your purchase and the amount given as your payment?");
String input = in.nextLine();
String[] data = input.split(",");
double $amount = Double.parseDouble(data[0]);
double price = Double.parseDouble(data[1]);
double change = price - $amount;
int ans[] = new int[10];
double money[] = { 100, 50, 20, 10, 5, 1, 0.25, 0.10, 0.05, 0.01 };
for (int looptimes = 0; looptimes < 10; looptimes++) {
ans[looptimes] = ((int) (change / money[looptimes]));
change = change - (ans[looptimes] * money[looptimes]);
}
for (int looptimes = 0; looptimes < 10; looptimes++) {
if (ans[looptimes] != 0) {
System.out.print(ans[looptimes]);
}
}
System.out.print('\n');
}
}
}
The main problem I am having is that, no matter the debugging I do, it is giving me incorrect outputs #2-5. It gives me 1 less for the last digit. Neither the programmer who gave me this problem nor I can find any reason for this occurrence.
Please help.

Looks like a floating point error.
Read this
You can use BigDecimal instead of double when calculating the change.
BigDecimal change = BigDecimal.valueOf(price - $amount);

Related

Why am I getting an error message while trying to code for change?

This is the question: A store clerk wants a program that calculates the exact change to give a customer with the minimum number of bills and coins. You should input the amount of the purchase and the amount of money tendered (given to the clerk) and then output the change required and the number of each bill and coin to make up the change. Remember you want the minimum number of coins and bills in each case.
** Plan out this program first, before writing any code **
A sample run of the program is shown below.
Change Making Program
Please enter the total purchase: $1.42
Please enter the amount tendered: $20.00
The change will be: $18.58
To make up this amount you will need:
1 ten-dollar bill
1 five-dollar bill
1 two-dollar coin
1 loonie
2 quarters
1 nickel
3 pennies
Thank you for using the Change Making Program
This is what I have so far:
package defaultpackage;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class ChangeMaker {
public static void main(String[] args) throws IOException {
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Please enter the total of your purchase: $");
double total = Integer.parseInt(stdin.readLine());
System.out.print("Please enter the amount of money tendered: $");
double tendered = Integer.parseInt(stdin.readLine());
double change = tendered - total;
System.out.print("Your change is: $" +change);
if (change > 99.99)
{
double hundreds = (change - (change % 100)) / 100;
System.out.print("Hundred-dollar bills: " + hundreds);
change = change - (hundreds * 100);
}
if (change > 49.99)
{
double fifties = (change - (change % 50)) / 50;
System.out.print("Fifty-dollar bills: " + fifties);
change = change - (fifties * 50);
}
if (change > 19.99)
{
double twenties = (change - (change % 20)) / 20;
System.out.print("Twenty-dollar bills: " + twenties);
change = change - (twenties * 20);
}
if (change > 9.99)
{
double tens = (change - (change % 10)) / 10;
System.out.print("Ten-dollar bills: " + tens);
change = change - (tens * 10);
}
if (change > 4.99)
{
double fives = (change - (change % 5)) / 5;
System.out.print("Five-dollar bills: " + fives);
change = change - (fives * 5);
}
if (change > 1.99)
{
double toonies = (change - (change % 2)) / 2;
System.out.print("Toonies: " + toonies);
change = change - (toonies * 2);
}
if (change > 0.99)
{
double loonies = (change - (change % 1)) / 1;
System.out.print("Loonies: " + loonies);
change = change - (loonies * 1);
}
if (change > 0.24)
{
double quarters = (change - (change % 0.25)) / 0.25;
System.out.print("Quarters: " + quarters);
change = change - (quarters * 0.25);
}
if (change > 0.09)
{
double dimes = (change - (change % 0.1)) / 0.1;
System.out.print("Dimes: " + dimes);
change = change - (dimes * 0.1);
}
if (change > 0.04)
{
double nickles = (change - (change % 0.05)) / 0.05;
System.out.print("Nickles: " + nickles);
change = change - (nickles * 0.05);
}
if (change > 0)
{
double pennies = (change - (change % 0.1)) / 0.1;
System.out.print("Pennies : " + pennies);
change = change - (pennies * 0.1);
}
}
}
Here is a solution to the problem you present. It produces exactly the desired output.
The code uses integer math to avoid the precision problems you will inevitably have when using floating point values to represent dollar amounts. To do this, input values are multiplied by 100 and treated as cents. When printing out dollar amounts, we divide by 100 to represent the values in dollars.
Another feature of this code is that it is data-driven. Rather than duplicate the logic for removing each denomination over and over, a table provides the information about each denomination, and then there is only one block of code that is run in a loop to deal with each denomination. The code deals with properly pluralizing each denomination name when appropriate, including the special case for "pennies".
package defaultpackage;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.List;
class Denomination {
public Denomination(int value, String name, String pluralName) {
this.value = value;
this.name = name;
this.pluralName = pluralName;
}
public Denomination(int value, String name) {
this(value, name, null);
}
String getDescription(int count) {
String desc = this.name;
if (count > 1)
if (pluralName == null)
desc += 's';
else
desc = pluralName;
return desc;
}
public int getValue() {
return value;
}
private final int value;
private final String name;
private final String pluralName;
}
class ChangeMaker {
private static final List<Denomination> denominations = List.of(
new Denomination(10000, "one-hundred-dollar bill"),
new Denomination(5000, "fifty-dollar bill"),
new Denomination(2000, "twenty-dollar bill"),
new Denomination(1000, "ten-dollar bill"),
new Denomination(500, "five-dollar bill"),
new Denomination(200, "two-dollar coin"),
new Denomination(100, "loonie"),
new Denomination(25, "quarter"),
new Denomination(10, "dime"),
new Denomination(5, "nickel"),
new Denomination(1, "penny", "pennies")
);
public static void main(String[] args) throws IOException {
System.out.println("Change Making Program");
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Please enter the total purchase: $");
int total = (int)(Double.parseDouble(stdin.readLine()) * 100);
System.out.print("Please enter the amount tendered: $");
int tendered = (int)(Double.parseDouble(stdin.readLine()) * 100);
int change = tendered - total;
System.out.printf("The change will be: $%.2f\n", change / 100.0);
System.out.println("To make up this amount you will need:");
for (Denomination denom: denominations) {
if (change == 0)
break;
if (change >= denom.getValue()) {
int count = change / denom.getValue();
if (count > 0) {
change = change - denom.getValue() * count;
System.out.printf("%d %s\n", count, denom.getDescription(count));
}
}
}
System.out.println("Thank you for using the Change Making Program");
}
}
Sample Run:
Change Making Program
Please enter the total purchase: $1.42
Please enter the amount tendered: $20.00
The change will be: $18.58
To make up this amount you will need:
1 ten-dollar bill
1 five-dollar bill
1 two-dollar coin
1 loonie
2 quarters
1 nickel
3 pennies
Thank you for using the Change Making Program
If the OP is asking this question to do a homework assignment, then I expect that this answer may be "too good". It may be using techniques not yet studied in class. Even if the OP could submit this as-is, I would encourage them to not do so. Instead, I'd suggest that they study this example, learn from it, and then incorporate what is learned into their own solution as appropriate. I encourage them to ask questions about the example, which I'd be happy to answer.
I have overseen the parseInt problem, but there is still another problem:
pennies = (change - (change % 0.1)) / 0.1;
...
change = change - (pennies * 0.1);
should be 0.01 instead of 0.1 - or just use what is left in change.
Advice: do not use double for money - lots of problems with rounding! (chances of change being short by one penny)
either use int/ long to represent cents, or
use BigDecimal
Note (change - (change % 100)) / 100 is basically the same as (int)(change / 100) - casting to int removes all decimals

Largest number of times square root can be calculated on numbers between 2 intervals

I wrote a simple program to calculate the maximum number of times square root can be calculated on a number , input is an interval from num1 to num2
eg:
if the input is (1,20), answer is 2, since square root of 16 is 4 , and square root of 4 is 2 .
int max = 0;
for (int i = num1; i <= num2; i++) {
boolean loop = true;
int count = 0;
int current = i;
if (i == 1) {
count++;
} else {
while (loop) {
double squareRoot = Math.sqrt(current);
if (isCurrentNumberPerfectSquare(squareRoot)) {
count++;
current = (int) squareRoot;
} else {
loop = false;
}
}
}
if (count > max) {
max = count;
}
}
return max;
static boolean isCurrentNumberPerfectSquare(double number) {
return ((number - floor(number)) == 0);
}
I get the answer, but was wondering wether this can be improved using some mathematical way ?
Any suggestions ?
To avoid more confusion here my final answer to this topic.
A combination of both previously mentioned approaches.
What 'Parameswar' is looking for is the largest perfect square formed by the lowest base.
Step 1 -
To get that calculate the largest possible perfect square based on your num2 value.
If it is outside your range, you have no perfect square within.
Step 2 -
If it is within your range, you have to check all perfect square formed by a lower base value with a higher number of times.
Step 3 -
If you find one that is within your range, replace your result with the new result and proceed to check lower values. (go back to Step 2)
Step 4 -
Once the value you check is <= 2 you have already found the answer.
Here some sample implementation:
static class Result {
int base;
int times;
}
static boolean isCurrentNumberPerfectSquare(double number) {
return ((number - Math.floor(number)) == 0);
}
private static int perfectSquare(int base, int times) {
int value = base;
for (int i = times; i > 0; i--) {
value = (int) Math.pow(base, 2);
}
return value;
}
private static Result calculatePerfectSquare(int perfectSquare) {
Result result = new Result();
result.base = (int) Math.sqrt(perfectSquare);
result.times = 1;
while (result.base > 2 && isCurrentNumberPerfectSquare(Math.sqrt(result.base))) {
result.base = (int) Math.sqrt(result.base);
result.times += 1;
}
System.out.println(perfectSquare + " -> " + result.base + " ^ " + result.times);
return result;
}
static int maxPerfectSquares(int num1, int num2) {
int largestPerfectSqr = (int) Math.pow(Math.floor(Math.sqrt(num2)), 2);
if (largestPerfectSqr < num1) {
return 0;
}
Result result = calculatePerfectSquare(largestPerfectSqr);
int currentValue = result.base;
while (currentValue > 2) {
// check lower based values
currentValue--;
int newValue = perfectSquare(currentValue, result.times + 1);
if (newValue >= num1 && newValue < num2) {
result = calculatePerfectSquare(newValue);
currentValue = result.base;
}
}
return result.times;
}
Edit - My assumption is incorrect. Refer to the answer provided by "second".
You can remove the outer loop, num2 can be directly used to determine the number with the maximum number of recursive square roots.
requiredNumber = square(floor(sqrt(num2)));
You just need to check to see if the requiredNumber exists in the range [num1, num2] after finding it.
So the refactoring code would look something like this,
int requiredNumber = Math.pow(floor(Math.sqrt(num2)),2);
int numberOfTimes=0;
if(requiredNumber>=num1) {
if (requiredNumber == 1) {
numberOfTimes=1;
} else{
while (isCurrentNumberPerfectSquare(requiredNumber)) {
numberOfTimes++;
}
}
}
Edit 4: for a more optimal approach check my other answer.
I just leave this here if anybody wants to try to follow my thought process ;)
Edit 3:
Using prime numbers is wrong, use lowest non perfect square instead
Example [35,37]
Edit 2:
Now that I think about it there is a even better approach, especially if you assume that num1 and num2 cover a larger range.
Start with the lowest prime number 'non perfect square' and
calculate the maximum perfect square that fits into your range.
If you have found one, you are done.
If not continue with the next prime number 'non perfect square'.
As a example that works well enough for smaller ranges:
I think you can improve the outerloop. There is no need to test every number.
If you know the smallest perfect square, you can just proceed to the next perfect square in the sequence.
For example:
[16, 26]
16 -> 4 -> 2 ==> 2 perfect squares
No neeed to test 17 to 24
25 -> 5 ==> 1 perfect square
and so on ...
#Chrisvin Jem
Your assumption is not correct, see example above
Edit:
Added some code
static int countPerfectSquares(int current) {
int count = 0;
while (true) {
double squareRoot = Math.sqrt(current);
if (isCurrentNumberPerfectSquare(squareRoot)) {
count++;
current = (int) squareRoot;
} else {
return count;
}
}
}
static boolean isCurrentNumberPerfectSquare(double number) {
return ((number - Math.floor(number)) == 0);
}
static int numPerfectSquares(int num1, int num2) {
int max = 0;
if (num1 == 1) {
max = 1;
}
int sqr = Math.max(2, (int) Math.floor(Math.sqrt(num1)));
int current = (int) Math.pow(sqr, 2);
if (current < num1) {
current = (int) Math.pow(++sqr, 2);
}
while (current <= num2) {
max = Math.max(countPerfectSquares(current), max);
current = (int) Math.pow(++sqr, 2);
}
return max;
}

Java code to find polygonal numbers based on input

I need a program that can do following example:
"What is the number of sides of your polygon?" "3"
"How many of these would you like to see?" "36"
"1 3 6 10 15 21 28 36 45 55"
"66 78 91 105 120 136 153 171 190 210"
"496 528 561 595 630 666"
-It has to be able to input the values from the first two questions and print then answers off 10 to a line. I've tried writing the code myself but constantly get stuck in the for loop.Thank you.
This is what I have so far:
Scanner input = new Scanner(System.in);
//Request number of sides the polygon must have
System.out.println("What is the number of sides of your polygon? ");
n = input.nextInt();
System.out.println("How many of these would you like to see? ");
k = input.nextInt();
long output = polygonalNumber(n,k);
for (k = 1; k < k; k++);
if (output % 10 == 0) {
System.out.println();
}
}
public static long polygonalNumber(long n, long k){
long p = (k * k) * (n-2) - (k * (n-4))/2;
return polygonalNumber(n,k);
Your code looks really messed up. But no worries, I wrote a version that supports from 3-6 sides.
Here it is:
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// Request number of sides the polygon must have
System.out.println("What is the number of sides of your polygon? ");
int sides = input.nextInt();
System.out.println("How many polygonal numbers do you want?");
int amount = input.nextInt();
input.nextLine();
input.close();
FindPolygonalNumbers(sides, amount);
}
static void FindPolygonalNumbers(int sides, int amount) {
String numbers = "";
for (int i = 1; i <= amount; i++) {
int number = 0;
if (sides == 3) {
number = (i * (i + 1)) / 2;
} else if (sides == 4) {
number = i * i;
} else if (sides == 5) {
number = (3 * i * i - i) / 2;
} else if (sides == 6) {
number = i * (2 * i - 1);
}
numbers = numbers + number + ", ";
}
System.out.println(numbers);
}
If you have any questions regarding the code, don't hesitate to ask about it.

Java 2D Minimization

I need help writing a program that is given a specified number of coordinate points in the form (X,Y). The number of points that will be given is the first line in the program; it can be read in through a scanner.
I need to calculate the least amount of area to cover all of the points with the lines x = a, and y = b. So, the area would be a * b (Area of a rectangle).
However, one coordinate point (X, Y) must be removed to optimize the area. The point that is removed should minimize the area as much as possible. I need help writing algorithm to do so.
This is a sample input, and output that I was given ::
SAMPLE INPUT
4
2 4
1 1
5 2
17 25
SAMPLE OUTPUT
12
In this example, the first line of input (4) indicates that four points will be input. The next four lines are the coordinates in form (x, y). The last point which is (17, 25) is removed as the outlier which leaves us with the first three points.
If the three remaining points are graphed, they can all be inside a box (3 by 4) hence the output is 12; (3 * 4). It is OK for the line to be on the point like in this example. However, the outlier is not always the last point, or very big. The outlier could be very small, the area just needs to be minimized.
--
This is what I have so far (I know it's not very much..) - please help me!
It's mostly just the algorithm that I need help with..
import java.io.*;
import java.util.*;
public class Area {
public static void main(String args[]) {
Scanner scan = new Scanner(System.in);
int numOfPoints = scan.nextInt();
int Xcoordinates[] = new int[numOfPoints];
int Ycoordinates[] = new int[numOfPoints];
for (int i = 0; i <= numOfCows - 1; i++) {
Xcoordinates[i] = scan.nextInt();
Ycoordinates[i] = scan.nextInt();
}
Let you have 4 points (2 4), (1 1), (5 2), (17 25).
As you can always remove one point to optimize area hence,there are C(4,3) combinations possible of points,which are:
{ { (2 4), (1 1), (5 2) }, { (1 1), (5 2), (17 25) }, { (2 4), (5 2),(17 25) }, { (2 4),(1 1),(17 25) } }
Minimum area you can find for a set will be:
(Max(all x coordinates)-Min(all x coordinates)) * (Max(all y
coordinates)-Min(all y coordinates))
{ (2 4), (1 1), (5 2) }
Minimum area for this set is equal to (5-1)*(4-1) = 4*3 = 12
{ (1 1), (5 2), (17 25) }
Minimum area you can find for this set will be: (17-1)*(25-1) =
16*24 = 384
{ (2 4), (5 2), (17 25) }
Minimum area you can find for this set will be: (17-2)*(25-2) =
15*23 = 345
{ (2 4),(1 1),(17 25) }
Minimum area you can find for this set will be: (17-1)*(25-1) =
16*24 = 384
Out of all the area for the set { (2 4), (1 1), (5 2) } is minimum which is equal to 12 ,so the required answer is 12.
The bruteforce solution is of course to compute the area of every combination of points and select the minimum.
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int numOfPoints = scan.nextInt();
int[][] points = new int[numOfPoints][2];
for (int i = 0; i < numOfPoints; i++) {
points[i][0] = scan.nextInt();
points[i][1] = scan.nextInt();
}
// Testcase, comment everything above out.
/*
* int numOfPoints = 4; int[][] points = { { 2, 4 }, { 1, 1 }, { 5, 2 },
* { 17, 25 } };
*/
// As we try to minimize, we start with the biggest possible value.
int minArea = Integer.MAX_VALUE;
// We don't know which one to skip yet, so this value should be anything
// *but* a valid value.
int skippedPoint = -1;
// Pretty straightforward. Check every point, get minimum
for (int skipped = 0; skipped < numOfPoints; skipped++) {
int area = calculateArea(points, skipped);
if (area < minArea) {
skippedPoint = skipped;
minArea = area;
}
}
System.out.println("The original area was " + calculateArea(points, -1) + " units big.");
System.out.println("The minimized area is " + minArea + " units big.");
System.out.println("This was reached by leaving the " + (skippedPoint + 1) + ". point (" + Arrays.toString(points[skippedPoint]) + ") out.");
}
/**
* Implementation of Rajeev Singh's AABB-algorithm
*
* #param points
* All points
* #param skipped
* The point to skip
* #return The area of the axis-aligned bounding box of all points without
* the specified point
*/
private static int calculateArea(int[][] points, int skipped) {
// Initialize values with the opposite of the desired result, see
// minimization-problem above.
int max_x = Integer.MIN_VALUE, min_x = Integer.MAX_VALUE, max_y = Integer.MIN_VALUE, min_y = Integer.MAX_VALUE;
for (int i = 0; i < points.length; i++) {
if (i == skipped) {
continue; // This is where the magic happens. Continue
// immediatly jumps to the start of the loop.
}
int[] point_i = points[i];
if (point_i[0] > max_x) {
max_x = point_i[0];
}
if (point_i[0] < min_x) {
min_x = point_i[0];
}
if (point_i[1] > max_y) {
max_y = point_i[1];
}
if (point_i[1] < min_y) {
min_y = point_i[1];
}
}
return (max_x - min_x) * (max_y * min_y);
}
You now have the minimal area and the point that has been left out.

How can I round down a decimal?

I am writing a program that will simulate a cash register change calculator. It should print the change and how to give back the change ( number of twenty, tens, fives, quarters, dimes, etc).
The problem is that when I compile the program, I get a big number. I've tried rounding it down but it doesn't work. ALSO, I don't know if it is caused by the change not being rounded but I won't get the number of cents, I only get 1 $10 bill.
p.s. I am taking a high school CS course and right now I can't use other methods of rounding it, I know there is a way like the one I attempted below (casting and stuff) which I am allowed to use at the moment.
Thank you.
public class changeCash
{
public static void main(String[] args)
{
double cost = 68.90;
double amtPaid = 80.00;
double change = 0;
int twentyBill= 0;
int tenBill = 0;
int fiveBill = 0;
int oneBill = 0;
int quarters = 0;
int dimes = 0;
int nickels = 0;
int pennies = 0;
change = amtPaid - cost;
change = ((int)change * 10) / 10.0;
System.out.println("Your change is " +"$" + change);
double back = amtPaid - cost;
if(back >= 20)
{
twentyBill++;
back -= 20;
System.out.println(twentyBill + " $20 bill(s)");
}
else if(back >= 10)
{
tenBill++;
back -= 10;
System.out.println(tenBill + " $10 bill(s)");
}
else if(back >= 5)
{
fiveBill++;
back -= 5;
System.out.println(fiveBill + " $5 bills(s)");
}
else if(back >= 1)
{
oneBill++;
back -= 1;
System.out.println(oneBill + " $1 bills(s)");
}
else if(back >= 0.25)
{
quarters++;
back -= 0.25;
System.out.println(quarters + " qaurter(s)");
}
else if(back >= 0.10)
{
dimes++;
back -= 0.10;
System.out.println(dimes + " dime(s)");
}
else if(back >= 0.05)
{
nickels++;
back -= 0.05;
System.out.println(nickels + " nickel(s)");
}
else if(back >= 0.01)
{
pennies++;
back -= 0.01;
System.out.println(pennies + " penny(ies)");
}
}
}
Couple of issues. First, smaller one:
change = amtPaid - cost;
Change is 11.1, as it should be, but then:
change = ((int)change * 10) / 10.0;
Casts take precedence over arithmetic, so first (int)change happens (which results in 11), then it is multiplied by 10, then divided by 10.0, and you end up with 11.0 instead of 11.1.
But your bigger problem is in your if statements. You have a series of if...else. Once one of these executes, the remainder of the else blocks will not. So when you have e.g.:
if (back >= 20) {
...
} else if (back >= 10) {
...
} else if (back >= 5) {
...
} else ...
As soon as one hits, it's done. If back >= 20 is false it goes to the next. Then if back >= 10 is true, it executes that, then doesn't execute the rest, so you would want to separate them, e.g.:
if (back >= 20) {
...
}
if (back >= 10) {
...
}
if (back >= 5) {
...
}
...
That'll get you closer, but you're still not quite there. For example, what if your change is 40? That will be two 20's. But your if statement will only take away a single 20. To that end, a while loop would be appropriate. It also more accurately reflects reality. In real life if you had to give somebody $40, you wouldn't just give them a single $20 and walk away, you'd get a dirty look. You'd keep giving them $20's until the amount you owed them was less than $20. So for example:
while (back >= 20) {
...
}
while (back >= 10) {
...
}
while (back >= 5) {
...
}
...
You want your code to reflect the logic you would use in reality.
Regarding your question in comments:
... why do I get $11.099999999999994 instead of just 11.1?
Floating-point rounding error. Decimal numbers are not 100% accurate; "11.1" can't be represented precisely. You have a couple of ways to work around it. You could round to two decimals when you display the number, e.g. System.out.printf("%.2f", change). However, you may want to use int and store the number of cents, rather than using double and storing the number of dollars. Working with integers is more precise, and actually, when working with currency in important applications, integers are often used for this reason.
Simpler Solution
double d = 2.99999999;
long l = (long) d;
Math.class, floor function
double d = Math.floor(2.55555) //result: 2.0
Returns the largest (closest to positive infinity) double value that
is less than or equal to the argument and is equal to a mathematical
integer
Find below the code which works well. Tested with different values. We want to avoid more than 2 decimal places hence I have added several utility methods just to do that.
Uncomment different cost values to see its working in different scenarios.
public class ChangeCash {
public static void main(String[] args) {
double cost = 65.90;
// cost = 68.33;
// cost = 42.27;
double amtPaid = 80.00;
double change = 0;
int twentyBill = 0;
int tenBill = 0;
int fiveBill = 0;
int oneBill = 0;
int quarters = 0;
int dimes = 0;
int nickels = 0;
int pennies = 0;
change = amtPaid - cost;
System.out.format("Your change is $ %.2f", decimalCeil(change, true));
System.out.println();
double back = decimalCeil(change, true);
if (back >= 20) {
twentyBill++;
back -= 20;
System.out.println(twentyBill + " $20 bill(s)");
}
if (back >= 10) {
tenBill++;
back -= 10;
System.out.println(tenBill + " $10 bill(s)");
}
if (back >= 5) {
fiveBill++;
back -= 5;
System.out.println(fiveBill + " $5 bills(s)");
}
if (back >= 1) {
oneBill = (int) (back * 10) / 10;
back -= oneBill;
System.out.println(oneBill + " $1 bills(s)");
}
if (decimalCeil(back) >= 0.25) {
quarters = (int) (back * 100) / 25;
back = correct2DecimalPlaces(back, 25);
System.out.println(quarters + " qaurter(s)");
}
back = (int) (decimalCeil(back, true) * 100);
if (back >= 10) {
dimes = (int) (back / 10);
back = back % 10;
System.out.println(dimes + " dime(s)");
}
if (back >= 5) {
nickels = (int) (back / 5);
back = back % 5;
System.out.println(nickels + " nickel(s)");
}
if (back >= 1) {
pennies = (int) back;
System.out.println(pennies + " penny(s)");
}
}
private static double correct2DecimalPlaces(double back, int modulo) {
int correctTwoPlaces = (int) (back * 100) % modulo;
back = (double) correctTwoPlaces / 100;
return back;
}
private static double decimalCeil(double change) {
int temp = (int) (change * 100);
double tempWithCeil = Math.ceil(temp);
double answer = tempWithCeil / 100;
return answer;
}
private static double decimalCeil(double change, boolean decimalThreePlaces) {
double temp = change * 1000;
double tempWithCeil = Math.ceil(temp);
double answer = tempWithCeil / 1000;
return answer;
}
}

Categories