Steve Vickers: Introduction to Computer Science

Fundamentals of Computing: Introduction to Computer Science

Assessed coursework 1: solutions

See further down for feedback on general performance on coursework.

1. Here is my Java code for magnitude.

    public double magnitude(){
        double sumsq = 0;
        for (int i = 0; i < a.length; i++){
            double ai = a[i];
            sumsq += ai*ai;
        }
        return Math.sqrt(sumsq);
    }

2. Here is the disassembled output from javap.

  public double magnitude();
    Code:
       0: dconst_0
       1: dstore_1
       2: iconst_0
       3: istore_3
       4: iload_3
       5: aload_0
       6: getfield      #2                  // Field a:[D
       9: arraylength
      10: if_icmpge     35
      13: aload_0
      14: getfield      #2                  // Field a:[D
      17: iload_3
      18: daload
      19: dstore        4
      21: dload_1
      22: dload         4
      24: dload         4
      26: dmul
      27: dadd
      28: dstore_1
      29: iinc          3, 1
      32: goto          4
      35: dload_1
      36: invokestatic  #3   // Method java/lang/Math.sqrt:(D)D
      39: dreturn

3. The local variables are as follows.
0: "this"
1: sumsq (two variable entries)
3: i
4: ai (two variable entries)

4. The lines of bytecode correspond to parts of Java code as follows.
0,1: sumsq = 0;
2,3: i = 0; (initializer in for-loop)
4,5,6,9,10: i < a.length; (loop test in for-loop)
13, 14, 17, 18, 19: ai = a[i];
21, 22, 24, 26, 27, 28: sumsq += ai*ai;
29: i++ (increment part of for-loop)
32: to loop back in for-loop
35, 36, 39: return Math.sqrt(sumsq);

5. The main iteration starts at line 4, with the loop test, and goes through to line 32. After each line the operand stack contents are as follows, written with the top on the right.

 4: i
 5: i, this
 6: i, a
 9: i, a.length
10: empty
13: this
14: a
17: a, i
18: a[i]
19: empty
21: sumsq
22: sumsq, ai
24: sumsq, ai, ai
26: sumsq, ai*ai
27: sumsq + ai*ai
28: empty
29: empty
32: empty

Assessed coursework: feedback

Here is some general feedback on how you managed with the coursework. There were some good answers, but also a lot of you misunderstood what was required. A general fault was writing too much. Make sure you check the solutions to see what is really needed - if you write too much in the exam you risk losing a lot of time.

Of 50 submissions, 22 of you got 70% (18 marks) or more, and 14 got between 50% and 69%.

The pass mark for the module is 50%, which in this exercise would be 13 marks.

If you got 12 marks or less I suggest you come to see me in my office hour (10-12 Tuesdays, room 215) for advice. Bring your marked answers with you.

Here is feedback on individual questions.

  1. Most of you got this essentially right, but one common fault was to use an instance variable instead of a local variable for something temporary needed in the method - for example, sumsq in my solution for the sum of squares so far.
    Make absolutely sure you understand the difference between local variables (including parameters) and instance variables (or non-static fields). Local variables are stored in the stack frame for a method call, and are just temporary for that call, while instance variables are stored on the heap as part of an object and persist between method calls. As a general rule, if you don't need the value to persist between method calls then it should be a local variable.
    Although they look very similar in the Java declarations, they are very different in the bytecode: local variables are accessed with load and store, instance variables with getfield and putfield - and instance variables are likely to be slower.
    * If you used instance variables instead of local variables the method would probably still work. However, one trap is to forget to reset them each time the method is called - it is certainly not enough just to initialize in the constructor.
  2. Difficult to get less than three marks here if your class successfully compiled and you followed the instructions for javap.
  3. The question is quite simple as long as you understand what is required. In the stack frame there is some space allocated for local variables, and each 4 byte entry has an index. You just have to match those indexes to local variables (and parameters) in the Java.
    * Don't forget that for a non-static method, index 0 always corresponds to "this".
    * Some of you used "for(double x: a)". Note that the Java compliler invents some extra local variables, without names but with indexes in the stack frame, for a reference to the array, its length, and the array index of the element being accessed.
  4. For a question like these make sure you say which parts of the Java source match which sequences of bytecode instructions. I deducted marks if you didn't reference the Java clearly.
    * Don't write detailed explanation to say what each bytecode operation does. Just say which pieces of bytecode relate to which pieces of Java.
  5. Make sure you understand how to answer this kind of question. I asked you to explain what the contents of the operand stack will be at the end of each bytecode operation.
    - Make a list of the bytecode operations (line by line, as in the disassembled version).
    - For each one, describe the whole of the operand stack after that operation.
    - Don't describe how the operations changes the stack (pushes this, pops that); just say what is on the stack afterwards.
    - It's usually easiest to write the stack sideways (top to right, bottom to left). You don't lose marks for not doing it like this, but it's usually easiest for you to write.

    * Understand how instance variables are accessed, with getfield (or putfield).
    - aload_0 pushes an object ref to "this".
    - getfield pops that and pushes the instance variable.
    - in this exercise the instance variable a is also an object ref, to an array.