0

I'm writing a multiplication program for a virtual computer called AIDJ.

It supports any number of variables and is able to read and execute any sequence of operations (programme) of the form

mk: <operation>

Where mk is the marker and must only be taken from:

Increment: x(i) = x(i) + 1 
Decrement: x(i) = x(i) - 1 
Conditional Jump: if x!=0 goto <mk>
Assignment: x(i) = c (where c is any natural number)

Apart from potential conditional jumps - AIDJ evaluates the operations in the order described by the programme and stops when the programme is completely processed.

Take for example the programme ADD with c >= 1:

00: x(1) = c
01: x(2) = d
02: x(2) = x(2) + 1
03: x(1) = x(1) - 1
04: if x(1) != 0 goto 02

Take for example the programme MULTIPLY with c >= 2:

00: x(1) = d
01: x(1) = d - 1
02: x(2) = c
03: x(3) = c
04: x(2) = x(2) + 1
05: x(3) = x(3) - 1
06: if x(3) =! 0 goto 04
07: x(1) = d - 1
08: if x(3) =! 0 goto 03 

I am making sure that c × d equals c + c + … + c (d summands) so I can use the programme ADD, and we make sure that ADD is executed d-1 times. When the computation stops, x(2) equals c × d.

This would produce following table of values if c=3 and d=3:

| Command                   | x(1) | x(2) | x(3) |
--------------------------------------------------
| 00: x(1) = d              | 3    | -    | -    |
| 01: x(1) = d - 1          | 2    | -    | -    |
| 02: x(2) = c              | 2    | 3    | -    |
| 03: x(3) = c              | 2    | 3    | 3    |
| 04: x(2) = c + 1          | 2    | 4    | 3    |
| 05: x(3) = d - 1          | 2    | 4    | 2    |
| 06: if x(3) =! 0 goto 04  | 2    | 4    | 2    |
| 04: x(2) = c + 1          | 2    | 5    | 2    |
| 05: x(3) = d - 1          | 2    | 5    | 1    |
| 06: if x(3) =! 0 goto 04  | 2    | 5    | 1    |
| 04: x(2) = c + 1          | 2    | 6    | 1    |
| 05: x(3) = d - 1          | 2    | 6    | 0    |
| 06: if x(3) =! 0 goto 04  | 2    | 6    | 0    |
| 07: x(1) = d - 1          | 1    | 6    | 0    |
| 08: if x(3) =! 0 goto 03  | 1    | 6    | 0    |
| 03: x(3) = c              | 1    | 6    | 3    | 
| 04: x(2) = c + 1          | 1    | 7    | 3    |
| 05: x(3) = d - 1          | 1    | 7    | 2    |
| 06: if x(3) =! 0 goto 04  | 1    | 7    | 2    |
| 04: x(2) = c + 1          | 1    | 8    | 2    |
| 05: x(3) = d - 1          | 1    | 9    | 1    |
| 06: if x(3) =! 0 goto 04  | 1    | 9    | 1    |
| 04: x(2) = c + 1          | 1    | 9    | 1    |
| 05: x(3) = d - 1          | 1    | 9    | 0    |
| 06: if x(3) =! 0 goto 04  | 1    | 9    | 0    |
| 07: x(1) = d - 1          | 0    | 9    | 0    |
| 08: if x(3) =! 0 goto 03  | 0    | 9    | 0    |

How would I alter the the above program so that it divides instead of multiply?

4

1 回答 1

4

Multyplying is adding in a loop, right? Well, dividing is subtracting in a loop until what's left of the dividend is less than the divisor. In pseudocode:

# We're dividing a/b, getting the quotient c
c = 0
while a >= b
{
    a = a - b
    c = c+1
}
# End of loop
# The value of a is the remainder at this point

So go with this. First, implement subtraction (which is decrement in a loop, on your VM). Then do the rest.

Since your conditionals are limited to comparing with zero, implement the logic of a>=b via subtraction (decrement in a loop). And don't be afraid to introduce extra variables. The architecture might be stunted, but there's no explicit limit on memory used, is there?

You can even combine the loop condition (which is decrement in a loop) with the loop body (also decrement in a loop). That's not how they'd do it in a high level language, and not even how a real CPU would do it - all modern CPUs have integer comparison as a primitive. Something along the lines of "decrement, if reached zero before the remain of the divisor reaches zero, then quit the loop and we're done". In real life, however, this kind of microoptimization (for a nonexistent architecture, no less) would be strongly recommended against.

Also, if this is homework, please add the tag "homework". Smells a lot like homework to me.

EDIT: here's the logic. We introduce three variables:

  • x(1) is the running copy of the dividend to be decremented
  • x(2) is the quotient - zero initially, to be incremented
  • x(3) is the running loop variable for the divisor.
  • d is the dividend
  • c is the divisor.
  • we can assign constants (like zero) to variables, can we?

Using a pseudocode that corresponds to the primitives of your VM. You translate it to AIDJ syntax - I mean, you have to do at least some work here. # marks comments. Labels (i. e. goto destinations) are marked with :

x(1) = d
x(2) = 0
x(3) = c

Main_Loop:

x(1) = x(1) - 1 # decrement the running copy of the dividend
x(3) = x(3) - 1 # decrement the running copy of the divisor
if x(3) != 0 goto Divisor_still_nonzero

# If we're here, this means we've reached the end of the divisor.
# Increment the quotient, reset the running divisor to the initial value

x(2) = x(2) + 1
x(3) = c

Divisor_still_nonzero:

# Now let's check if we've reached the zero on the dividend
if x(1) != 0 then goto Main_Loop

# If x(1) is zero then we end up here.
# Means we've exhausted the dividend.
# Now the value of x(2) is the quotient.
# The remainder is c minus x(3),
# but retrieving it was not a requirement.

In real life, you should also check if c and d are zero or negative in the very beginning. If d is zero, the code will break - it'll go into negatives on the very first iteration, and will terminate only if the variables are subject to overflow. If c is zero, the whole division is illegal.

Extra handling for negatives is required, too.

Also, keep in mind that some professors are known to watch Stack Overflow.

于 2012-06-14T15:16:28.853 回答