0

I am supposed to write a Java program to sum the following sequence: 1.0/1.0 + 1.0/2.0 + 1.0/3.0.... + 1.0/15,000,000.0 in increasing order and then again in decreasing order starting from 1.0/15,000,000.0 + 1.0/14,999,999 all the way down to 1.0/1.0 using 32 bit floating point. I'm struggling to figure out how to do this, but here is what I have so far (no idea if it will work):

EDIT: Sorry to open this thing back up, but I'm getting a 1.0 for both answers and I'm pretty sure that's incorrect. Does anyone know what I did wrong?

public class FloatSum {

public static float increasingSum (float numbers1){
float sum1 = 0;
for (int i = 1; i <= 15000000; i++){ 
    sum1 = sum1 + 1/i; 
    } 
return sum1;
} 

public static float decreasingSum (float numbers2){
float sum2 = 0;
for (int i = 15000000; i >= 1; i--){ 
    sum2 = sum2 + 1/i; 
    } 
return sum2;
}

public static void main(String[] args) {
float sum1 = 0;
float sum2 = 0; 

System.out.println(increasingSum(sum1));
System.out.println(increasingSum(sum2));
}
}
mskfisher
  • 3,291
  • 4
  • 35
  • 48
Bryan
  • 2,951
  • 11
  • 59
  • 101
  • If I understand the problem correctly, you are _really_ adding `2/1 + 2/2 + 2/3 + ... + 2/14999999` + `1/15000000` at the very end. – Joel Cornett Jan 21 '12 at 22:08
  • `1/i` does integer division hence the result is always 0. – Voo Jan 26 '12 at 01:19
  • Nice catch. I changed the "int i = 1" to "float i = 1" and now both answers come out to infinity. What else do I need to change? Thanks in advance. – Bryan Jan 26 '12 at 03:44

4 Answers4

5

Since this is homework, I'll limit my answer to a couple of hints:

  1. You don't need the array: a single scalar accumulator variable will suffice. Initialize it to zero and add every term to it.
  2. Don't loop over the terms of the sum, loop over the denominators (which are very conveniently integer).
NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • Thanks, I'll think about that and see what I can come up with. – Bryan Jan 21 '12 at 21:52
  • How do I efficiently add every term if there are 15,000,000 of them? – Bryan Jan 21 '12 at 22:05
  • 1
    @user1157541: For a modern computer, 15 million trivial iterations is child's play. If I were in your shoes, I'd first focus on correctness, and worry about performance later. – NPE Jan 21 '12 at 22:06
  • I would also use either 2 `for` loops, one for decreasing and increasing order each. Or... use one for loop and add an extra operation: something to the effect of `abs(15000000 - i)` ;) – Joel Cornett Jan 21 '12 at 22:06
2

Completely agree with aix. As to why your code is not compiling: the "a" variable is a float, but then you try to use it to access an array (which requires an int), and since it's illegal to use a float as an int you get a compilation error. You might solve the error by casting the float to an int

numbers1[(int)a]

but this will be useless, since the program is still wrong:

  • there is no point in accessing the array, since all elements are 0 (you do have created correctly an array, but all elements are merely initialized to 0)
  • since the test condition for the for is a < numbers1.length, in the last iteration you'll get an ArrayOutOfBoundException in the code numbers1[a+1] (you'll try to access the 15000001th element)

There is another problem, which will not make your program to fail, but seems to expose some misunderstanding of how the for loop works: specifically, you increment the x variable at each iteration, but that's futile since the variable x is used only the for initialization: the a = 1/x part is executed exactly once, prior to perform the loop. Here, a brief for primer:

for( Initializer; TestExpr; CountExpr ){ Body }

A machine that execute the loop will perform the following:

  1. Execute the Initializer code
  2. if TestExpr evaluate to false, goto 6
  3. execute the Body code
  4. execute the CountExpr code
  5. goto 2
  6. finish!

An advice that I can give you, is to try to work out on paper how to perform your task, using the usual math constructs, and then "port" your solution to java.

cheng81
  • 2,434
  • 2
  • 21
  • 18
1

Your logic in the for loop is not correct. Haha, i'm not quite sure what you're telling it to do but let's see if we can walk through it....

Forget the rest of the code for now, and focus on what the for loop is doing:

You initialize float variable 'a' as 1/x. Set the end value as the length of the array (good). and then you increment variables 'a' by 1 and 'x' by 1...

Now think of it this way, you initialize 'a' as 1/x, making it 1. It runs through the loop with the value a = 1. Then it increments 'x' by 1 and increments 'a' by 1. Now think hard because this is where your logic is flawed. This DOES in fact make x = 2 now, but you are ALSO making a = 2. 'x' and 'a' are independent variables. Reread the definition of the for loop and see if you can reconcile what you are attempting to do.

Now, a loop allows you to do iterations. In this case you have 30,000,000 of them (15,000,000 "counting up" and 15,000,000 "counting down"). So let's make two for loops, each with 15,000,000 iterations

for (int i = 1; i <= 15000000; i++){
statements;
}

for (int i = 15000000; i >= 1; i--){
statements;
}

Now, you want to sum together 1.0/1.0 + 1.0/2.0 + ... + 1.0/15,000,000.0. Initialize sum1 at 0:

float sum1 = 0; 

Each iteration you're going to add 1/i to the sum. Thus your statement inside each for loop will look like

sum1 += 1/i;

which is the same as

sum1 = sum1 + 1/i;

And there you have it. For the first loop, each iteration adds 1/i starting at i = 1 and ending at i = 15,000,000. For the second loop it adds 1/i starting at i = 15,000,000 and stopping at i = 1. Obviously in your case you can replace 15,000,000 with 'numbers1.length'. Then return sum1 and all your errors will disappear just like that.

note: careful how you constrain the for loop. Make sure it includes the end values. (note the <= 15,000,000 and >= 1 in the two loops) This will not make much a difference in your code and the answer will come out the same, but in the future it will be significant.

PMull34
  • 56
  • 5
0

use float if you wish but look at this: Java:Why should we use BigDecimal instead of Double in the real world?

It's called loss of precision.

Community
  • 1
  • 1
Jimmt
  • 852
  • 2
  • 11
  • 29
  • I don't prefer to use float, but that's the assignment. I think your point on loss of precision is likely what our professor is trying to teach us. – Bryan Jan 23 '12 at 00:51