Why doesn't this compile, it keeps giving me errors - java

When i compile this it keep giving the error "This method must return a result of type double", but i believe my pay is double. What went wrong?..................................
public double getNetPay (int totalHoursWorked)
{
int basePayRate = 15;
double overTime = 15*1.5;
double taxRate1 = 0.25;
double taxRate2 = 0.21;
double taxRate3 = 0.15;
if (totalHoursWorked > 40)
{
double pay =totalHoursWorked*overTime;
if (pay > 1200)
{
return pay*taxRate1;
}
if (pay >=500||pay <1199)
{
return pay*taxRate2;
}
if (pay <=499)
{
return pay*taxRate3;
}
}
else
{
double pay =totalHoursWorked*basePayRate;
if (pay > 1200)
{
return pay*taxRate1;
}
if (pay >=500||pay <1199)
{
return pay*taxRate2;
}
if (pay <=499)
{
return pay*taxRate3;
}
}
}

You need to add a return statement outside the conditional blocks.
As conditional blocks are not guaranteed to execute always, Java needs to make sure that method always return something as promised.
You can do something like
double defaultTaxRate = 0.33; // put some desired value
if (totalHoursWorked > 40)
{
// All conditional blocks
}
return pay*defaultTaxRate;

Of course your pay is double, but you are returning it from inside a if condition.Java Compiler will give error because if that condition is false then it will not execute that return statement,So you have to see clearly that in any condition something(which is double here) must return.for example:
public int get() {
if(condition) {
return one_integer_value;
} else {
return another_integer_value;
}

There is nothing wrong with your return type. Its double only. The way you have created if conditions are wrong. Here there are chances that your any of the if condition not get satisfy and return statement is not executed. thus Compiler is giving error that you This method must return a result of type double
public double getNetPay(int totalHoursWorked) {
int basePayRate = 15;
double overTime = 15 * 1.5;
double taxRate1 = 0.25;
double taxRate2 = 0.21;
double taxRate3 = 0.15;
double result = 0d;
if (totalHoursWorked > 40) {
double pay = totalHoursWorked * overTime;
if (pay > 1200) {
result = pay * taxRate1;
} else if (pay >= 500 || pay < 1199) {
result = pay * taxRate2;
} else if (pay <= 499) {
result = pay * taxRate3;
}
} else {
double pay = totalHoursWorked * basePayRate;
if (pay > 1200) {
result = pay * taxRate1;
} else if (pay >= 500 || pay < 1199) {
result = pay * taxRate2;
} else if (pay <= 499) {
result = pay * taxRate3;
}
}
return result;
}

A good practice in imperative language is too minimize number of return statements in a method.
public int get() {
int result = default_value;
if(condition) {
result = one_integer_value;
} else if (another_condition) {
result = another_integer_value;
}
return result;
}
It makes the code much clearer and avoid this kind of problem. Anyway there are some situation where it's not fully appropriated. Take this as an advice not as a strict rule, the idea itself makes debate :
Should a function have only one return statement?

Use eclipse IDE which helps to find out compile time error.
return statement always should be outside of any block. Avoid multiple return statement in one method instead create a variable and return that variable at the end of the method.

Related

How to get rid of multiple if statements in java?

Is there a better way to write this constructor which has multiple if statements and multiple arguments? I'm a noob to programming so any leads would be helpful.
public Latency(final double full, final double cpuOne, final double cpuTwo, final double cpuThree, final double cpuFour) {
if (full > 10.0 || (full <= 0.0)) {
throw new IllegalArgumentException("Must check the values");
}
this.full = full;
if (cpuOne == 0 && cpuTwo == 0 && cpuThree == 0 && cpuFour == 0) {
throw new IllegalArgumentException("not all can be zero");
} else {
if (cpuOne == 0.5) {
this.cpuOne = full;
} else {
this.cpuOne = cpuOne;
}
if (cpuTwo == 0.5) {
this.cpuTwo = full;
} else {
this.cpuTwo = cpuTwo;
}
if (cpuThree == 0.5) {
this.cpuThree = full;
} else {
this.cpuThree = cpuThree;
}
if (cpuFour == 0.5) {
this.cpuFour = full;
} else {
this.cpuFour = cpuFour;
}
}
}
I think this code doesn't need much of context as it is pretty straight forward.
I found out that we can't use switch statements for type double. How to optimize this?
There are a number of possible ways of refactoring the code that you've written, and there are pros and cons of each one. Here are some ideas.
Idea One - use the conditional operator
You could replace the else block with code that looks like this. This is just effectively a shorter way of writing each of the inner if/else blocks. Many people find this kind of form more readable than a bunch of verbose if/else blocks, but it takes some time to get used to it.
this.cpuOne = cpuOne == 0.5 ? full : cpuOne;
this.cpuTwo = cpuTwo == 0.5 ? full : cpuTwo;
this.cpuThree = cpuThree == 0.5 ? full : cpuThree;
this.cpuFour = cpuFour == 0.5 ? full : cpuFour;
Idea Two - move common functionality to its own method
You could have a method something like this
private static double changeHalfToFull(double value, double full) {
if (value == 0.5) {
return full;
} else {
return value;
}
}
then call it within your constructor, something like this.
this.cpuOne = changeHalfToFull(cpuOne);
this.cpuTwo = changeHalfToFull(cpuTwo);
this.cpuThree = changeHalfToFull(cpuThree);
this.cpuFour = changeHalfToFull(cpuFour);
This has the advantage that the key logic is expressed only once, so it's less error prone than repeating code over and over.
Idea Three - use arrays
You could use an array of four elements in the field that stores these values. You could also use an array for the constructor parameter. This has a huge advantage - it indicates that the four CPU values are somehow all "the same". In other words, there's nothing special about cpuOne compared to cpuTwo, for example. That kind of messaging within your code has real value to someone trying to understand this.
public Latency(final double full, final double[] cpuValues) {
// validation conditions go here ...
this.cpuValues = new double[4];
for (int index = 0; index <= 3; index++) {
if (cpuValues[index] == 0.5) {
this.cpuValues[index] = full;
} else {
this.cpuValues[index] = cpuValues[index];
}
}
}
Or a combination
You could use some combination of all these ideas. For example, you might have something like this, which combines all three of the above ideas.
public Latency(final double full, final double[] cpuValues) {
// validation conditions go here ...
this.cpuValues = new double[4];
for (int index = 0; index <= 3; index++) {
this.cpuValues[index] = changeHalfToFull(cpuValues[index]);
}
}
private static double changeHalfToFull(double value, double full) {
return value == 0.5 ? full : value;
}
There are obviously other possibilities. There is no single correct answer to this question. You need to choose what you're comfortable with, and what makes sense in the larger context of your project.
DRY - Don't Repeat Yourself
Each if is essentially the same. Put it in a separate method and call the method once for each cpu* variable.
public class Latency {
private double full;
private double cpuOne;
private double cpuTwo;
private double cpuThree;
private double cpuFour;
public Latency(final double full,
final double cpuOne,
final double cpuTwo,
final double cpuThree,
final double cpuFour) {
if (full > 10.0 || (full <= 0.0)) {
throw new IllegalArgumentException("Must check the values");
}
this.full = full;
if (cpuOne == 0 && cpuTwo == 0 && cpuThree == 0 && cpuFour == 0) {
throw new IllegalArgumentException("not all can be zero");
}
else {
this.cpuOne = initCpu(cpuOne);
this.cpuTwo = initCpu(cpuTwo);
this.cpuThree = initCpu(cpuThree);
this.cpuFour = initCpu(cpuFour);
}
}
private double initCpu(double cpu) {
return cpu == 0.5 ? full : cpu;
}
public static void main(String[] arg) {
new Latency(9.99, 8.0, 7.0, 6.0, 0.5);
}
}

If-else with two possible ways

Could you please help me find a solution for my code? I'm making a new Android app in which I need to make some calculations and the scenario is the following:
There are four fields to be calculated. Two EditText (number decimal) field are obligatory and the other two are optional, BUT, if the optional fields are filled, then it needs to be in the calculation, otherwise only the obligatory fields will be used.
Right now I'm totally OK with calculating the obligatory fields but when I try some if-else clause to include the optional fields in the calculation, the app goes bananas.
I'm not sure where I should make this two-step option, if I should use boolean to check the option field condition, if I just keep using if-else...
The problem is not the calculatin itself, but having two ways for the code to follow: One using only the obligatory fields if nothing else is inserted and the other one using all four fields.
Thanks everyone!
Code below is only using the two obligatory fields.
public void calcularResultado(View view) {
//check for blank values in obligatory fields
if (editGasolina.length() == 0) {
editGasolina.setError("Insira o valor");
}
if (editEtanol.length() == 0) {
editEtanol.setError("Insira o valor");
//runs the code
} else {
double valorGasolina = Double.parseDouble(editGasolina.getText().toString());
double valorEtanol = Double.parseDouble(editEtanol.getText().toString());
double valorResultado = valorEtanol / valorGasolina;
double porcentagem = (valorResultado) * 100;
String valorResultadoTexto = Double.toString(porcentagem);
valorResultadoTexto = String.format("%.2f", porcentagem);
if (valorResultado >= 0.7) {
textResultado.setText("GASOLINA");
textRendimento.setText(valorResultadoTexto + "%");
} else {
textResultado.setText("ETANOL");
textRendimento.setText(valorResultadoTexto + "%");
}
You almost got it. What happens now, since you have an if-if-elseconstruction, it considers the first if statement to be seperate from the if-else block below. That is to say, if editEtanol.length() == 0 evaluates to false, it will execute the else block below, even if editGasolina.length() == 0 evaluates to true.
Changing the line if (editEtanol.length() == 0) { to else if (editEtanol.length() == 0) { should already help alot. Hope that helps!
public void calcularResultado(View view) {
//check for blank values in obligatory fields
if (editGasolina.length() == 0) {
editGasolina.setError("Insira o valor");
}
if (editEtanol.length() == 0) {
editEtanol.setError("Insira o valor");
//runs the code
} else {
double valorGasolina = Double.parseDouble(editGasolina.getText().toString());
double valorEtanol = Double.parseDouble(editEtanol.getText().toString());
boolean optionalField1Used = optionalEditText1.length() != 0;
boolean optionalField2Used = optionalEditText2.length() != 0;
double valorResultado = 0;
if (!optionalField1Used && !optionalField2Used) {
valorResultado = valorEtanol / valorGasolina;
} else if (optionalField1Used && !optionalField2Used) {
valorResultado = //some other calculation
} else if (!optionalField1Used && optionalField2Used) {
valorResultado = //yet another calculation
} else {
valorResultado = //calculation if both optional fields used
}
double porcentagem = (valorResultado) * 100;
String valorResultadoTexto = Double.toString(porcentagem);
valorResultadoTexto = String.format("%.2f", porcentagem);
if (valorResultado >= 0.7) {
textResultado.setText("GASOLINA");
textRendimento.setText(valorResultadoTexto + "%");
} else {
textResultado.setText("ETANOL");
textRendimento.setText(valorResultadoTexto + "%");
}
Let us assume that the optional fields are called edit1 and edit2. I also assume that in order to use the alternative computation, both optional values must be present.
To enhance code clarity, I would define two Boolean variables to explicitly indicate whether the mandatory and optional fields have values. Something like the following.
public void calcularResultado(View view) {
var mandatoryValues = true;
var optionalValues = false;
if (editGasolina.length() == 0 {
editGasolina.setError("Insira o valor");
mandatoryValues = false;
}
if (editEtanol.length() == 0 {
editEtanol.setError("Insira o valor");
mandatoryValues = false;
}
if (edit1.length() > 0 && edit2.length() > 0) {
optionalValues = true;
}
if (mandatoryValues) {
if (optionalValues) {
// do alternative computation
} else {
// do computation for mandatory values only
}
}
}
Note that if either mandatory value is absent, no computation is performed.
Hope it helps - Carlos

Error: missing return statement (once more)

public static int salariDepart1( int duradaPeriode, int horesEfectives, float preuHora, int bonificHoresExtres) {
int salary;
if(duradaPeriode<0||horesEfectives<0||preuHora<0||bonificHoresExtres<0){
return (int) -1;
}
else if(horesEfectives<(duradaPeriode-(duradaPeriode*0.75))){
if(preuHora<6){
salary = (int) (preuHora * horesEfectives);
return (int) Math.round(salary);
}
else{
salary = (int) (horesEfectives * (preuHora-(preuHora*0.10)));
return (int) Math.round(salary);
}
}
else if(horesEfectives>(duradaPeriode+(duradaPeriode*0.20))){
bonificHoresExtres = (int) (preuHora+(preuHora*0.03));
if(bonificHoresExtres>200){
return (int) -2;
}
else if(bonificHoresExtres<200){
salary = (int) (horesEfectives * (preuHora+(preuHora*0.03)));
return (int) Math.round(salary);
}
else{
salary = (int) (horesEfectives * preuHora);
return (int) Math.round(salary);
}
}
}
public static void main(String[] args){
System.out.println(salariDepart1(200,120,8,5));
System.out.println(salariDepart1(190,100,7,10));
System.out.println(salariDepart1(180,90,7,20));
}
}
This error keeps popping up, and I dont know why. Help is appreciated. :)
The reason gets clearer if you indent the code consistently and clearly:
public static int salariDepart1(int duradaPeriode, int horesEfectives, float preuHora, int bonificHoresExtres) {
int salary;
if (duradaPeriode < 0 || horesEfectives < 0 || preuHora < 0 || bonificHoresExtres < 0) {
return (int) - 1;
} else if (horesEfectives < (duradaPeriode - (duradaPeriode * 0.75))) {
if (preuHora < 6) {
salary = (int)(preuHora * horesEfectives);
return (int) Math.round(salary);
} else {
salary = (int)(horesEfectives * (preuHora - (preuHora * 0.10)));
return (int) Math.round(salary);
}
} else if (horesEfectives > (duradaPeriode + (duradaPeriode * 0.20))) {
bonificHoresExtres = (int)(preuHora + (preuHora * 0.03));
if (bonificHoresExtres > 200) {
return (int) - 2;
} else if (bonificHoresExtres < 200) {
salary = (int)(horesEfectives * (preuHora + (preuHora * 0.03)));
return (int) Math.round(salary);
} else {
salary = (int)(horesEfectives * preuHora);
return (int) Math.round(salary);
}
}
}
What if duradaPeriode is >= 0 but neither horesEfectives < (duradaPeriode - (duradaPeriode * 0.75)) nor horesEfectives > (duradaPeriode + (duradaPeriode * 0.20)) is true? That's the path where the code doesn't return a value. So there's a path through the code that doesn't have a return.
Even if the conditions were all mutually-exclusive, the compiler can't always know that they are If they really are (which I don't think is the case above), make the final else if just an else. If they aren't, well, that's your problem, you need a returnin that case.
There is no else path for
else if(horesEfectives>(duradaPeriode+(duradaPeriode*0.20))){
So if that condition is not satisfied the compiler needs a return statement, which is missing.
Generally one should avoid to have many return statements, instead you better should introduce a returnValue variable which you inizialize at the beginning. This improves the abiliyt to debug your code.
int retVal = -1;
and assign the retVal in each of the conditions,
eg:
..
retVal = Math.round(salary);
..
finally return the value as last line
return retVal;
Set a default value that is returned when none of the conditional return statements are used.
So adding
return -1
for example at the end of the function will solve this
Not all code paths in your logic will encounter a return statement. Hence, you're missing one.
Your structure looks essentially like this:
if (something) {
if (something) {
return;
} else {
return;
}
} else if (something) {
if (something) {
return;
} else {
return;
}
}
Your "inner" conditionals are fine, but look at the "outer" one:
if (something) {
// every path in here returns
} else if (something) {
// and every path in here returns
}
What if neither of the "outer" conditions is true? No return statement is ever encountered.
Add an else to the "outer" conditional with a return or add a return after the entire conditional block. Every possible logical path through the method must return something.

Java binarySearch return is being ignored

So as the title suggests, I am writing some code to perform a version of a binary search in Java. However, my return statements are ignored and the function instead returns the last "catch all" return statement as shown below:
public int binarySearch(int min, int max) {
int mid = ((min+max)/2);
double[][] m1 = createFilledSquareMatrix(mid);
double[][] m2 = createFilledSquareMatrix(mid);
double[][] m3 = new double[mid][mid];
long time = analyzeMultiply(m1, m2, m3);
if(time == 1000) {
return mid;
}
if (time > 1000) {
m1 = createFilledSquareMatrix(mid-1);
m2 = createFilledSquareMatrix(mid-1);
m3 = new double[mid-1][mid-1];
time = analyzeMultiply(m1, m2, m3);
if(time <= 1000) {
return mid; //I am reached but ignored
}
else {
binarySearch(min, mid-1);
}
}
else {
System.out.println("here");
m1 = createFilledSquareMatrix(mid+1);
m2 = createFilledSquareMatrix(mid+1);
m3 = new double[mid+1][mid+1];
time = analyzeMultiply(m1, m2, m3);
if(time >= 1000) {
return mid+1; //I am reached but ignored
}
else {
binarySearch(mid+1, max);
}
}
return -2;
}
So I have commented the return statements that are ignored. I go through with the debugger and it executes the return but then just goes to the outter return -2 statement and then executes that. I've never had this type of issue before so I feel like I am missing something simple. Any help would be appreciated.
Your method is recursive. This means that every time you recurse, you need to do something with the returned value from the recursive call. What you are seeing is that the recursive calls reach a termination point, return a value, and then bubble back out. However since the instance that made the recursive call doesn't do anything with the returned value, it continues executing as if nothing happened, causing it to drop back to it's "catch all" return instead, and so on.
For example,
else {
binarySearch(min, mid-1);
}
should be
else {
return binarySearch(min, mid-1);
}

GOTO/Continue in Java Dynamic Programming

I have the following piece of code in Java implementing dynamic programming recursiverelatio:
public double routeCost() throws Exception {
double cost = Double.MAX_VALUE;
for (int l=i; l<=j; l++) {
if (! (customers.get(l) instanceof VehicleCustomer) )
continue;
double value = F(l,j) + (customers.get(l).distanceFrom(depot));
if (value < cost)
cost = value;
}
return cost;
}
private double F(int l, int m) {
//=========================== FIRST CASE ===========================
if (l==i && m==i) {
//System.out.println(i+","+j+","+l+","+m);
return firstCase();
}
//=========================== SECOND CASE ===========================
if (l==i && (i<m && m<=j) ) {
//System.out.println(i+","+j+","+l+","+m);
//analyses the possibility of performing all the soubtours based at heicle customert_i
return secondCase(i,m);
}
//=========================== GENERAL CASE ===========================
else {
System.out.println(i+","+j+","+l+","+m);
assert (customers.get(l) instanceof VehicleCustomer);
assert ( (i<l && l<=j) && (l<=m && m<=j) );
return Math.min(thirdCaseFirstTerm(l,m), thirdCaseSecondTerm(l,m));
}
}
private double firstCase() {
mainRoute.add(depot);
mainRoute.add(customers.get(i));
return depot.distanceFrom(customers.get(i));
}
private double secondCase(int i,int m) {
double caseValue = Double.MAX_VALUE;
int k = i;
while (k<m) {
double totalDemand=0;
for (int u=k+1; ( (u<=m) && (totalDemand<=truckCapacity) ); u++)
totalDemand += customers.get(u).getDemand();
double cost = F(i,k) + thita(i,k+1,m);
if (cost <= caseValue)
caseValue = cost;
k++;
}
return caseValue;
}
private double thirdCaseFirstTerm(int l, int m) {
double caseValue = Double.MAX_VALUE;
int k = i;
while (k<m) {
double totalDemand=0;
for (int u=k+1; ( (u<=m) && (totalDemand<=truckCapacity) ); u++)
totalDemand += customers.get(u).getDemand();
double cost = F(l,k) + thita(l,k+1,m);
if (cost <= caseValue)
caseValue = cost;
k++;
}
return caseValue;
}
private double thirdCaseSecondTerm(int l,int m) {
double caseValue = Double.MAX_VALUE;
int k = i;
for (Customer cust : customers) {
int h = customers.indexOf(cust);
if ( (!(cust instanceof VehicleCustomer)) || (h >=l)) {
continue;
}
double totalDemand=0;
for (int u=k+2; ( (u<=m) && (totalDemand<=truckCapacity) ); u++)
totalDemand += customers.get(u).getDemand();
double cost = F(h,k) + customers.get(h).distanceFrom(customers.get(l)) + thita(l,k+2,m);
if (cost < caseValue)
caseValue = cost;
}
return caseValue;
}
Method F(int,int) is invoked from the for loop in method routeCost().
I want to find a way to enforce that whenever the assertion assert (customers.get(l) instanceof VehicleCustomer);
` is not true, instead of going down to the return statement, I want to infrom the for loop from the routeCost() to continue to the next iteration. But F() has to return a value!
I know that what I'm trying to do violates almost every rule of object orientation, but I really need that.
You could throw an Exception in F() and catch it in routeCost().
This approach is much better than using assertions. They are rarely used in practice, and there's a good reason for this: exceptions are much more flexible and better suited for detecting errors, invalid input etc.
PS: When I say "rarely used", I base this statement on the fact that I saw hundreds of thousands of lines of Java code in the past years and I rarely came accross code that uses assertions.
You can return a special value like Double.NaN which you can check for with Double.isNaN(d)
You could make F() return a Double (instead of double) and return null in the case where your assert fails. Then have your outer for loop do a null check on the returned value before adding it, etc.
Why not replace the asserts with if statements? When the if-statements are true then calculate the value, otherwise return the MAX_VALUE of double. When F returns MAX_VALUE the cost will not be updated.
if (customers.get(l) instanceof VehicleCustomer) {
if ( (i<l && l<=j) && (l<=m && m<=j) ) {
return Math.min(thirdCaseFirstTerm(l,m), thirdCaseSecondTerm(l,m));
}
}
return Double.MAX_VALUE;
Use asserts during development to weed out things that should never happen in private methods. (Asserts can be switched off in production)
Throw an exception when something unexpected happens (e.g. a client of your class passes in invalid data).
However, from your question it seems you expect to get instances that are not VehicleCustomer, so asserts and exceptions are not the right approach here.
Peter Lawrey's and Jeff's answers will also work.

Categories