I have an issue with the following method. If I apply the if/else condition which is currently set as a comment /* */, the variable withdrawalAmountVar get double value (if balance is 100 and I withdraw 1 final balance is 98, if I withdraw 10 the final balance is 80). Why?
public void makeWithdrawalButton()
{
//transfer user's input into withdrawalAmountVar
withdrawalAmountVar = Integer.parseInt(text5.getText());
//check if withdrawal should be allowed according to overdraft set
/*
if ( (moneyAmountVar -= withdrawalAmountVar) < overdraftVar)
{
JOptionPane.showMessageDialog(null, "Withdrawal amount exceeds overdraft" );
text5.setText("");
}
else
{
*/
try
{
//make withdrawal from current deposit amount
moneyAmountVar -= withdrawalAmountVar;
output = new DataOutputStream(new FileOutputStream("datafile.dat") );
output.writeInt(accountNumberVar);
output.writeUTF(firstNameVar);
output.writeUTF(lastNameVar);
output.writeInt(moneyAmountVar);
output.close();
}
catch(IOException e)
{
System.err.println( "Cannot make withdrawal");
System.exit(1);
}
}
The problem is
if ( (moneyAmountVar -= withdrawalAmountVar) < overdraftVar)
because you used the operation -= you are actually changing the value of moneyAmountVar to moneyAmountVar-withdrawalAmountVar. When you use this operation or something like it, the lValue will always change accordingly, no matter if it is in a conditional or loop.
To Fix:
int temp = moneyAmountVar - withdrawalAmountVar;
if ( (temp) < overdraftVar)
A Temp variable will make sure that the value of moneyAmount will not change.
Related
This question already has answers here:
Endless while loop problem with try/catch
(2 answers)
Closed 7 years ago.
I need to be able to take user input until the input is greater than the initial price, but I also need to make it robust so that the user can't break the program by entering something other than a double/integer. If the user does enter something other than a double/int.
The problem is that it creates a loop and repeats "Please enter valid currency" + "Please enter: price"
public static double findChange()
{
System.out.println("\nPlease insert: " + price + " (enter payment amount)");
initialPrice = price;
while (payment < price)
{
try{
payment = kb.nextDouble();
}
catch (Exception e)
{
System.out.println("Please enter valid currency");
}
if (payment > 0){
totalPayment += payment;
price -= payment;
price = (price * 100);
payment = 0;
}
if (totalPayment < initialPrice)
System.out.println("Please Insert:" + price);
}
change = totalPayment - initialPrice;
change = Math.round(change * 100);
change = change / 100;
System.out.println("\nChange Given: $" + change);
return change;
}
The reason you're seeing an infinite loop is that you never clear the invalid entry out of the input. If you look at the docs, it says
If the translation is successful, the scanner advances past the input that matched.
When it fails, you should call kb.next() to remove the input that did not match a double, so that you can move on to the next user entry. Otherwise, you'll keep trying to parse the same invalid text over and over:
catch (Exception e)
{
System.out.println("Please enter valid currency");
kb.next();
}
A few other things you can improve as well. There's no need to be using a try and catch here, since you can use the hasNextDouble method to check that the input is valid. If you do decide to stick with exception handling though, you should catch InputMismatchException rather than a generic Exception, or else you risk running into some more problems (for example, if the input gets exhausted). You can also put a continue in when the input fails, so that it doesn't evaluate the rest of the code which is assuming that you correctly read a value.
if(kb.hasNextDouble()){
payment = kb.nextDouble();
} else{
System.out.println("Please enter valid currency");
kb.next();
continue;
}
Note that there's still a problem with your logic, and the loop will never exit (since payment always gets reset to zero). I assume you want to do totalPayment < price instead.
Since you want it to recognize any input, but only use doubles, try Double.parseDouble(String). I also moved the rest of the logic to your try block, since it should only occur when valid input is received. If it can't parse the double, it breaks out without attempting the rest of the logic and tries again.
while (payment < price && price > 0){
try{
payment = Double.parseDouble(kb.next());
if (payment > 0){
totalPayment += payment;
price -= payment;
price = (price * 100);
payment = 0;
}
if (totalPayment < initialPrice){
System.out.println("Please Insert:" + price);
}
}
catch (Exception e) {
System.out.println("Please enter valid currency");
}
}
My program is nearly done except for one problem. I'm having an out of scope problem with the for loop. The goal of the program is to compound monthly interest for a user inputted amount & term.
An example of output at $5000 principal with 5% interest for 3 years would be:
Month: Interest: Principal:
1 $20.83 $5020.83
2 $20.92 $5041.75
etc etc etc
Starting Balance = $ 5000.00 // having problem outputting these w/ for-loop
Final Account Balance = $ 5807.36 // System.out.print keeps repeating multiple times
Total Interest Paid = $ 807.36 // but i can't use variables outside of loop
My problem is that during my for loop, I keep outputting Starting Balance, Final Balance and Total Interest every time the program goes through the loop. but if I try to use the variables outside the loop it goes out of scope and if I try to declare variables outside of the loop I can't use them inside the loop because it's already been declared in the constructor.
Can anyone give me some hints or advice?
My code:
public class Calculator
{
public Calculator()
{
Scanner input = new Scanner(System.in);
boolean error = false;
while (!error){
System.out.print("Please input the following: principal, interest rate, term >> ");
double principal = input.nextDouble();
double interest_rate = input.nextDouble();
int term = input.nextInt();
String Month = input.next();
char dollar_sym = 36;
if (interest_rate <= 0 || term <= 0 || principal <= 0) // input validation
{
System.out.println("The term, interest rate and principal must be greater
than zero");
continue;
}
if (!Month.equals("month")) // input validation
{
System.out.println("Please input month after term");
continue;
}
System.out.println("Month: " + " Interest: " + "Principal: ");
if (Month.equals("month"))
{
for (int month = 1; month <= term; month++)
{
double interest = (principal * interest_rate / 100) / 12;
principal = principal + interest;
System.out.printf("%4d %c%5.2f %c%5.2f\n", month,
dollar_sym, interest, dollar_sym, principal );
double start_principal = principal - interest; // problem
double final_principal = principal; // problem
double total_interest = interest * interest_rate; // problem
System.out.println(" Starting balance = " + start_principal ); // problem
System.out.println("Final account balance = " + final_principal ); // problem
System.out.println("Total Interest Paid = " + total_interest); // problem
}
}
}
}
}
Declare them before the loop begins, so they will exist inside the loop and after it:
double start_principal = 0;
double final_principal = 0;
double total_interest = 0;
Scanner input = new Scanner(System.in);
boolean error = false;
while (!error) {
// ...
}
// ...
In my answer, I am assuming that when you say goes out of scope, you mean that you get a compile time error. (note, it would make the answer easier to address if you provided the error message and the line that is causing the error message).
The scope of a variable refers to where the variable is accessible. For example, if you declare a variable inside of an if statement, the scope is that if statement. Some example code:
public void updateStatus(){
Boolean shouldCheckStatus = true;//this variable is declared inside of the updateStatus method, so that is the scope of the variable
if(shouldCheckStatus == true){
Int hitCounter = 0;//this variable is declared inside of the if statement, so it is only accessible inside of the if statement
//do some work
if(hitCounter > 100){
self.registerHits(hitCounter);//hitCounter is still accessible here, because it is still inside of the if statement
}
else{
shouldCheckStatus = false;
}
}//close the if statement and so close the scope...
//the hitCounter variable is no longer in scope, because we are no longer in the if statement
//but shouldCheckStatus is still in scope, because we are still in the method
if(shouldCheckStatus == true){
self.callAnotherMethod();
}
}
So in your problem, you need to declare your variable above where you want to use it, inside of the scope that you want to use it. And then not declare it again. So declare before the loop.
I have a do while loop. Checking x is between two values. Now im supposed to be taking in an int value, but if the user types a double im getting exceptions. How do I incorparate a check in the same if statement so that if the user types a double it would print something like "x must be an int between 10 and 150:"
do {
x = sc.nextInt();
if ( x < 10 || x > 150 ) {
System.out.print("x between 10 and 150: ");
} else {
break;
}
You do not need an additional check. The exception is just there so you can act accordingly in your program. After all, it doesn't really matter how exactly the input was wrong. Just catch the exception (NumberFormatException, I guess?) and upon catching it, print an error message:
while (true) try {
// here goes your code that pretends only valid inputs can occur
break; // or better yet, put this in a method and return
} catch (NumberFormatException nfex) { // or whatever is appropriate
System.err.println("You're supposed to enter integral values.");
// will repeat due to while above
}
You can just catch the exception and handle it, using a while (true) to allow the user to re-try.
Here's my code:
Scanner sc = new Scanner(System.in);
do {
System.out.print("\nInsert a number >>> ");
try {
int x = sc.nextInt();
System.out.println("You inserted " + x);
if (x > 10 && x < 150) {
System.out.print("x between 10 and 150: ");
} else {
break;
}
} catch (InputMismatchException e) {
System.out.println("x must be an int between 10 and 150");
sc.nextLine(); //This line is really important, without it you'll have an endless loop as the sc.nextInt() would be skipped. For more infos, see this answer http://stackoverflow.com/a/8043307/1094430
}
} while (true);
public class SomeClass {
public static void main(String args[]) {
double x = 150.999; // 1
/* int x = (int) 150.999; */ // 2
if ( x >= 10 && x <= 150 ) { // The comparison will still work
System.out.print("x between 10 and 150: " + x + "\n");
}
}
}
Declare x as double, comparisons between double and int will still work.
Or, cast the number and any decimal values will be discarded.
Responses to previous question , my initial answer to that question had been solved, but I had another problem when it came down to looping which was later solved by simply using a for loop.
However, my problem is I do not want the user to constantly have to restart the program after an exception is handled, rather I want it to loop the same beginning questions to the user. I've tried placing print statements after the return statements, and also tried completely copying the logic code after the try catch, however, realizing that that would not cause the user to loop unlimited times for the exception. Also, on a side note yes my previous question had good answers, however, no one managed to answer my more recurring problem, which is why no one got the check mark towards their answer.
import java.io.*;
import java.text.DecimalFormat;
public class Test
{
public static void main(String[] args) throws IOException
{
double x;
x = circlemethods(0.0, 0.0, 0.0, 1.0);
}
public static double circlemethods(double volume, double surfacearea,
double area, double radius) throws IOException
{
BufferedReader myInput = new BufferedReader(new InputStreamReader(System.in));
String numInput;
String reqInput;
String amountStr;
double numInt = 0;
double num = 0;
double answer = 0;
double amount = 0;
double answer2 = 0;
double answer3 = 0;
double answer4 = 0;
for (double i = 0; i < 999; i++)
;
try
{
// for (double i = 0; i < 999; i++);
// while (numInt != 999) {
System.out.println("This program will ask for a given user radius, then proceed to calculate the user input");
System.out.println("The program will use four methods to achieve this, all calling back to the main method");
System.out.println("Press any key to continue");
numInput = myInput.readLine();
System.out.println("First, what would you like to calculate?");
System.out.println("Enter '1' for Circumference, '2' for area, '3' for volume, or '4' for surface area");
reqInput = myInput.readLine();
numInt = Double.parseDouble(reqInput);
System.out.println("Now enter the radius of the required shape(Half of diameter)");
numInput = myInput.readLine();
num = Double.parseDouble(numInput);
DecimalFormat nextAmount = new DecimalFormat("0.00");
amountStr = nextAmount.format(amount);
if (numInt == 1)
{
System.out.println("You chose to calculate circumference, given the radius :" + num);
answer = (3.14) * (2) * (num);
System.out.print("The circumference of that sphere is :");
System.out.println(answer + "cm³");
return answer;
}
else if (numInt == 2)
{
System.out.println("You chose to calculate area, given the radius :" + num);
answer2 = (3.14) * 2;
System.out.print("The area of the circle is :");
System.out.println(answer2 + "cm²");
return answer2;
}
else if (numInt == 3)
{
System.out.println("You chose to calculate volume, given the radius :" + num);
answer3 = 4 / 3 * (3.14) * (num) * (3) * (3) * (3);
System.out.print("The volume of that sphere is : cm³");
System.out.println(answer3 + "cm³");
return answer3;
}
else
// if (numInt == 4)
{
System.out.println("You chose to calculate surface area, given the radius :" + num);
answer4 = 4 * (3.14) * (num) * (2) * (2);
System.out.print("The Surface area of that sphere is :");
System.out.println(answer4 + "cm²");
return answer4;
}
} catch (Exception e)
{
System.out.println("Please do not enter any string values, next time input enter a number ");
return 0;
// how to loop this untill the user inputs a number????
}
}
}
First, you use a while(true) loop instead of looping for 999 times. (That loop doesn't actually do anything considering there is a semicolon right after it.)
Then, you remove the return 0; from your catch block.
So it would be
while(true) {
try {
.... //your code
}
catch {...}
} //while loop end bracket
This way, the loop will only end if it reaches one of your return statements.
You need to loop until you get a valid value. One way to do that is loop until a boolean value is set to true. Try something similar to this:
boolean inputIsValid = false;
while (!inputIsValid) { ...
Then when you have determined you have a valid input, add the line:
inputIsValid = true;
Your loop will continue until inputIsValid becomes true.
You could also create an endless while loop. Then when you receive a valid input, break out of the loop:
while(true) {
//when valid input is received
break;
}
Ok, I need my program to validate user entered data. If that data is invalid, the program needs to skip almost all of my code and get to the end of my while loop to ask if the user would like to proceed with calculating another loan. My professor has not provided us with a method of doing this and all the information ive found on the internet is not specific enough to help me. Once again, I need the code after the validation to be skipped without exiting the program and go to the end of the loop where I ask the user if they want to calculate another loan. Here is my code thus far.
/* This program is an extension of the previous Interest Calculator. The only different is this one can
compute not only simple interest but daily and monthly compound interest using a switch statement to
differentiate each type of interest. */
import javax.swing.*;
// Import the GUI methods
public class InterestCalculatorLoop {
public static void main(String[] args) {
// Entry point of program
String again = "yes";
while (again.equalsIgnoreCase("yes" ))
{
String option = JOptionPane.showInputDialog("Which type of loan would you like to find interest for? \n1 = Simple Interest \n2 = Monthly Compounded Interest \n3 = Daily Compounded Interest");
int optionInt = Integer.parseInt(option);
int interestType = Integer.parseInt(option);
String paString = JOptionPane.showInputDialog("Enter the principal amount");
double pa = Double.parseDouble(paString);
double interest = 0;
double months = 0;
double totalInterest = 0;
double years = 0;
final double daysInYear = 365.0;
final double daysInMonth = 30.41666666667;
final double monthsInYear = 12.0;
// Logic statements to validate user input or otherwise run through the rest of the program without calculation
if (pa <= 0)
{
JOptionPane.showMessageDialog(null, "Data Error: The principal amount must be greater than zero. You entered " + pa);
return;
}
else
{
String interestString = JOptionPane.showInputDialog("Enter The Annual Interest Rate [1 - 100 percent]) ");
interest = Double.parseDouble(interestString);
}
if (interest < 0 || interest > 100)
{
JOptionPane.showMessageDialog(null, "Data Error: The interest amount must be between 1 and 100. You entered " + interest);
return;
}
else
{
String monthsString = JOptionPane.showInputDialog("Enter the number of months");
months = Double.parseDouble(monthsString);
}
if (months <= 0)
{
JOptionPane.showMessageDialog(null, "Data Error: The number of months must be above 0. You entered " + months);
return;
}
else
{
switch (optionInt)
{
// Case for simple intrest
case 1: optionInt = 1;
months = months/monthsInYear;
totalInterest = pa * (interest/100.0) * months;
JOptionPane.showMessageDialog(null, "The total amount of interest of your loan is $" + totalInterest + ".");
break;
// Case for monthly compounded interest
case 2: optionInt = 2;
interest = interest/100.0;
years = months/monthsInYear;
double exponent = months*years;
double interestOverMonths = 1+interest/months;
double thirdTotal = Math.pow(interestOverMonths, exponent);
double secondTotal = pa*thirdTotal;
totalInterest = secondTotal - pa;
JOptionPane.showMessageDialog(null, "The total amount of interest of your loan is $" + totalInterest + ".");
break;
// Case for daily compounded interest
case 3: optionInt = 3;
interest = interest/100.0;
double days = months*daysInMonth;
years = days/daysInYear;
exponent = days*years;
double interestOverDays = 1+interest/days;
thirdTotal = Math.pow(interestOverDays, exponent);
secondTotal = pa*thirdTotal;
totalInterest = secondTotal - pa;
JOptionPane.showMessageDialog(null, "The total amount of interest of your loan is $" + totalInterest + ".");
break;
}
}
again = JOptionPane.showInputDialog("Would you like to compute another loan? (yes or no)");
}
}
}
Break is very useful for stopping loops as you said you wanted. Essentially it has the effect of setting the boolean parameter of a for loop to true.
You can of course, use what in CMD is referred to a GOTO. you can create something like:
top:
for(int i = 0; i < 10; i++){
if(i == 9){
break top;
}
}
I've skimmed through your code and to be honest, I don't know much about loans and the calculations associated with it.
As you're clearly still learning the basics, a simple solution by the looks of it would be to take out:
while (again.equalsIgnoreCase("yes" ))
{
/*
* FROM HERE
*/
String option = JOptionPane.showInputDialog("Which type of loan would you like to find interest for? \n1 = Simple Interest \n2 = Monthly Compounded Interest \n3 = Daily Compounded Interest");
int optionInt = Integer.parseInt(option);
//...
/*
* TO HERE
*/
again = JOptionPane.showInputDialog("Would you like to compute another loan? (yes or no)");
}
And put it in its own method called for example:
public static void askAndProcessDetails()
So when you return you will go to the repeat dialogue.
while (again.equalsIgnoreCase("yes" ))
{
askAndProcessDetails();
again = JOptionPane.showInputDialog("Would you like to compute another loan? (yes or no)");
}
continue is maybe one of the worse feature of java, with the break keyword (except in switch statements). It leads to jigsaw code where you have to find out where the code jumps. One continue may be practical but it gets very hard to change the code it produces (think about adding an inner loop..), and 2 continues will make you crazy.
You can always avoid using continue, there is always another solution. Same for break.
Here, why don't you just use some kind of
if( answerIsValid ) {
//process it
...
}//if
That's easy, simple, clear and even better when you have a separate method that contains processing.
Also, in your case, that is tied to robustness, you could provide a process() method that throws an exception if the data entered is not valid. This makes it even more clear that there is a "normal" program behavior and a bunch of strange cases you handle as errors.
public void processAnswer( String stringAnswer ) throws ArithmeticException {
int answer = Integer.parseInt( stringAnswer );
//rest of processing
...
}//met
then your main loop becomes
String again = "yes";
while (again.equalsIgnoreCase("yes" ))
{
String stringAnswer = JOptionPane...
try {
process( stringAnswer );
} catch( ArithmeticException ex ) {
JOptionPane.showMessageDialog( "This is not an integer !" );
}//catch
}//while