Search code examples
javaloopsmathnumbers

Addition of odd and even numbers from range of L1 and L2 provided by user input


I'm struggling with this task. User is providing numbers L1 and L2. Add all odd numbers from range L1,L2 and all even numbers from this range and display the sums. I have to make it in 3 ways, using: for, while and do while loops. My for loop works perfectly, but while is displaying some higher scores.

import java.util.Scanner;

public class PPO4b {

    public static void main(String[] args) {
        
        Scanner value1Check = new Scanner(System.in);
        System.out.println("Provide first value: ");
        int value1 = value1Check.nextInt();
        
        Scanner value2Check = new Scanner(System.in);
        System.out.println("Provide second value: ");
        int value2 = value2Check.nextInt();

        int sumOdd = 0;
        int sumEven = 0;
        int i = 0;

        while (i <= 0) {
            if (i % 2 == 1) {
                sumOdd = sumOdd + i;
            } else {
                sumEven = sumEven + i;
            }
            i = i + 1;
        }
        System.out.println("Sum is equal to: " + sumEven);
        System.out.println("Sum is equal to: " + sumOdd);
    }
}
 

Solution

  • With your current approach here are some observations.

    • You only need one Scanner.

    • You are testing i for parity where you should be testing the input range
      e.g should be something like:

            while (value1 <= value2) {
                if (value1 % 2 == 1) {
                   sumOdd = sumOdd + value1;
      
    • don't forget to increment value1

    • When printing, don't label each sum with just sum. Use a descriptive name

    Alternative approach

    With a little math you can do this in O(1) time.

    • For the sum of 1 thru n values, n(n+1)/2) will give the sum
    • Similarly for k thru n values, (n-k+1)(n+k)/2 will give the sum of those values.
    • now consider a range of numbers like 2 3 4 5 6. The total number of even values is 3 which are 2, 4, and 6. This is true even if you have 1 2 3 4 5 6 7.
    • for any even value s, the next one lower is ((s-1). So if s = 4 would be 3
    • for any odd value s, the next lower one would be (s-1)|1. So for s == 4, (s-1) = 3 and 3|1 == 3. The OR simply sets the low order bit to make the value odd or let it stay odd.
    • Similarly for any value e, e|1 will be either the same odd value or the next highest.

    Now there is enough information to compute the sum of the even and odd values between s and e.

    For given int e and int s;

    int totalSum = ((e+s)*(e-s+1))/2;
    e = (e|1);
    s = (s-1)|1;
    int evenCount = (e-s)/2;
    int sumEven = ((e - s + 1) * (evenCount))/2;
    int sumOdd = totalSum - sumEven;
    

    Here is how to verify it.

    • compute the even and odd sums using an IntStream of the ranges, filtering out even and odd values as appropriate
    • next use the above methods for computing the same values.
    • compare corresponding sums and report any discrepancies.
    Random rnd = new Random();
    for (int i = 0; i < 200000; i++) {
        int s = rnd.nextInt(200) +100;
        int e = rnd.nextInt(500) + s;
        int compEven = IntStream.rangeClosed(s, e)
                .filter(r -> r % 2 == 0).sum();
        int compOdd = IntStream.rangeClosed(s, e)
                .filter(r -> r % 2 == 1).sum();
        
        int totalSum = (e + s) * (e - s + 1) / 2;
        e |= 1;
        s = (s - 1) | 1;
        int evenCount = (e - s + 1) / 2;
        int evenSum = ((e + s) * evenCount) / 2;
        int oddSum = totalSum - evenSum;
        if (evenSum != compEven || oddSum != compOdd) {
            System.out.println("Oops - sums don't match");
        }
    }
    

    Note: depending on the range you may need to use long or BigInteger types to avoid overflow.