0

My input for my program seems to be traveling to the wrong else statement in my if-else statements.

import java.util.Scanner;
import java.text.*;

public class CSCD210Lab6
{
   public static void main (String [] args)
   {
     Scanner waterInput = new Scanner(System.in);
     DecimalFormat df = new DecimalFormat("$#,###.00"); 
     DecimalFormat zf = new DecimalFormat("#,###.0"); 

      //declare variables
      int beginMeter, endMeter;
      String customerCode;
      double billingAmount,gallonsUsed;


      billingAmount = 0;

      System.out.print("Please Enter Your Customer Code: ");
      customerCode = waterInput.next();
      System.out.print("Please Enter Your Beginning Meter Reading: ");
      beginMeter = waterInput.nextInt();
         if(beginMeter < 0)
         {
            System.out.println();
            System.out.print("ERROR! You Have Entered A Negative Number. The Program Will Now Close.");
            System.exit(0);
         }

      System.out.print("Please Enter Your Ending Meter Reading: ");
      endMeter = waterInput.nextInt();
         if(endMeter < 0)
         {
            System.out.println();
            System.out.print("ERROR! You Have Entered A Negative Number. The Program Will Now Close.");
            System.exit(0);
         }
      if(endMeter > beginMeter)
      {
        gallonsUsed = ((double)endMeter - beginMeter)/10;
      }
      else
      {
         gallonsUsed = (1000000000-((double)beginMeter - endMeter))/10; 
      }
      if (customerCode.equals("r")||customerCode.equals("R"))
      {
         billingAmount = 5.00 + (.0005 * gallonsUsed);
      } 

      if(customerCode.equals("c")||customerCode.equals("C") && gallonsUsed <= 4000000)      
      {
         billingAmount = 1000.00;
      }

      if(customerCode.equals("c")||customerCode.equals("C") && gallonsUsed > 4000000)
      {
        billingAmount = 1000.00 + ((gallonsUsed-4000000) * 0.00025);
      }

      if(customerCode.equals("i")||customerCode.equals("I")&& gallonsUsed <= 4000000)
      {
         billingAmount = 1000.00;
      }

      if(customerCode.equals("i")||customerCode.equals("I")&& gallonsUsed > 4000000 && gallonsUsed < 10000000)
      {
         billingAmount = 2000.00;
      }
      if(customerCode.equals("i")||customerCode.equals("I")&& gallonsUsed >= 10000000) 
      {
         billingAmount = 2000.00 +(gallonsUsed * .00025);
      }


      System.out.println();
      System.out.print("Your Customer Code is: "+customerCode); 
      System.out.println();
      System.out.print("Your Beginning Meter Reading is: "+beginMeter); 
      System.out.println();
      System.out.print("Your Ending Meter Reading is: "+endMeter);
      System.out.println();
      System.out.print("You Have Used "+zf.format(gallonsUsed)+" Gallons During This Billing Period.");
      System.out.println();
      System.out.print("Your Bill is: "+df.format(billingAmount));
      System.out.println();
      System.out.println();
      System.out.print("Please Pay Promptly. We Detest Late Accounts.");



   }
}

For example, if I enter c, and the total water used in less than 4,000,000 gallons, it executes the line of code for when the total gallons used is more than 4,000,000 gallons. Why?

3
  • Is all that code relevant? Why don't you cut down your code snippet to only the parts that are relevant? Have you debugged your application? Commented Oct 8, 2014 at 1:25
  • It goes to the right conditional(s). Attach a debugger and step the code. Commented Oct 8, 2014 at 1:29
  • It's a great example of the importance of the order of operations and if ... else if... statements Commented Oct 8, 2014 at 1:33

5 Answers 5

2

Because of the order of operations with your conditionals

http://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html

customerCode.equals("c")||customerCode.equals("C") && gallonsUsed <= 4000000

T || F && F

This equates to true, so billingAmount = 1000.00;

But the very next statement is

customerCode.equals("c")||customerCode.equals("C") && gallonsUsed > 4000000)

T || F && F

This also equates to true, so billingAmount gets overridden - billingAmount = 1000.00 + ((gallonsUsed-4000000) * 0.00025);

Both of these if statements are true for your condition.

To fix, use parenthesis. And also use else statements. There is no reason to go through the numerous condition checks when one of the first ones is true.

Sign up to request clarification or add additional context in comments.

Comments

0

Its because the or-clause || put ( ) around it.

if( (customerCode.equals("c")||customerCode.equals("C")) && gallonsUsed > 4000000)

Comments

0

The && between the second and third test gets evaluated first, then || with the first test (which is true when you enter 'c').

Use parentheses to indicate to the reader (and compiler) which parts of the if statement should be evaluated first. In your case, your if statement should read:

if((customerCode.equals("c")||customerCode.equals("C")) && gallonsUsed <= 4000000)

A better approach would be to use the following pattern:

if(customerCode.equals("c")||customerCode.equals("C"))       
{
    if(gallonsUsed <= 4000000)
    {
        billingAmount = 1000.00;
    } else {
        billingAmount = 1000.00 + ((gallonsUsed-4000000) * 0.00025);
    }
}

Comments

0
  if(customerCode.equals("c")||customerCode.equals("C") && gallonsUsed > 4000000)

is equivalent to

  if(customerCode.equals("c") ||
       (customerCode.equals("C") && gallonsUsed > 4000000))

because of operator precedence. Specifically, && has a higher precedence than ||, so if you have both in the same expression, it treats the expressions to the left and right of && as the operands of &&, and the result of && as the operand of ||. So if the customer code is lower-case c, it won't look at gallonsUsed.

You need parentheses around the || part:

  if((customerCode.equals("c")||customerCode.equals("C")) && gallonsUsed > 4000000)

Or use equalsIgnoreCase and avoid the whole operator-precedence problem:

  if (customerCode.equalsIgnoreCase("c") && gallonsUsed > 4000000)

Comments

0

And has higher preceence then or,

if(customerCode.equals("c")||customerCode.equals("C") && gallonsUsed <= 4000000)      
{
  billingAmount = 1000.00;
}
if(customerCode.equals("c")||customerCode.equals("C") && gallonsUsed > 4000000)
{
  billingAmount = 1000.00 + ((gallonsUsed-4000000) * 0.00025);
}

So, you wanted

if((customerCode.equals("c")||customerCode.equals("C")) && gallonsUsed <= 4000000)      
{
  billingAmount = 1000.00;
}
if((customerCode.equals("c")||customerCode.equals("C")) && gallonsUsed > 4000000)
{
  billingAmount = 1000.00 + ((gallonsUsed-4000000) * 0.00025);
}

But I would rewrite it as

if (customerCode.equalsIgnoreCase("c")) {
  billingAmount = 1000.00 + (gallonsUsed <= 4000000) ? 0 : 
      ((gallonsUsed-4000000) * 0.00025);
}

or,

if (customerCode.equalsIgnoreCase("c")) {
  if (gallonsUsed <= 4000000) {
    billingAmount = 1000.00;
  } else {
    billingAmount = 1000.00 + ((gallonsUsed-4000000) * 0.00025);
  }
}

And for customerCode "i" that might look like,

if (customerCode.equalsIgnoreCase("i")) {
    if (gallonsUsed <= 4000000) {
        billingAmount = 1000.00;
    } else {
        billingAmount = 2000.00 + ((gallonsUsed < 10000000) ? 0
                : (gallonsUsed * 0.00025));
    }
}

1 Comment

You're gonna fix the rest of his code too? :) Although, I would argue in this case, an inline conditional cuts down on readability/maintainability. I'd suggest programming for readability, and let the compiler do the inline optimization.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.