My Return Statement is Unreachable - java

public BigDecimal calculateTotal() {
BigDecimal percent = BigDecimal.valueOf(0.9);
int i = 0;
BigDecimal price = BigDecimal.valueOf(0.0);
while(!myOrders.isEmpty()){
if (!myOrders.get(i).getItem().isBulk() && myMembership == true){
price = price.add(myOrders.get(i).calculateOrderTotal().multiply(percent));
myOrders.remove(i);
}
else{
price = price.add(myOrders.get(i).calculateOrderTotal());
myOrders.remove(i);
}
}
//WHY IS THIS UNREACHABLE?!
return price.setScale(2, RoundingMode.HALF_EVEN);
}
I know that anything after a return statement is unreachable code, but my only return statement is unreachable and I can't figure out why. The while loop is the way it is because I'm grasping at straws, I'm aware that it probably won't do what I want it to do. myOrders is an ArrayList.

EDIT: Since OP said it is an ArrayList, my answer no longer applies.
You never update your index i. This should work:
public BigDecimal calculateTotal() {
BigDecimal percent = BigDecimal.valueOf(0.9);
int i = 0;
BigDecimal price = BigDecimal.valueOf(0.0);
while(!myOrders.isEmpty()) {
if (!myOrders.get(i).getItem().isBulk() && myMembership == true) {
price = price.add(myOrders.get(i).calculateOrderTotal().multiply(percent));
myOrders.remove(i);
} else {
price = price.add(myOrders.get(i).calculateOrderTotal());
myOrders.remove(i);
}
i++; // <-- You were missing this
}
// Not unreachable anymore :)
return price.setScale(2, RoundingMode.HALF_EVEN);
}

Your variable i is never incremented. Depending on what type of Collection myOrders is, removing the 0th element each time may not shift the elements in the collection, and myOrders will never be empty.

There is nothing in the posted code to explain the error.
Since you said your IDE is Eclipse, I suggest to clean the project.
Also, make sure to fix all other errors before looking at this one.
This error doesn't make sense,
I suspect you have other compiler errors in your project,
which somehow cause this as a strange side effect.
After you fix everything else, this one should naturally disappear.
Btw, to see clearer, here's a cleaned up version of the same code, doing exactly the same thing:
BigDecimal percent = BigDecimal.valueOf(0.9);
BigDecimal price = BigDecimal.ZERO;
while (!myOrders.isEmpty()) {
Order first = myOrders.get(0);
BigDecimal subtotal = first.calculateOrderTotal();
if (!first.getItem().isBulk() && myMembership) {
subtotal = subtotal.multiply(percent);
}
price = price.add(subtotal);
myOrders.remove(0);
}
return price.setScale(2, RoundingMode.HALF_EVEN);

Cleaning eclipse solved the problem.

Related

Variable initialized but not recognized?

Hey I am a high school and I found the solution to my problem but confused on why it's doing what it's doing can someone explain? Also I tried looking for the answer but couldn't find it so sorry if someone's already answered this.
So at getAverage() I state int i; and initialize it in the foreach loop but when it runs it says "variable i might not have been initialized"? I found the solution to this was just make int i = 0; but i'm confused because I know you can state a variable and not initialize it at that time as long as you initialize it later. So what makes this so special?
public class ArrayAverage
{
private int[] values;
public ArrayAverage(int[] theValues)
{
values = theValues;
}
public double getAverage()
{
// Problem here
int i; // Solution: int i = 0;
for(int value : values){
i += value;
}
double avg = (double)i / values.length;
return avg;
}
}
// This pseudo code code has nothing to do with above code
// but is example of what I know can be done but isn't
int i;
i = 10;
System.out.println(i);
//Output would be 10
The issue is that the you're adding the variable i to itself, and another value. However, the initial value for i has not been defined in the previous code. This is the reason that i = 0 would make the code work, as the program now understands that for the first loop, it has to add the value to 0, then the second loop will know to add the previous value, to the new value.
Hope this helped.

UVa Online Judge 100th (3n+1) uDebug shows everything as correct but wrong answer

This is my first UVa submission so I had a few problems in the way. The biggest hurdle that took my time so far was probably getting all the formats correctly (I know, shouldn't have been too hard but I kept getting runtime error without knowing what that actually meant in this context). I did finally get past that runtime error, but I still get "Wrong answer."
Listed below are the things I've done for this problem. I've been working on this for the last few hours, and I honestly thought about just dropping it altogether, but this will bother me so much, so this is my last hope.
Things I've done:
considered int overflow so changed to long at applicable places
got the whole list (1-1000000) in the beginning through memorization for computation time
submitted to uDebug. Critical input and Random input both show matching output.
submitted to to UVa online judge and got "Wrong Answer" with 0.13~0.15 runtime.
Things I'm not too sure about:
I think I read that UVa doesn't want its classes to be public. So I left mine as class Main instead of the usual public class Main. Someone from another place mentioned that it should be the latter. Not sure which one UVa online judge likes.
input. I used BufferedReader(new InputStreaReader (System.in)) for this. Also not sure if UVa online judge likes this.
I thought my algorithm was correct but because of "Wrong answer," I'm not so sure. If my code is hard to read, I'll try to describe what I did after the code.
Here is my code:
class Main {
public static int mainMethod(long i, int c, List<Integer> l) {
if (i==1)
return ++c;
else if (i%2==0) {
if (i<1000000&&l.get((int)i)!=null)
return l.get((int)i)+c;
else {
c++;
return mainMethod(i/2, c, l);
}
}
else {
if (i<1000000&&l.get((int)i)!=null)
return l.get((int)i)+c;
else {
c++;
return mainMethod(i*3+1, c, l);
}
}
}
public static int countMax(int x, int y, List<Integer> l) {
int max=0;
if (x>y) {
int temp = x;
x= y;
y = temp;
}
for (int i=x; i<=y; i++) {
if (l.get(i)>max)
max = l.get(i);
}
return max;
}
public static void main(String[] args) {
List<Integer> fixed = Arrays.asList(new Integer[1000000]);
for (long i=1; i<1000000; i++) {
fixed.set((int)i, mainMethod(i,0,fixed));
}
String s;
try {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while ((s = br.readLine())!=null) {
int x = -1;
int y = -1;
for (String split : s.split("\\s+")) {
if (!split.equals("\\s+") && x==-1) {
x = Integer.parseInt(split);
} else if (!split.equals("\\s+") && x!=-1) {
y = Integer.parseInt(split);
}
}
if (x!=-1&&y!=-1)
System.out.println(Integer.toString(x) + " " + Integer.toString(y) + " " + Integer.toString(countMax(x,y,fixed)));
}
} catch (IOException e) {
} catch (NumberFormatException e) {
}
}
}
I apologize for generic names for methods and variables. mainMethod deals with memorization and creating the initial list. countMax deals with the input from the problem (15 20) and finding the max length using the list. The for loop within the main method deals with potential empty lines and too many spaces.
So my (if not so obvious) question is, what is wrong with my code? Again, this worked perfectly fine on uDebug's Random Input and Critical Input. For some reason, however, UVa online judge says that it's wrong. I'm just clueless as to where it is. I'm a student so I'm still learning. Thank you!
Haven't spotted your error yet, but a few things that may make it easier to spot.
First off:
int goes to 2^31, so declaring i in mainMethod to be long is unnecessary. It also states in the problem specification that no operation will overflow an int, doesn't it? Getting rid of the extraneous longs (and (int) casts) would make it easier to comprehend.
Second:
It's probably clearer to make your recursive call with c + 1 than ++c or doing c++ before it. Those have side effects, and it makes it harder to follow what you're doing (because if you're incrementing c, there must be a reason, right?) What you're writing is technically correct, but it's unidiomatic enough that it distracts.
Third:
So, am I missing something, or are you never actually setting any of the values in the List in your memoization function? If I'm not blind (which is a possibility) that would certainly keep it from passing as-is. Wait, no, definitely blind - you're doing it in the loop that calls it. With this sort of function, I'd expect it to mutate the List in the function. When you call it for i=1, you're computing i=4 (3 * 1 + 1) - you may as well save it.

Recursive method with wrong parameter

This was my answer to a question in which I was supposed to convert an iterative method to a recursive method. The teacher told me I cant use a-=1 as a parameter... So they gave me 0 points..
When I run this it works as it supposed to be..
Could someone tell me why its wrong?
public int do(int a){
if(a==0){
return 1 ;
}else{
return a * do(a-=1);
}
}
The problem with your code is that you're reading the value of a and reassigning it with a -= 1 in the same expression, but the order of these operations is not specified. The statement:
return a * do(a -= 1);
could be implemented as:
temp = a;
a -= 1;
return temp * do(a);
which will do what you were probably expecting, or:
a -= 1;
return a * do(a);
which will multiply by the decremented value of a rather than its original value.
The correct way to write your function is:
public int do(int a){
if(a==0){
return 1 ;
}else{
return a * do(a-1);
}
}
Just pass the result of the subtraction as an argument, don't reassign the variable at the same time.
I assume that this is in java?
I see two big problems with this snippet.
do is a reserved keyword. It may cause compilation errors, so you should name your method something else.
Executing -= in a parameter call seems quite ambiguous. Will the negation operator run before or after the multiplication by a? The more clear operator to use would be simply the - operator, and it would complete with the same result.
That said, something like this might have been what the teacher was looking for:
public int calculateSomething(int a) {
if (a == 0) {
return 1;
} else {
return a * calculateSomething(a - 1);
}
}

Method not working completely? What could be the error?

I was just working on some project and I could not find out what's wrong with the following code :
double getInterest(double amt,double tax){
double diff=0;
double refund=0;
double interest=0;
if(amt>=(tax*0.4)){
diff=amt-(tax*0.4);
System.out.println(" "+diff); //This is not working.Nothing gets printed.
refund=diff; //The value is not being assigned to refund.
} //refund remains to be 0 throughout.
interest=diff*0.01*12;
if(refund>0){
JOptionPane.showMessageDialog(null,"Your refund is: "+refund);
}
return interest;
}
I can't figure out any error in the code. But it is still not working completely.
The errors are given in the code in the form of comments.
Anyone help me to figure out the errors and reslove the issue?
I don't know why the value of diff is not getting printed and why the value of diff is not being assigned to the variable refund.
I'm working in NetBeans and it's not giving any kind of compile-time error.
I've tried to check the values by using the println for both diff and refund But the values are not getting printed.
Well if the statements in the if block are never executed, that implies that there is never a call to this method where the arguments meet the condition amt >= (tax*0.4). So the real question is, what values are you passing to this method?
Your bracketing on the
if(amt>=(tax*0.4){
line is missing a closing ) bracket before the first { bracket. Make sure you check your bracketing and make sure you have all errors turned on in the options menu (if you can).
This code should not compile because of the bracketing error. Check that Netbeans is compiling the right project as this should go crazy at compile time.
You should always use the BigDecimal type when dealing with currency to avoid double precision issues.
Here is the code rewritten in BigDecimal
BigDecimal getInterest(final BigDecimal amount, final BigDecimal tax) {
BigDecimal diff = BigDecimal.ZERO;
BigDecimal refund = BigDecimal.ZERO;
BigDecimal reducedTax = new BigDecimal("0.4").multiply(tax);
System.out.println("Amount is " + amount + ". Tax times 0.4 is " + tax + ".");
if (amount.compareTo(reducedTax) >= 0) {
diff = amount.subtract(reducedTax);
System.out.println(diff);
refund = diff;
}
BigDecimal interest = diff.multiply(new BigDecimal("0.01")).multiply(new BigDecimal("12"));
if (refund.compareTo(BigDecimal.ZERO) > 0) {
JOptionPane.showMessageDialog(null, "Your refund is: " + refund);
}
return interest;
}
Yes, I know it's much uglier. It will also be much slower. But it's new correct.
Onto your issue, presumably the code is not entering the if because amount was not greater than tax * 0.4 - if you are sure that it was then maybe you have already encountered double precision issues.
I have added a println before the if so you can see what the values are before the test happens.

If-else block in nested for loops - Compiler claims I need a return statement

How do I make this work? It says that I need to add a return statement but I have one.
public boolean clockFactCheck(int a, int b){
for (int i = 0; i <= 276; i++){
for (int h = 0; h <= 55; h++){
if (a == i + 186 && b == h + 133){
return true;
} else {
return false;
}
}
}
}
The code provided may not reach one of the returns for any input a,b and that's what the compiler is complaining about.
Actually in your case the if-else will be reached with the very first iteration - unfortunately something which the compiler cannot deduce. Therefore, it goes the save way and issues this error.
Comment: Therefore, in your loop seems not to make much sense since it will not iterate at all but stop within the first iteration i==0 and h==0. Did you meant to code something like that?
You don't have a return statement after the for loop but even then h++ is dead code becaue it will never get past the first iteration.
Place the return statement outside the loop. (declare a boolean in your function, modify it and return it at the end)
My guess is that the compiler is not clever enough to figure out that there is no codepath around the loops.
If this is real code, simplify it to
return (a == 186 && b == 133);
If this is not the real code, there is probably another path that does not return (if you made an error pasting), or there really is a compiler bug or limitation. At one point, the halting problem bites you, and the code is too complex for the compiler to figure out.
In the latter case I would place a
throw new RuntimeException(
String.format("should never get here (a = %d, b = %d) !",a,b));
at the last statement.
That makes both the compiler happy and does not introduce an "undefined" return value for a case that should either never happen, or if it does, has not been thought of.
Oh yeah my bad, I'm sorry this was a stupid question it was 5am when I posted this. I figured out the answer to my problem. If you made the same stupid mistake as me here is the fix
public boolean clockFactCheck(int a, int b){
for (int i = 0; i <= 276; i++){
for (int h = 0; h <= 55; h++){
if (a == i + 186 && b == h + 133){
return true;
}
}
}
return false;
}
Java requires every path return a value. The compiler could not judge if the circulation will return a path. If your code is like this:
public boolean add(){
for(int i=0;i<100;i++)
if(i==5000)
return true;}
the function add will not return a value. Instead, an error will occur.

Categories