Java method passing/ordered logic inquiry - java

Let me first make it clear that this is for an assignment. I'm very new to programming so all guidance is greatly appreciated. The program I have to calculate is a parking fee charge for a $2.00 minimum for 3 hrs or less, .50 cents per additional hr, and charge is capped at $10/ per 24 hr period. Program must display most recent customer charge as well as running total. Constants must be initialized, Math.ceil must be used, and method calculateCharges must be used to solve each cust's charge. I get uber errors when I attempt to run this program, and you'll probably laugh when you see it, but where have I erred? I'm not looking for the answer to be handed to me, just looking for the logic behind how to get to the correctly written program. Please help!
package Parking;
import java.util.Scanner;
public class parking
{
private static final double THREE_HOURS = 2.00;
private static final double PER_HOUR_COST = .50;
private static final double WHOLE_DAY_COST = 10.00;
public static void main (String [] args)
{
double hoursParked = 0;
double cumulativeCharges = 0;
double storage1 = 0;
double storage2 = 0;
Scanner input = new Scanner(System.in);
System.out.print("\nThis program displays the charge for the most recent customer");
System.out.print(" as well as the running total of yesterday's receipts\n");
do
{ System.out.printf("Enter an number between 1-24 for hours parked in garage or -1 to quit:");
hoursParked = input.nextDouble ();
}
while((hoursParked > 0)&&(hoursParked <= 24)&&(hoursParked != -1));
if( hoursParked <= 3)
System.out.printf("Most recent customer's charge was: %.2f\n" , THREE_HOURS);
storage1 += THREE_HOURS;
if(hoursParked >= 18.01)
System.out.printf("Most recent customer's charge was:%.2f\n" , WHOLE_DAY_COST);
storage2 += WHOLE_DAY_COST;
double result = calculateCharges(hoursParked * PER_HOUR_COST);
System.out.printf("Most recent customer charge was:%.2f\n" , result);
cumulativeCharges = storage1 + storage2;
System.out.printf("Running total of yesterday's receipts is:%.2f\n" , cumulativeCharges);
} // end main
public static double calculateCharges (double hoursParked)
{
Math.ceil(hoursParked);
double total = hoursParked * PER_HOUR_COST;
return total;
} // end method calculateCharges
} // end class parking

In your while condition, the third condition is useless because if the value is positive, that necessarily means it is different than -1.
In your function you want to calculate the cost of parking time but you give as parameter a cost instead of a number of hours when you call your function. Is that normal? With that you will calculate the cost of the cost instead of the cost corresponding to a number of hours.
public static double calculateCharges (double hoursParked)
and
double result = calculateCharges(hoursParked * PER_HOUR_COST);

There's a couple things here.
Your while condition is checked at the end of the do loop, it is what allows you to break after reading hoursParked. Thus, the only way you are going to reach the code outside of the do loop (after the while), is if hoursParked is -1.
Secondly, when you do not have braces for your if conditions, you are only executing the first line after it, aka. the System.out.print's. Therefore, your first if condition will execute (printing the string), then storing 2.00 in storage1. Similarly, the second if condition will execute (printing the string), then storing 10.00 in storage2.
Because hoursParked is always -1, you are passing in (-1 * .5) to calculateCharges. You are not storing the result of Math.ceil() so it effectively does nothing. You are then returning (-.5 * .5) = -.25.
cumulativeCharges is just adding 2 + 10 in every case.
Suggestions - make sure you are encapsulating the code you want to execute inside the do loop, and only break after you have done your calculations on hoursParked.

Related

How come my program freezes up when I click calculate?

Here is my code:
private void btnCalculateActionPerformed(java.awt.event.ActionEvent evt) {
int intInitialInvest = Integer.parseInt(this.txtInputInitialInvest.getText());
int intAnnualInterest = Integer.parseInt(this.txtInputAnnualInterest.getText());
int intEndingValue = Integer.parseInt(this.txtInputEndingValue.getText());
double dblAnnualPercent = intAnnualInterest/100;
int count = 0;
while (intInitialInvest < intEndingValue){
intInitialInvest += (intInitialInvest * dblAnnualPercent);
count += 1;
}
this.lblOutputYears.setText("The number of years required is " + count);
}
This program is supposed to calculate how many years (which is count) it takes for example for a cd with a value of $2000 to become $5000 with an annual interest rate of 8%. This should then return 12. What I did was create a while loop which runs until the $2000 turn into $5000 or more from interest which is expressed by intInitialinvest += (intInitialInvest * dblAnnualPercent);
Every time I run the program by clicking the "Calculate" button, the program freezes and doesn't do anything then I have to go into task manager to close it.
Be careful with integer divisions:
double dblAnnualPercent = intAnnualInterest/100;
causes the value of dblAnnualPercent to be 0.0, and thus you run into an infinite loop. You perform an integer division (e.g 8/100=0) then convert to double (0.0, not 0.05 as you would have expected).
double dblAnnualPercent = intAnnualInterest/100.;
should fix your bug.
Hint: add assertions, run your problem with assertions enabled.
assert(dblAnnualPercent > 0.);
would have saved you (assuming you run your program with -ea).
But also try to solve your problem without a loop. There is a closed form solution to your problem, using math instead of loops... that solution is one line only.
If intInitialInvest=0 or dblAnnualPercent=0 and intEndingValue > 0 you'll loop forever.
while (intInitialInvest < intEndingValue){
intInitialInvest += (intInitialInvest * dblAnnualPercent);
count += 1;
}
You have to test your values before you enter the loop, especially as you seem to read these values from some input. This is a possible attack vector, even when you assert on these values, as your algorithm breaks, when someone feeds input that makes intInitialInvest=0 or intAnnualInterest<100.

Debugger stops working

My program needs to allow the user to input an employee's name and total annual sales. When the user is finished adding employees to the array, the program should determine which employee had the highest sales and which had the lowest sales. It should then print out the difference between the two numbers.
In my code below, I have a totalPay class that holds the annual sales input by the user (it includes other variables and methods from a previous assignment that are not used here). The salesPerson class holds the employee's name and totalPay object, which includes their annual sales. (I realize this is overcomplicated, but I'm modifying my previous assignment rather than starting from scratch.)
When I run this code, it allows me to enter the name and sales, but when I enter "yes or no" to add another employee, it crashes and tells me there is a NullPointerException on line 58, noted in the code.
I've ran the debugger (without any breakpoints) and it just stops at line 46, noted in the code. It doesn't give an error message, it just doesn't update that variable and my "step into" buttons for the debugger grey out and I can't click them anymore. (I'm using NetBeans, if that's relevant.)
Any ideas would be much appreciated!
EDIT: Here is the output and error message.
Name? captain America
Input annual sales: 80
Add another employee? yes or no
no
Exception in thread "main" java.lang.NullPointerException at commission.Commission.main(Commission.java:58)
package commission;
//Commicaion calulator
import java.util.Scanner;
public class Commission
{
public static void main(String args [])
{
salesPerson[] emps = new salesPerson[10]; //Employee Array
String cont = "yes";
String n="";
double s=0;
int i=0;
salesPerson high = new salesPerson();
salesPerson low = new salesPerson();
// scanner object for input
Scanner keyboard = new Scanner(System.in);
//Enter in employee name
while (cont == "yes"){
System.out.print("Name? ");
n = keyboard.nextLine();
emps[i] = new salesPerson();
emps[i].setName(n);
//Loop of yes or no entering more employees
//If yes add another name if no continue with total Commision
//Enter in the sales amount of commistion
System.out.print("Input annual sales: ");
s=keyboard.nextDouble();
emps[i].pay.annual = s;
System.out.println("Add another employee? yes or no ");
keyboard.nextLine();
cont = keyboard.next(); //Line 46: Debugger stops here.
if (cont =="yes")
i++;
if (i==9){
System.out.println("You have reached the maximum number of employees.");
cont = "no";
}
}
i=0;
for (i=0; i<emps.length; i++){
if (emps[i].pay.annual > high.pay.annual) //Line 58: It claims the error is here.
high = emps[i];
if (emps[i].pay.annual < low.pay.annual)
low = emps[i];
}
double diff = high.pay.annual - low.pay.annual;
System.out.println("Employee "+low.getName()+" needs to earn "+diff+" more to match Employee "+high.getName());
// Output table for composation with increments of $5000
// int tempAnnual =(int) pay.annual;
// for (i=tempAnnual; i<= pay.annual; i+=5000)
// System.out.println(i+" "+ pay.getReward(i));
}
public static class totalPay
{
double salary=50000.0; //Yearly earned 50000 yr fixed income
double bonusRate1=.05; //bounus commission rate of 5% per sale
double commission; //Commission earned after a sale
double annual; //Sales inputted
double reward; // Yearly pay with bonus
double bonusRate2= bonusRate1 + 1.15 ; // Sales target starts at 80%
public double getReward(double annual)
{
double rate;
if (annual < 80000)
rate=0;
else if ((annual >= 80000) || (annual < 100000 ))
rate=bonusRate1;
else
rate=bonusRate2;
commission = annual * rate;
reward=salary + commission;
return reward;
}
}
public static class salesPerson
{
String name; //Employee Name
totalPay pay = new totalPay();
public void setName(String n) //Name
{
name=n;
}
public String getName()
{
return name;
}
}
}
You create this array of max size 10:
salesPerson[] emps = new salesPerson[10];
but only create and assign an object reference for each SalesPerson object entered. Since you only enter 1 name, only the 1st entry in the array is valid, then remaining 9 are null. You then attempt to iterate through the entire array (emps.length is 10 ):
for (i=0; i<emps.length; i++){
if (emps[i].pay.annual > high.pay.annual)
which leads to the NPE when indexing the first null reference. You need to change your loop to something like:
int numEntered = i; //last increment
for (i=0; i< numEnetered; i++){
if (emps[i].pay.annual > high.pay.annual)
It stops the debugger because it waits for your input using the keyboard. If you type the input and hit enter, the debugger will continue from there on.
By the way, your should read up on naming conventions and coding best practices for java
Your debugger is stopped because it's blocked on input coming in from the Scanner. This is specified in the documentation:
Finds and returns the next complete token from this scanner. A complete token is preceded and followed by input that matches the delimiter pattern. This method may block while waiting for input to scan, even if a previous invocation of hasNext() returned true.
That aside, you're fortunate to have entered that code block at all. You're comparing Strings incorrectly, so at a glance it'd look like you wouldn't enter that loop except under certain special circumstances. This is also the reason that your NPE occurs; you're initializing elements of your array under false pretenses (== with a String), so:
You may never initialize anything
You may only initialize the first thing (if (cont =="yes"))
I've only gone over a few of the high points, but for the most part, the blocking IO is why your debugger has stopped. The other errors may become easier to see once you start using .equals, but I'd encourage you to get an in-person code review with a classmate, tutor, or TA. There are a lot of misconceptions strewn about your code here which will make it harder to debug or fix later.

How to solve this program?

I found this Java exercise :
Create a class Sales that has TotalSales (double) , Commission (double),
Commissi onRate (double), and NoOfItems (integer).
write a java application that asks the user to enter the Total Sales and the number of items then calculates the commission and prints it out.
The commission rate should be as following:
Condition :
Less than 500, commissionRate is 0
Greater than or equal 500 or Number of Items >= 5, commission rate is 5%.
Grater than or equal 1000 or Number of items >=10, commission rate is 10%
..
I wrote this code:
Main Class :
import java.util.Scanner;
public class testSales {
public static void main(String[] args) {
Sales s1 = new Sales();
Scanner get = new Scanner(System.in);
System.out.println("Enter total Sales");
s1.totalSale = get.nextDouble();
System.out.println("Enter number of Items");
s1.NoOfItems = get.nextInt();
if(s1.totalSale < 500){
s1.commission = s1.commissionRate = 0;
}
else if(s1.totalSale >= 500 && s1.totalSale <= 999 || s1.NoOfItems >= 5 && s1.NoOfItems <=9){
s1.commission = s1.commissionRate = s1.totalSale * 5 / 100;
}else if(s1.totalSale >= 1000 || s1.NoOfItems >=10) {
s1.commission = s1.commissionRate = s1.totalSale *10/100;
}
System.out.println(s1.commission);
}
}
One problem in your code is the case where NoOfItems > 5 but totalSale < 500. For this case, the commission will incorrectly be set to 0 because the first if statement eats it.
Please try to be more specific with your question. "this doesn't work and I don't know why" is not easy to help with.
Aside from the point brought up by HedonicHedgehog, there are a few other things to consider:
The sales class only has two global variables, which corresponds to the information entered by the user. The other two fields, commission and commissionRate, are calculated values. Therefore, there is no need to create variables for them. Just add to the sales class accessor methods (getters) that return these values. For example, below is my getCommission() method:
public double getCommission()
{
return totalSales * getCommissionRate();
}
Of course, you can see this method is dependent upon the getCommissionRate() method. Because there is a gap on your requirements with total items, I am ignoring it for now:
public double getCommissionRate()
{
if (totalSales < 500)
return 0;
if(totalSales < 1000)
return .05;
else
return 0.1;
}
Alternatively, you could create a LOCAL commission variable, and set the value before returning it. It is a good programming practice to limit the scope of your variables. In this case, there is not a good reason to have a global commission or commissionRate variables.
Lastly, your test class is simplified because all you need to do is to prompt the user for the two needed fields, and it simply spits out the output because the Sales class provides the calculation needed to figure out the rest:
public static void main(String[] args)
{
Sales s1 = new Sales();
Scanner input = new Scanner(System.in);
System.out.print("Enter total Sales");
s1.setTotalSales(input.nextDouble());
System.out.print("Enter number of Items: ");
s1.setNumOfItems(input.nextInt());
System.out.printf("$%.2f", s1.getCommission());
input.close();
}
I used the printf() method to format the output string. The following is a sample run:
Enter total Sales: 503.45
Enter number of Items: 5
$25.17
Enter total Sales: 1003.67
Enter number of Items: 19
$100.37
Enter total Sales: 45.00
Enter number of Items: 19
$0.00
Remember that this example ignores the number of items because of the reasons already mentioned. Once you figure out what needs to be done to cover of the gap in the requirements, you can modify this code to do the rest. Also remember that your Sales class only requires two fields: totalSales and numOfItems. The other to components (commission, and commissionRate) are calculated; therefore, no global variable or setter methods needed. Just the two getter methods I provided.

Lost on how to find the largest price below the target value from a given menu

I am trying to create a method called selectFood that takes the amount of money I have as a parameter, outputs the selections on the screen and returns the percentage tip I will be leaving rounded to one decimal place.
I have the possible costs without tip done through recursion but I need to compare them and find the larger one. Please help
public static void selectFood(double money){
/*String[]menu={"Bandera Pizza Bread","Boston's Pizza Bread","Garlic Twist Bread","Single Order",
"Sun-Dried Tomato Bruschetta","Three Cheese Toast","Double Order wings","Starter Size wings",
"Cactus Nachos","Baked Ravioli Bites","Southwest Quesadilla"};
*/
double[]itemCost={6.49,5.35,7.49,5.35,6.99,6.35,16.49,8.99,10.29,8.49,9.25};
possibilities(itemCost.length,"",itemCost,money);
//selectFood(n,itemCost,0);
}
public static void possibilities(int length,String sofar,double[]itemCost,double money){
if(length==0){
//selectFood(sofar,itemCost,money,0);
float totCost=0;
double target=money/1.15;
double minTip=money-target;
char[]sofarList=sofar.toCharArray();
for(int i=0;i<sofarList.length;i++){
if(sofarList[i]=='1'){
totCost+=itemCost[i];
}
}
if(totCost<target){
System.out.println(totCost);
}
}
else{
possibilities(length-1,sofar+"0",itemCost,money);
possibilities(length-1,sofar+"1",itemCost,money);
}
}
Right now I get back
0.0
8.49
6.35
6.99
5.35
7.49
5.35
6.49
To find the largest value below the target value, you need a variable to hold the current maximum in each iteration you are making thru recursion.
I changed the logic of your program to keep track of the current maximum value
public static void possibilities(int length,String sofar,double[]itemCost,double money){
if(length==0){
//selectFood(sofar,itemCost,money,0);
float totCost=0;
double target=money/1.15;
double minTip=money-target;
char[]sofarList=sofar.toCharArray();
for(int i=0;i<sofarList.length;i++){
if(sofarList[i]=='1'){
totCost+=itemCost[i];
}
}
if(totCost<target && totCost>max){
max = totCost;
System.out.println(totCost);
for(int i=0;i<sofarList.length;i++){
System.out.print(sofarList[i]);
}
System.out.println("\n");
}
}
else{
possibilities(length-1,sofar+"0",itemCost,money);
possibilities(length-1,sofar+"1",itemCost,money);
}
}
and you need to declare the variable max as static inside your class
static double max=0;
I added print statement to show the maximum value chosen in each feasible iteration.
After the end of all iterations the maximum value is stored in the max variable and to keep track of the menu list we need to add one more static variable as given below
static String menulist=null;
and we need to assign the value inside the method possibilities
if(totCost<target && totCost>max){
max = totCost;
menulist = sofarList;
}
The trouble you probably have with your method (besides it being relatively hard to understand) is, that your method is not actually computing a value (well... not returning any at least), but it is printing something to System.out. Generally, your methods should either compute something or alter state (e.g., perform I/O), but not both.
A simple fix would be to store totCost in an instance variable instead of printing it. That is, you can change your lines:
if(totCost < target){
System.out.println(totCost);
}
to
if(totCost < target && highestPrice < totCost){
highestPrice = totCost;
}
where highestPrice is an instance variable. Now you can access highestPrice from the selectFood method.
Note that this is a hack rathar than a clean solution! Your code would be much cleaner if your possibilities method would return the value it computes as the regular return value.
Rethink how you would recursivly compute the cost:
You are given a set (in your case, an array) of prices, and a budget.
For each price you can either take the item and pay the price, or you can not take the item and keep the money
If you have only one item in the list, the most expensive combination you can make is either 0, if you cannot afford the item, or the value of the item, if you can.
The last point is your base-case (not considering that you could also have an empty array). So you have for a base case
double possibilities(double[] items, double money){
if (items.length == 1 && items[0] < money / 1.15) return items[0]; else return 0;
A side note here: Don't put magic numbers (e.g., 1.15) in your code. They do not convey any meaning.
Now for the general case where items.length>1: We can either take the first item, or we can not take it. If we do take it, then we will have less money to spend on the remaining items. Also, we can only take it, if we can afford it, i.e., if money>items[0]. With the remaining money and the remaining items we call the method recursivly and take the bigger value.
if(items.length > 1)
if (items[0] < money / 1.15)
double totCostWithItem0 = items[0] + possibilities(/* items[1 to length], money - items[0] */)
double totCostWithoutItem0 = possibilities(/* items[1 to length], money */)
return totCostWithItem0 > totCostWithoutItem0 ? totCostWithItem0 : totCostWithoutItem0;
else // cannot afford it
return possibilities(/* items[1 to length], money */
Sorry for being so sloppy with the code here. Because you are working with arrays, you need to copy items 1 to length in a new array in order to pass it in the recursive call. Also... I am not quite sure what the division by 1.15 is supposed to do, so you may need to adjust the money you are recursively passing.

Calculate average from sources that sends data at different time.

In my current project, I am going to write a function of calculating average Temperature.
A notatable point of this function is that it receives data from many temperature sources at different time. Could you advise me "How can I write a function with such a behavior?"
For instance, following function receives tempSensorData from many temperature Sensors, which sends temperature data at different time. I need to write a logic of calculating average temperature.
public void calculateRoomAvgTemp(TempStruct tempSensorData) {
// Write logic of calculating Average Temperature.
}
Why don't you just keep a running average? Assuming that your method gets called each time a temperature reading is taken, you can do the following:
private final List<Double> temps = Collections
.synchronizedList(new ArrayList<Double>());
private double currentAverage = 0d;
public void calculateRoomAvgTemp(TempStruct tempSensorData) {
synchronized (this.temps) {
this.temps.add(tempSensorData.temp);
this.currentAverage = 0d;
for (Double temp : this.temps) {
this.currentAverage += temp;
}
this.currentAverage /= this.temps.size();
}
}
can you store past temperatures in a separate field in the class? I noticed that your method is void, therefore doesn't return anything. I'm going to assume you want to store the average in the separate field. Example:
public class TempCalculator {
private double totalTemp = 0;
private int sensors = 0;
private double averageTemp = 0;
public void calculateRoomAvgTemp(TempStruct tempSensorData) {
totalTemp += tempSensorData.getTemp(); // Assuming getTemp() exists
sensors += 1;
averageTemp = totalTemp / sensors;
}
public double getAvgTemp() {
return averageTemp;
}
}
Of course, this can be done with a list if you want to store temperatures used and shaped to your needs. Hope this helps.
one way I could think of - insert values as you receive them into an ArrayList. If you need to calculate the average temperature after each data point that you receive, run through a for loop and average out the data points in the ArrayList to get the required value. One could look into using memoization to avoid running through the loop for all values.
Another option would be to use apache commons math whereby you can use the descriptive statistics option (using a rolling array) to get the mean (average).
I am assuming your code is single threaded. If multithreaded, you could use a thread safe vector (or add locks/synchronization on your own).
Hope this helps.
To calculate the average without keeping all historic values in memory (or a database), use a "moving average". This mathematical tool can give you the new average from the last one plus the current value.
You can create one thread which will calculate the temperature and many which will measure it values from different places. When some measurement is done the thread pushes the result into e.g. LinkedBlockingQueue. It's important to synchronize this operation because many threads might try to push results at the same time. The thread which calculate average temperature would run in a loop, pop new result from the queue, recalculate the temperature and then once again try to pop another result. As far as the queue will be empty the thread would be blocked on reading from it. In this way you would have an asynchronous communication between threads and the average temperature would be recalculated immediately after the measurements are done.

Categories

Resources