is there any way I could make this code shorter? - java

This is a simple code, however, I wanna know if I could somehow make it shorter, I don't know that much to even know what to look for, so I'm not looking for someone to rewrite if for me, I only want someone to tell me what methods should I use, how do I call a variable the user wrote outside if, or such things that would help me. I'm new to coding, so sorry if I'm making a stupid question.
System.out.println("Write name: ");
name = s.nextLine();
System.out.println("Write last name: ");
lastName = s.nextLine();
System.out.println("Write id: ");
id = s.nextInt();
System.out.println("Write your average GPA: ");
average = s.nextDouble();
System.out.println("Your name is:" +name+ "\nYour last name is: "
+lastName+ "\nYour GPA is: " +average+ "\nYearly tuition is: "
+tuitionCost);
if(average >= 9.0){
System.out.println("Your discount is: 20% off.");
d = 100-20;
total = (d * tuitionCost)/100;
System.out.println("Your yearly tuition is: " +total);
}
else if(average <= 8.99 && average >= 8.5){
System.out.println("Your discount is: 10% off.");
d = 100-10;
total = (d * tuitionCost)/100;
System.out.println("Your yearly tuition is: " +total);
}
else if(average <= 8.49 && average >= 8.0){
System.out.println("Your discount is: 5% off.");
d = 100-5;
total = (d * tuitionCost)/100;
System.out.println("Your yearly tuition is: " +total);
}
else{
System.out.println("You have no discount. Your yearly tuition is: "
+tuitionCost);
}

You could turn your discounts into a class:
class Discount {
private final List<Tier> tiers = List.of(
new Tier(0.0, 0), new Tier(8.0, 5), new Tier(8.5, 10), new Tier(9.0, 20));
private class Tier {
private final double gpa;
private final int discount;
}
private int discount(double gpa) {
return tiers.stream().filter(t -> t.gpa <= gpa)
.mapToDouble(t -> t.discount).max().getAsDouble();
}
public double tuition(double gpa, double base) {
return (1.0 - discount(gpa)/100.0) * base;
}
public String discountMessage(double gpa) {
if (discount(gpa) == 0)
return "You have no discount";
else
return "Your discount is " + discount(gpa) + "%";
}
}
I've left some details out but you get the idea.
This may be overkill - it would depend on how often the tiers might change. But it does satisfy the DRY principle (don't repeat yourself). This makes your code more resilient: it's less likely you will change your code in one place and forget to change it elsewhere.
You mention making your code shorter. I subscribe to the principle that you should look for clarity before brevity.

Well, the logic certainly could be simplified a little: if you are careful to write the if..else if sequence in descending order, your logic could simply be:
/* CAUTION: KEEP IN DESCENDING ORDER! ... yes, add this comment! */
if (average >= 9.0) {
}
else if (average >= 8.5) {
}
... and so on. (Which also makes each of the if-conditions consistent.)
Now, be very careful that your else case does all of the things that all of the other cases do: it should assign values to d and to total. It should "look exactly like all the other ones."
Beyond that, I probably wouldn't change a single thing, and here's why: the logic is now "fairly obvious at first glance," and each of the cases are clearly independent. If "the marketing department" suddenly comes up with a grand new idea which only applies to some of the cases but not others ... (and marketing departments always do) ... you're covered. Future programmers could simply "make small, targeted commits" to this logic and they'd never have to re-write it.

Yes, you could simplify by
int discount = -1;
if(average >= 9.0){
discount = 20;
}
else if(average <= 8.99 && average >= 8.5){
discount = 10;
}
.
.
System.out.printf("Your discount is: %d%% off.%n", discount);
d = 100-discount;
total = (d * tuitionCost)/100;
System.out.println("Your yearly tuition is: " +total);
Note
The if-else could be better as a swtich

Related

Simplified way to scan values in?

Current i am scanning in 4 exam score grades, each to their own variable that has been declared and initialized. I was wondering if there was better way i should be doing this to make it less clutters. Please bear with me though as i am currently in my first java class at uni and dont have any prior experience so i dont want the solution to be super complex, not yet at least but something easily understandable. Not sure if it helps/matters but i am using BlueJ as my IDE.
import java.util.*;
public class GradeCalculatorDriver
{
public static void main(String [] args){
String s1 = "student";//Declare student string variable;
String s2;
double exam1 = 0;//Declare and initalize variables.
double exam2 = 0;//Declare and initalize variables.
double exam3 = 0;//Declare and initalize variables.
double exam4 = 0;//Declare and initalize variables.
do{
Scanner input = new Scanner(System.in);
System.out.println("This program will calculate the average of 4 exam scores, and return the lowest, highest, and letter grade associated with the average");
System.out.println("Please enter the name of the student");//Request student name and scans it into a string.
String student = input.next();
System.out.println("Please enter one exam score, then hit enter and repeat for following grades.");//Request exam scores and scan them into variables.
exam1 = input.nextDouble();
exam2 = input.nextDouble();
exam3 = input.nextDouble();
exam4 = input.nextDouble();
double highest = GradeCalculator.high(exam1, exam2, exam3, exam4);//Calls highest grade method.
double lowest = GradeCalculator.low(exam1, exam2, exam3, exam4);//Calls lowest grade method.
double average = GradeCalculator.avg(exam1, exam2, exam3, exam4);//Calls average grade method.
char letterGrade = GradeCalculator.letter(exam1, exam2, exam3, exam4);//Calls letter grade method.
System.out.printf("The highest exam score is : %.2f " + highest);//Displays highest grade.
System.out.printf("The lowest exam score is : %.2f " + lowest);//Displays lowest grade.
System.out.printf("The average exam score is : %.2f " + average);//Displays average grade.
System.out.print("The letter grade is " + letterGrade);//Displays letter grade associated with average.
System.out.println("Would you like to enter another students grades? (yes/no)");//asks the user if they would like to calculate another factorial.
s2 = input.next();
} while (s2.equalsIgnoreCase("YES"));//checks to see what the users response was.
System.out.print("Thank you for using my program!");//Ending statement.
}
}
public class GradeCalculator{
public static double high(double exam1, double exam2, double exam3, double exam4){//Calculates the highest exam score entered.
double highest;//Declare and initilize variable.
highest = Math.max(Math.max(Math.max(exam1, exam2), exam3), exam4);
return highest;//Returns highest exam score.
}
public static double low(double exam1, double exam2, double exam3, double exam4){//Calculates the lowest exam score entered.
double lowest = 0;//Declare and initilize variable.
lowest = Math.min(Math.min(Math.min(exam1, exam2), exam3), exam4);
return lowest;//Returns highest exam score.
}
public static double avg (double exam1, double exam2, double exam3, double exam4){//Calculates the average exam score.
double average;//Declare variable.
double count = 4;//Declare and initilize variable.
average = ((exam1 + exam2 + exam3 + exam4) / count);
return average;//Returns average grade.
}
public static char letter (double exam1, double exam2, double exam3, double exam4){//Calculates the letterGrade based on the average exam score.
char letterGrade;//Declare and initilize variable.
double count = 4;//Declare and initilize variable.
double average = ((exam1 + exam2 + exam3 + exam4) / count);//declare and calculate average score.
if (average >= 90)
letterGrade = 'A';
else if (average >= 80)
letterGrade = 'B';
else if (average >= 70)
letterGrade = 'C';
else if (average >= 60)
letterGrade = 'D';
else
letterGrade = 'E';
return letterGrade;//Returns letter grade.
}
}
You can use a List<Double> scores = new ArrayList<>() to hold the exam score values and reduce code clutter. Then as you added new exam scores from user input, you would call scores.add(input.nextDouble()) for each input value.
Well, in my opinion, if this is your first kick at the cat (so to speak) then you're well on your way to being a successful Java programmer. As for reducing clutter, I suppose it depends upon what you have already learned, like the Java methods and statements already covered and are now at your disposal to create an application to accomplish the task at hand. There is really no way to know the extent of your learning and therefore the suggestions provided below should only be defined as mere suggestions:
There is nothing wrong with your current model other than a few minor errors which will generate a MissingFormatArgumentException and that is within the code lines:
System.out.printf("The highest exam score is : %.2f " + highest);
System.out.printf("The lowest exam score is : %.2f " + lowest);
System.out.printf("The average exam score is : %.2f " + average);
Any errors within your code should be repaired first. Each of the code lines above contains a fault and it's simply because there is no argument supplied for the format specifier (%.2f). This is because you placed a plus (+) character in place of where a comma separator character is to go so as to indicate the argument for %.2f to represent. In this case the + will append the following string or variable content to the string before it. The code should be:
System.out.printf("The highest exam score is : %.2f ", highest);
System.out.printf("The lowest exam score is : %.2f ", lowest);
System.out.printf("The average exam score is : %.2f ", average);
Or just utilize the String.format() method:
System.out.println("The lowest exam score is: " + String.format("%.2f",lowest));
System.out.println("The highest exam score is: " + String.format("%.2f", highest));
System.out.println("The average exam score is: " + String.format("%.2f", average));
Declaring Scanner should not be done upon every iteration of your do/while loop. Place this declaration above the do/while code block so as not to open unnecessary instances of Scanner.
Explaining application functionality does not need to be done upon each iteration of the do/while loop. Move this message above the do/while code block.
When prompting for User input don't use the Scanner#next() method unless you are expecting to receive string tokens. Sometimes it's just plain easier to use the Scanner#nextLine() method. In my opinion I feel it can give more flexibility and allows you a better opportunity to prevent possible exceptions (don't rely on exceptions if you can prevent them).
Believe it or not...sometimes comments can be the biggest source of code clutter. There is absolutely no need to comment the obvious. Yes, I might have done so but it's only so as to explain the code. It is expected to be deleted.
You can get rid of the code line: String s1 = "student";//Declare student string variable;. You don't seem to use this variable anywhere.
As already suggested an array or collection mechanism can be used to hold student scores however in the sense of reducing clutter, it won't for a mere 4 scores but it will for many more scores and therefore is a good way to handle this portion of the code. It is still a good way to go in any case if your course has already covered the use of Arrays and or ArrayLists. Not sure if your requirements are to utilize only what you've already learned. In any case....
To utilize an array to store Student scores you would also need to modify all your methods within the GradeCalculator Class. This in itself will remove parameter clutter since all you would need is a single parameter instead of 4 for each method. The methods in that class might look something like this if you want to use Arrays:
public class GradeCalculator {
public static double high(double[] exams) {//Calculates the highest exam score entered.
double highest = 0.0d;//Declare and initilize variable to 0.0
for (int i = 0; i < exams.length; i++) {
if (exams[i] > highest) {
highest = exams[i];
}
}
return highest;//Returns highest exam score.
}
public static double low(double[] exams) {//Calculates the lowest exam score entered.
double lowest = exams[0];
for (int i = 0; i < exams.length; i++) {
if (exams[i] < lowest) {
lowest = exams[i];
}
}
return lowest;//Returns lowest exam score.
}
public static double avg(double[] exams) {//Calculates the average exam score.
double average = 0.0d; //Declare variable.
double sum = 0.0d;
for (int i = 0; i < exams.length; i++) {
sum+= exams[i];
}
average = sum / exams.length;
return average; //Returns average grade.
}
//Calculates the letter-Grade based on the average exam score.
public static char letter(double average) {
char letterGrade;//Declare and initilize variable.
if (average >= 90) {
letterGrade = 'A';
}
else if (average >= 80) {
letterGrade = 'B';
}
else if (average >= 70) {
letterGrade = 'C';
}
else if (average >= 60) {
letterGrade = 'D';
}
else {
letterGrade = 'E';
}
return letterGrade; //Returns letter grade.
}
}
The letter() method only ever needed one parameter instead of the 4 you had forced to provide and that is the value that is returned from the average() method. You see, you don't need to calculate the average again within the letter() method since you already have a method that does, and has done that. Just pass the already calculated average to the letter() method.
To fill an array with User input it's best to carry out the task using a loop of some sort but then again, it depends upon exactly how you want the User to provide that information (like Test Scores). Perhaps you would like the User to supply all the scores from a single input by separating each score with a white-space:
Please enter all student scores (separated with a space):
65 112 75 88
The code for this might look something like this:
String s2;
boolean invalidEntry;
String LS = System.lineSeparator();
double[] exams; // Declare Array
Scanner input = new Scanner(System.in);
System.out.println("This program will calculate the average of any number of "
+ LS + "desired exam scores and return the lowest, highest, and "
+ LS + "letter grade associated with that determined average." + LS);
do {
s2 = "";
invalidEntry = false;
// Request Student Name
System.out.println("Please enter the name of the student (nothing to exit):");
String student = input.nextLine();
if (student.equals("")) { break; }
// Request exam scores
System.out.println("Please enter all student scores (each separated with a space): ");
String scores = input.nextLine();
// If nothing was supplied break out of loop
if (scores.equals("")) {
invalidEntry = true;
break;
}
String[] scoresArray = scores.split("\\s+"); // Split the input into single scores (regex "\\s+" is used to split on one or more whitespaces).
exams = new double[scoresArray.length]; // Initalize Array.
// Convert scores to double data type...
for (int i = 0; i < scoresArray.length; i++) {
/* Is the string value actually a numerical signed
or unsigned integer or double type value. Save
this Regular Expression. It's handy to have. */
if (scoresArray[i].matches("-?\\d+(\\.\\d+)?")) {
exams[i] = Double.parseDouble(scoresArray[i]);
}
else {
System.out.println("One or more of the Scores supplied are invalid! "
+ "Enter Student Scores again!" + LS);
invalidEntry = true;
break;
}
}
if (invalidEntry) { continue; } // Redo loop on Invalid Entry
double highest = high(exams);
double lowest = low(exams);
double average = avg(exams);
char letterGrade = letter(average);
System.out.println(LS + "Results For Student: " + student);
System.out.println("From " + String.format("%02d" , exams.length) +
" exam scores: " +
Arrays.toString(exams).replaceAll("[\\[\\]]", ""));
System.out.println("The lowest exam score is: " + String.format("%.2f",lowest));
System.out.println("The highest exam score is: " + String.format("%.2f", highest));
System.out.println("The average exam score is: " + String.format("%.2f", average));
System.out.println("The letter grade is: " + letterGrade + LS);
while (s2.equals("")) {
System.out.println("Would you like to enter another Students Scores? (yes/no)");
s2 = input.nextLine();
if (!s2.equalsIgnoreCase("yes") && !s2.equalsIgnoreCase("no")) {
System.out.println("Invalid Response! 'Yes' or 'No' only!");
s2 = "";
}
}
} while (s2.equalsIgnoreCase("yes") || invalidEntry);
System.out.println("Thank you for using my program!");
Sometimes it is just easier for the User to enter all the scores on one line as demonstrated within the above code however, you set the rules towards how your application is to function. If you want each score to be entered individually then so be it. The code might then look something like this:
String s2;
int indexCounter; // Declare an index counter for array.
boolean invalidEntry;
String LS = System.lineSeparator();
double[] exams; //Declare Array.
Scanner input = new Scanner(System.in);
System.out.println("This program will calculate the average of any number of "
+ LS + "desired exam scores and return the lowest, highest, and "
+ LS + "letter grade associated with that determined average." + LS);
do {
s2 = "";
indexCounter = 0; // Set index counter to 0
invalidEntry = false;
// Request Student Name
System.out.println("Please enter the name of the Student (nothing to exit):");
String student = input.nextLine();
if (student.equals("")) { break; }
// Get number of Scores to enter from User
int numberOfScores = 0;
while (numberOfScores == 0) {
System.out.println("Please enter the number of scores you wish to enter:");
String numScores = input.nextLine();
// Is the value supplied a String Integer value
if (!numScores.matches("\\d+")) {
System.out.println("Invalid number of scores provided! Try Again..." + LS);
continue;
}
numberOfScores = Integer.parseInt(numScores);
}
exams = new double[numberOfScores]; // Initialize Array
// Request exam scores
while (indexCounter < numberOfScores) {
System.out.println("Please enter exam score #" + (indexCounter + 1) +
" then hit enter: ");
exams[indexCounter] = input.nextDouble();
input.nextLine(); // Clear the scanner buffer
indexCounter++;
}
double highest = high(exams);
double lowest = low(exams);
double average = avg(exams);
char letterGrade = letter(average);
System.out.println(LS + "Results For Student: " + student);
System.out.println("From " + String.format("%02d" , exams.length) +
" exam scores: " +
Arrays.toString(exams).replaceAll("[\\[\\]]", ""));
System.out.println("The lowest exam score is: " + String.format("%.2f",lowest));
System.out.println("The highest exam score is: " + String.format("%.2f", highest));
System.out.println("The average exam score is: " + String.format("%.2f", average));
System.out.println("The letter grade is: " + letterGrade + LS);
while (s2.equals("")) {
System.out.println("Would you like to enter another Student's Scores? (yes/no)");
s2 = input.nextLine();
if (!s2.equalsIgnoreCase("YES") && !s2.equalsIgnoreCase("NO")) {
System.out.println("Invalid Response! 'Yes' or 'No' only!");
s2 = "";
}
}
} while (s2.equalsIgnoreCase("YES") || invalidEntry);
System.out.println("Thank you for using my program!");
You will have noticed that some of the code above takes advantage of Regular Expressions such as "\\s+", "\\d+", "[\\[\\]]", or even "-?\\d+(\\.\\d+)?". It's never to late to learn how to utilize Java's java.util.regex package for pattern matching. It can quickly become a close friend for you and once learned, you will find yourself using it all the time. To test Regular Expressions and to get explanations of what a particular expression does you can use the website RegEx101.com for example: this regex.

How would you write Junit tests for this code?

Im new to java and practising my coding, how would I write some Junit tests for this code without changing it? I wanted to write some Junits to see if the output is correct. Could someone provide one such example?
Any help is greatly appreciated.
package returnOnInvestment;
import java.util.Scanner;
/**
This program compares CD /Investment plans input by the year
broken down by the requirements below:
This program creates a table of compound interest investment growth over time
Broken down by: a) year b) balance at end of year
Finance formula of A= P(1+ r/n)^n*t is used:
A = Future Value | P = Initial Investment
r = annual interest rate |n = times interest is compounded/year
t = years invested
*/
public class BestInvesment
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
String bestBankName = "";
double bestGrowth = 0;
boolean done = false;
while(!done)
{
System.out.print("Plan name (one word, Q to quit): ");
String bankName = in.next();
if (bankName.equals("Q"))
{
done = true;
}
else
{
System.out.print("Please enter your principal investment: ");
final double PRINCIPAL_INVESTMENT = in.nextDouble();
System.out.print("Please enter the annual interest rate: ");
double iRate = in.nextDouble();
System.out.print("Please enter number of times interest is compounded per year: ");
final double INCREMENT = 1;//in.nextDouble();
System.out.print("Enter number of years: ");
int nyears = in.nextInt();
iRate = iRate/100; System.out.println("iRate:" + iRate);
//Print the table of balances for each year
for (int year = 1; year <= nyears; year++)
{
double MULTIPLIER = INCREMENT * year;
System.out.println("Multiplier: " + MULTIPLIER); // I've included this print statement to show that the multiplier changes with each passing year
double interest = 1 + (iRate/INCREMENT);
double balance = PRINCIPAL_INVESTMENT;
double growth = balance * Math.pow(interest, MULTIPLIER);
growth = growth - PRINCIPAL_INVESTMENT;
balance = balance + growth;
System.out.printf("Year: %2d Interest Earned: $%.2f\t Ending Balance: $%.2f\n", year, growth, balance);
if (bestBankName.equals("") || bestGrowth > growth) // || bestBankName > growth
{
bestBankName = bankName; // bestBankName = bankName
bestGrowth = growth; // mostGrow = growth
}
System.out.println("Earning with this option: " + growth);
}
}
}
System.out.println("Best Growth: " + bestBankName);
System.out.println("Amount Earned: " + bestGrowth);
}
}
As it is, this code is very difficult to test, which it is a symptom of some design smells.
One thing to realize is that you are severely violating the Single Responsibility Principle.
Your code which is just one blob is doing the following things:
printing stuff to console
getting input from the user
doing some calculation
coordinating all this
Since this is in the realm of practicing, I would heavily refactor the code into separate classes. Those then should be easily testable, especially the one doing the calculation, since it will have just some simple methods where you can pass some values as arguments, and check the results
For testing the input and output classes note that you can change System.in and System.out to point to your own implementations, so you can create those to facilitate testing. You might want to look into a mocking framework for this (e.g. Mockito) but it is perfectly possible without such framework.

Java pseudocode to code [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I'm about to build a program written in Java. I've already done its pseudocode, but I'm stuck on the code and I don't know what to do exactly. Well this is my progress so far:
pseudocode:
class Customer
Print out “Enter costumer’s name” (Pop up to answer)
Random boolean
If True
print membership type
print current date and time
class Visit
Print out "Have you bought anything?" (Pop up to answer)
if the answer is “no”
print “Have a nice day!”
exit program
if else the answer is “yes”
continue
if else the answer is not “no” nor “yes”
ask again
class Discount
Print "Enter Price of Item:" (Pop up to price)
if customer's membership type is “Premium”
the discount to the price will be 20%
else if customer's membership type is “Gold”
the discount to the price will be 15%
else if customer's membership type is “Silver”
the discount to the price will be 10%
else if customer's membership type “simple”
the discount to the price will be 10%
class Main
Variables: customer, visit, discount
customer = new object
Customer visit = new object
Visit discount = new object Discount
do work with customer
do work with visit
do work with discount
Print customer.name, customer.surname, discount.price, discount.final_price
code:
import java.util.Scanner;
public class Discount
{
public static void main(String[] args)
{
String cust_name;
String cust_surname;
String answer;
String answer2;
float firstPrice, rate_1, D_rate, discount, final_price, prem_disc;
prem_disc = 0;
final_price = 0;
discount = 0;
Scanner in = new Scanner(System.in);
System.out.println("Enter Costumer's Name:");
cust_name = in.next();
cust_surname = in.next();
System.out.println("Have you bought anything?");
answer = in.next();
if (answer.equals("no"))
{
System.out.println("Have a good day!");
System.exit(0);
} else if (!answer.equals("no"))
System.out.println("Enter Price of Item:");
firstPrice = in.nextFloat();
System.out
.println("What type of membership do you have? Premium, Gold, Silver or simple?");
answer2 = in.next();
if (answer2.equals("Premium"))
{
prem_disc = 20;
discount = (firstPrice * 20 / 100);
final_price = (firstPrice - discount);
} else if (answer2.equals("Gold"))
{
prem_disc = 15;
discount = (firstPrice * 15 / 100);
final_price = (firstPrice - discount);
} else if (answer2.equals("Silver"))
{
prem_disc = 10;
discount = (firstPrice * 10 / 100);
final_price = (firstPrice - discount);
} else if (answer2.equals("simple"))
{
prem_disc = 10;
discount = (firstPrice * 10 / 100);
final_price = (firstPrice - discount);
}
System.out.println("Costumer Name:" + cust_name + " " + cust_surname
+ "\n" + "Discount Rate:" + prem_disc + "\n"
+ "Discounted Price:" + final_price + "\n");
}
}
It's working, but there are many things that are missing. :/
Just take one step at a time, and when that step completely works, proceed to the next step.
An example:
Here's your pseudo-code (which, by the way, is a great way to start):
class Visit
Print out "Have you bought anything?" (Pop up to answer)
if the answer is “no”
print “Have a nice day!”
exit program
if else the answer is “yes”
continue
if else the answer is not “no” nor “yes”
ask again
Let's just implement and test the "is the answer yes-or-no" functionality:
/**
<P>{#code java MyHomeworkMainClass}</P>
**/
public class MyHomeworkMainClass {
public static final void main(String[] ignored) {
System.out.println("Visit.isUserInputYesNo(null)=" + Visit.isUserInputYesNo(null));
System.out.println("Visit.isUserInputYesNo(\"gibberish\")=" + Visit.isUserInputYesNo("gibberish"));
System.out.println("Visit.isUserInputYesNo(\"yes\")=" + Visit.isUserInputYesNo("yes"));
System.out.println("Visit.isUserInputYesNo(\"no\")=" + Visit.isUserInputYesNo("no"));
}
}
class Visit {
public static final boolean isUserInputYesNo(String input) {
return (input != null &&
(input.equals("yes") || input.equals("no")));
}
}
Now run it and see if it does what you want:
[C:\java_code\]java MyHomeworkMainClass
Visit.isUserInputYesNo(null)=false
Visit.isUserInputYesNo("gibberish")=false
Visit.isUserInputYesNo("yes")=true
Visit.isUserInputYesNo("no")=true
It does. Now add something else small to this and just keep going until you're done. For particularly difficult parts, it may be beneficial to create a completely separate class, with its own testing class. Then at the end, merge it all together. And never get rid of your testing functions, which will always be there for diagnosing future problems.
Good luck!

How do I add all results from my loop

Question Answered: Thank you everyone for the help!!!
i'm having a bit of trouble with finishing my code mainly because I'm really new to coding, but nonetheless I'm still trying. Any help is greatly appreciated!
I have 3 problems:
My main problem is that i do not understand how to get my code to add all the totals from each loop.
Also, after the loop starts it won't end when I enter '0' anymore, but if i end the loop when i first run the loop it will work.
Finally, how do i make the decimal total to show up in this format; xx.xx rather than xx.xxxxxxx?
Thank you in advance, i really appreciate any help
import java.util.Scanner;
public class takeOrders {//Find totals and average price
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int euro; // what country the candy canes are from
int us;// what country the candy canes are from
int holder; //place holder for user input of location
int v110 = 0; //110v
int v240 = 0; //240v
int sum = 0, i = 1;
double total = 0;
double discount = 0;
do {
//Prompt what country the order is for
System.out.println("What country is the order for? (press '0' to see the Net Total of order) ");
System.out.println("1: Europe\n2: U.S.");
holder = input.nextInt();
// 110 or 240 voltage
if (holder == 1) {
//How many boxes are ordered EUROPE
System.out.println("Input number of 240v boxes needed");
v240 = input.nextInt();
total = 2.40 * v240;
System.out.println("Order total: $" + total);
} else if (holder == 2) {
// How many boxes are ordered US
System.out.println("Input number of 110v boxes needed");
v110 = input.nextInt();
total = 2.40 * v110;
}
// Discount for U.S.
if (holder == 2) {
if (v110 >= 3)
discount = total * .05;
} else if (v110 >= 10) {
discount = total * .10;
}
if (discount > 0) {
System.out.println("Order total: $" + total);
System.out.println("Total with Discount: $" + (total - discount));
}
} while ((v240 != 0) || (v110 != 0));
}
}
In order to finish the loop i would use holder instead of v110 and v240 this way you dont need to enter a country and then an order amount.
The problem can be due to that if you first select US and enter a value this value is retained until you enter again US an another amount so your loop wonth end unless you select allways the same country and then select 0 as amount
To accumulate total you should do
total += 2.40*v240;
or
total=total+(2.40*v240);
This way the total amount will get increased on each loop
In order to format the output you can use this code fragment:
DecimalFormat df = new DecimalFormat("#.##");
System.out.print(df.format(total));
I hope this may help you to familiarize with programming and Java.
Once you capture an input, your while condition can never be true, hence the infinite loop. Instead of
while ((v240 != 0) || (v110 != 0));
try
while (holder != 0);
Either that, or you will need to reset v240 and v110 to zero each time you repeat the loop.
Using printf is the simplest to achieve this.
System.out.printf("%.2f", total);
So for your case:
System.out.printf("Order total: %.2f", total);
You can also use DecimalFormat to show up to the digit you want to print.
import java.text.DecimalFormat;
DecimalFormat df = new DecimalFormat("#.##");
System.out.println("Order total: $" + df.format(total));

JAVA: Runtime Exception (I think that's what i need to use)

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

Categories

Resources