Devil'sBride
Devil'sBride

Reputation: 1

Java -vending machine that can't accept pennies

So I'm working on a java project that involves creating a soda machine that adjusts price based on temperature. I can't seem to figure out how to make sure the machine does NOT accept pennies when accepting payment from the user.

I feel like I'm overcoding but I'm at my wit's end because I don't have any clue how to not accept pennies.

import java.util.*;
import java.text.*;
public class SodaMachine extends SodaTester
{
    public static void main(String[] args)
    {
        double temp;
        double money;
        double change;
        double price1 = .50;
        double price2 = .55;
        double price3 = .60;
        double price4 = .65;
        double price5 = .75;
        double price6 = .80;
        double price7 = .85;
        double price8 = .90;
        double price9 = 1.00;

        System.out.println("Hi there! Please enter the temperature in Farenheit:");
        Scanner scan = new Scanner(System.in);
        temp = scan.nextDouble();
        DecimalFormat fmt = new DecimalFormat("0.#");

        NumberFormat fmt2 = NumberFormat.getCurrencyInstance();

        if (temp < 40 || temp > 120)
        {
            System.out.println("Invalid input. Temperature should be between 40 and 120 degrees Farenheit.");
            while (temp < 40 || temp > 120)
            {
                temp = scan.nextDouble();
                System.out.println("The rounded temperature in degrees Farenheit is: " + fmt.format(temp));
                System.out.println("Invalid input. Temperature should be between 40 and 120 degrees Farenheit.");
            }
        }

        if(temp < 50 && temp >= 40)
        {
            System.out.println("The rounded temperature in degrees Farenheit is: " + fmt.format(temp));
            System.out.println("The price is: " + fmt2.format(price1));

            System.out.println("Please insert amount of payment: ");
            money = scan.nextDouble();
            while (money < price1)
            {
                System.out.println("Invalid input please try again. Your total is: " + fmt2.format(price1));
                money = scan.nextDouble();
            }
            change = money - price1;
            System.out.println("Your Change is: " + fmt2.format(change));
        }else if (temp >= 50 && temp <= 60) {
            System.out.println("The rounded temperature in degrees Farenheit is: " + fmt.format(temp));
            System.out.println("The price is: " + fmt2.format(price2));

            System.out.println("Please insert amount of payment: ");
            money = scan.nextDouble();
            while (money < price2)
            {
                System.out.println("Invalid input please try again. Your total is: " + fmt2.format(price2));
                money = scan.nextDouble();
            }
            change = money - price2;
            System.out.println("Your Change is: " + fmt2.format(change));
        }else if (temp > 60 && temp <= 65) { 
            System.out.println("The rounded temperature in degrees Farenheit is: " + fmt.format(temp));
            System.out.println("The price is: " + fmt2.format(price3));

            System.out.println("Please insert amount of payment: ");
            money = scan.nextDouble();
            while (money < price3)
            {
                System.out.println("Invalid input please try again. Your total is: " + fmt2.format(price3));
                money = scan.nextDouble();
            }
            change = money - price3;
            System.out.println("Your Change is: " + fmt2.format(change));
        }else if (temp > 65 && temp <= 70) {
            System.out.println("The rounded temperature in degrees Farenheit is: " + fmt.format(temp));
            System.out.println("The price is: " + fmt2.format(price4));

            System.out.println("Please insert amount of payment: ");
            money = scan.nextDouble();
            while (money < price4)
            {
                System.out.println("Invalid input please try again. Your total is: " + fmt2.format(price4));
                money = scan.nextDouble();
            }
            change = money - price4;
            System.out.println("Your Change is: " + fmt2.format(change));
        }else if (temp > 70 && temp <= 75) {
            System.out.println("The rounded temperature in degrees Farenheit is: " + fmt.format(temp));
            System.out.println("The price is: " + fmt2.format(price5));

            System.out.println("Please insert amount of payment: ");
            money = scan.nextDouble();
            while (money < price5)
            {
                System.out.println("Invalid input please try again. Your total is: " + fmt2.format(price5));
                money = scan.nextDouble();
            }
            change = money - price5;
            System.out.println("Your Change is: " + fmt2.format(change));
        }else if (temp > 75 && temp <= 80) {
            System.out.println("The rounded temperature in degrees Farenheit is: " + fmt.format(temp));
            System.out.println("The price is: " + fmt2.format(price6));

            System.out.println("Please insert amount of payment: ");
            money = scan.nextDouble();
            while (money < price6)
            {
                System.out.println("Invalid input please try again. Your total is: " + fmt2.format(price6));
                money = scan.nextDouble();
            }
            change = money - price6;
            System.out.println("Your Change is: " + fmt2.format(change));
        }else if (temp > 80 && temp <= 85) {
            System.out.println("The rounded temperature in degrees Farenheit is: " + fmt.format(temp));
            System.out.println("The price is: " + fmt2.format(price7));

            System.out.println("Please insert amount of payment: ");
            money = scan.nextDouble();
            while (money < price7)
            {
                System.out.println("Invalid input please try again. Your total is: " + fmt2.format(price7));
                money = scan.nextDouble();
            }
            change = money - price7;
            System.out.println("Your Change is: " + fmt2.format(change));
        }else if (temp > 85 && temp <= 90) {
            System.out.println("The rounded temperature in degrees Farenheit is: " + fmt.format(temp));
            System.out.println("The price is: " + fmt2.format(price8));

             System.out.println("Please insert amount of payment: ");
            money = scan.nextDouble();
            while (money < price8)
            {
                System.out.println("Invalid input please try again. Your total is: " + fmt2.format(price8));
                money = scan.nextDouble();
            }
            change = money - price8;
            System.out.println("Your Change is: " + fmt2.format(change));
        }else if (temp > 90 && temp <= 120) {
            System.out.println("The rounded temperature in degrees Farenheit is: " + fmt.format(temp));
            System.out.println("The price is: " + fmt2.format(price9));

            System.out.println("Please insert amount of payment: ");
            money = scan.nextDouble();
            while (money < price9)
            {
                System.out.println("Invalid input please try again. Your total is: " + fmt2.format(price9));
                money = scan.nextDouble();
            }
            change = money - price9;
            System.out.println("Your Change is: " + fmt2.format(change));
        }
    }






















}

Upvotes: 0

Views: 255

Answers (2)

Kevin Cruijssen
Kevin Cruijssen

Reputation: 9336

I won't go into detail about your current code, but you basically want to check if the decimal value you've read from the user modulo-0.05 equals 0 (so it has no remainder). One issue in this is that floating point precision can interfere with the checks when you use double, which is why you'd always want to use java.math.BigDecimal for currency calculations.

Here an example:

BigDecimal input = new BigDecimal(scanner.next());
if(input.remainder(new BigDecimal("0.05")).compareTo(BigDecimal.ZERO) == 0){
  System.out.println("Input "+input+" is valid!");
} else{
  System.out.println("Input "+input+" is not valid!");
}

For the inputs "1", "1.00", "1.05", "4.35", "1.01", "3.21", "4.68" it will output the following:

Input 1 is valid!
Input 1.00 is valid!
Input 1.05 is valid!
Input 4.35 is valid!
Input 1.01 is not valid!
Input 3.21 is not valid!
Input 4.68 is not valid!

Try it online.


Since BigDecimal can be quite confusing for new Java users, you could perhaps let the user input the amount in cents (so as integers), in which case it can be something like this instead:

int input = scanner.nextInt();
if(input % 5 == 0){
  System.out.println("Input "+input+" is valid!");
} else{
  System.out.println("Input "+input+" is not valid!");
}

For the input "100", "105", "435", "101", "321", "468" it will output the following:

Input 100 is valid!
Input 105 is valid!
Input 435 is valid!
Input 101 is not valid!
Input 321 is not valid!
Input 468 is not valid!

Try it online.


EDIT: Since I had some time, I reworked your solution with re-usable methods.

Please have a good look what I did, and if you have any questions about specific parts let me know. It now uses recursive methods until the user enters a valid input. The boolean showMessage parameters in the methods are to show the "Please enter X" messages only once.

import java.lang.IllegalArgumentException;
import java.lang.NumberFormatException;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.InputMismatchException;
import java.util.Scanner;
public class SodaMachine{ 
  private static final String currencySymbol = "$";
  private static final BigDecimal roundOn = new BigDecimal("0.05");
  private Scanner scanner;
  private NumberFormat currencyFormat;

  public SodaMachine(){
    scanner = new Scanner(System.in);
    currencyFormat = NumberFormat.getCurrencyInstance();
  }

  public static void main(String[] args){
    SodaMachine sodaMachine = new SodaMachine();
    double farenheitInput = sodaMachine.enterFarenheit(true);
    System.out.println("The temperature in degrees Farenheit you've entered is: " + farenheitInput);

    BigDecimal price = sodaMachine.determinePrice(farenheitInput);
    System.out.println("The price is: " + sodaMachine.currencyFormat.format(price));

    BigDecimal payment = sodaMachine.enterPayment(price, true);

    BigDecimal change = payment.subtract(price);
    System.out.println("Your change is: " + sodaMachine.currencyFormat.format(change));
  }

  private double enterFarenheit(boolean showMessage){
    if(showMessage){
      System.out.println("Hi there! Please enter the temperature in Farenheit:");
    }

    double farenheitInput;
    try{
      farenheitInput = scanner.nextDouble();
    } catch(InputMismatchException ex){
      scanner.nextLine(); // Get rid of the invalid user-input
      System.out.println("The value you've entered is not a valid. The input should be a decimal input. Please try again.");
      return enterFarenheit(false);
    }

    if(farenheitInput < 40 | farenheitInput > 120){
      System.out.println("Invalid input. Temperature should be between 40 and 120 degrees Farenheit.");
      return enterFarenheit(false);
    }

    return farenheitInput;
  }

  private BigDecimal determinePrice(double farenheit){
    String strPrice;
    // Temperature is in the range [40, 50):
    if(farenheit >= 40 && farenheit < 50){
      strPrice = "0.50";
    }
    // Temperature is in the range [50, 60]:
    else if(farenheit >= 50 && farenheit <=60){
      strPrice = "0.55";
    }
    // Temperature is in the range (60, 65]:
    else if(farenheit > 60 && farenheit <= 65){
      strPrice = "0.60";
    }
    // Temperature is in the range (65, 70]:
    else if(farenheit > 65 && farenheit <= 70){
      strPrice = "0.65";
    }
    // Temperature is in the range (70, 75]:
    else if(farenheit > 70 && farenheit <= 75){
      strPrice = "0.75";
    }
    // Temperature is in the range (75, 80]:
    else if(farenheit > 75 && farenheit <= 80){
      strPrice = "0.80";
    }
    // Temperature is in the range (80, 85]:
    else if(farenheit > 80 && farenheit <= 85){
      strPrice = "0.85";
    }
    // Temperature is in the range (85, 90]:
    else if(farenheit > 85 && farenheit <= 90){
      strPrice = "0.90";
    }
    // Temperature is in the range (90, 120]:
    else if(farenheit > 90 && farenheit <= 120){
      strPrice = "1.00";
    }
    // Invalid temperature range:
    else{
      // Since we already validated the input-range, it should never go here,
      // but added it just in case.
      throw new IllegalArgumentException("The temperature must be in the range [40, 120]!");
    }
    return new BigDecimal(strPrice);
  }

  private BigDecimal enterPayment(BigDecimal price, boolean showMessage){
    if(showMessage){
      System.out.println("Please enter amount of payment: ");
    }

    String userInput = scanner.next();
    // Remove the optional currency symbol from the user input
    userInput = userInput.replace(currencySymbol, "");

    BigDecimal paymentInput;
    try{
      paymentInput = new BigDecimal(userInput);
    } catch(NumberFormatException ex){
      scanner.nextLine(); // Get rid of the invalid user-input
      System.out.println("The value you've entered is not a valid. The input should be a price input. Please try again.");
      return enterPayment(price, false);
    }

    if(paymentInput.compareTo(price) < 0){
      System.out.println("Your payment of " + currencyFormat.format(paymentInput) + " is too low. Please try again. The total price is: " + currencyFormat.format(price));
      return enterPayment(price, false);
    }

    if(paymentInput.remainder(roundOn).compareTo(BigDecimal.ZERO) != 0){
      System.out.println("Your payment should be rounded to " + currencyFormat.format(roundOn) + ". Please try again.");
      return enterPayment(price, false);
    }

    return paymentInput;
  }
}

Try it online.

Upvotes: 2

001
001

Reputation: 13533

Your code can be simplified alot, but I will focus on the issue at hand.

I would create a function to get user input, ensuring it does not contain pennies:

double getMoney(String prompt, Scanner scan)
{
    double money = 0;
    while(true) {   // Loop until proper input
        System.out.println(prompt);
        money = scan.nextDouble();
        // There are a few ways to determine if it has pennies.
        // I will convert to int and check if it is divisible
        // by 10 or 5
        int i = (int)Math.round(money * 100);  // Convert to pennies
        if (0 == i % 5) {
            // It's ok, return
            return money;
        }
    }
}

Side note: using floating point for currency is bad practice. Floating point can introduce rounding errors. It's better to use integers and store the values using the lowest denomination. In this case pennies.

Upvotes: 0

Related Questions