MARIE Assembly If-Then - if-statement

Pseudocode:
if x > 1 then
y = x + x;
x = 0;
endif;
y = y + 1;
I am tracing the MARIE code below based from the pseudocode:
ORG 100
IF, LOAD X
SUBT ONE / What is this for?
SKIPCOND 800
JUMP ENDIF
THEN, LOAD X
ADD X
STORE Y
LOAD ZERO
STORE X
ENDIF, LOAD Y
ADD ONE
STORE Y
HALT
X, DEC ?
Y, DEC ?
ONE, DEC 1
ZERO, DEC 0
Why is the SUBT ONE needed there?

It does the comparison by subtracting 1 from x, leaving the result in the accumulator. We can then use a conditional branch on whether the resulting value in AC is zero, positive or negative.
Look up what SKIPCOND 800 does: How does `Skipcond` work in the MARIE assembly language?
Unlike most architectures where add/subtract instructions set flags and conditional branches test them, MARIE's conditional branch instruction is a test-and-branch, like MIPS bgtz / beq with $zero / bltz

I think the reason they add
SUBT ONE
is because we don't have a skip condition for x > 1, but we do have a skip condition for x > 0, which is
skipcond 800 / meaning X > 0
Since that's the case, I think they just subtracted one from both sides, making them both equal. (x - 1) > (1 - 1) / same as (x - 1) > 0. from here, we can use skipcond.
That's my best educated guess for why that's included. Hope this helps five years later.

Use MARIE Simulator to enter and run the following program:
Input
Store TestVal
If, Skipcond 800
Jump Else
Then, Store Y
Add Y
Jump EndIf
Else, Load Y
EndIf, Add X
Add X
Store Z
Output
Halt
X, Dec 5
Y, Dec 2
Z, Dec 0
TestVal, Dec -1
instructions:
Use “ORG” instruction to start your program at address 100.
Use your last university ID number when you are asked to input a number.
For example, if your ID is1415161678532, then you will use the number 2.
b) Suppose that the value, say a, has been entered. What are the instructions in
the above program that will be executed? Your answer should explain the flow
of execution for a<0, a=0, and a>0.
c) Based on your answer in part b, formulate what happens in the three cases, by
stating the output as a function of the variables (for example, Output= 3x-2a+y)

Related

Can I prevent GNU bc from spewing out zeros?

Suppose I want to solve the equation x + 3 = 40 using GNU bc. One way I could do this would be to start by checking to see if 0 is a solution, then checking 1, and so on, until I get to the right answer. (Obviously not the best way to do algebra, but oh well.) So I enter the following code into GNU bc:
int solver(int x);
define solver(x){
if(x + 3 == 40) return x;
x = x + 1;
solver(x)
}
solver(0)
It produces 37 - the right answer, of course - but the 37 is then followed by 37 zeros. Based on some experimentation, it seems like each zero comes from an instance of the if statement being false, but how do I prevent the zeros from showing up? I'm using GNU bc to solve more complicated functions and create more complex lists of numbers, so it really isn't practical for me to sort through all the zeros. Any help would be appreciated, since I haven't yet figured anything out.
For each operation that isn't an assignment, bc prints an exit status. One way to suppress that is to assign to the dummy value . (which is just the value of the last result anyway), another way is to make sure you explicitly print exactly what you need.
I would have written your function like this:
#!/usr/bin/bc -q
define solver(x) {
if (x + 3 == 40) return x
return solver(x+1)
}
print solver(0), "\n"
quit
A few remarks for your attempt:
I don't understand what your first line is supposed to do, I just dropped it
I've indented the code, added some whitespace and removed the semicolons – mostly a matter of taste and readability
I've simplified the recursive call to avoid the solver(x) line stand on its own, as this produces the spurious 0
As for your suspicion that the if statement produces the zeroes: try, in an interactive session, the following:
1 == 2 # Equality test on its own produces output
0
1 == 1 # ... for both true and false statements
1
if (1 == 2) print "yes\n" # No output from false if condition
if (1 == 1) print "yes\n" # If statement is true, print string
yes

Linear Programming: Depict logical expression in a boolean variable

I have a mixed integer linear program (MIP or MILP).
In the end I want a boolean variable im my linear program, that has the following properties.
I have two variables:
boolean b.
real x, with x being 0 or larger.
What I want to achieve is:
b == false if x == 0.
b == true if x > 0.
I found a way to depict if x is in specific range (e.g. between 2 and 3) via:
2*b <= x
x <= 3*b
The problem with the above testing formula is, that b will be true if x is in the given range and false if outside that range.
Does anybody know a way to set a boolean variable to false if x == 0 and to true if x is larger than 0?
If U is an upper bound of x then
if x > 0 ==> b == 1
can be made as
x <= U*b
The second part (x == 0 => b == 0) needs to be modified to
x < epsilon ==> b == 0
which can be made as
b <= 1 + x - epsilon
where epsilon is a small number. Other than good practice this is necessary, because solvers do not work in rational arithmetic (although there are some research efforts to make them do so), but with certain precision thresholds, and therefore quantities such as 10e-12 are treated as zero.
I hope this helps!
You could use the signum function http://en.wikipedia.org/wiki/Signum_function take the absolute value and negate it. Since you didn't name a specific programming language I keep it general.

How to assign binary variable in AMPL in respect to another variable

I have a problem with AMPL modelling. Can you help me how to define a binary variable u that suppose to be equall to 0 when another variable x is also equall to 0 and 1 when x is different than 0?
I was trying to use logical expressions but solver that I am working with (cplex and minos) doesn't allow it.
My idea was:
subject to:
u || x != u && x
Take M a 'big' constant such as x < M holds, and assume x is an integer (or x >= 1 if x is continuous). You can use the two constraints:
u <= x (if x=0, then u=0)
x <= M*u (if x>0, then u=1)
with u a binary variable.
If now x is continuous and not necessarily greater than 1, you will have to adapt the constraints above (for example, the first constraint here would not be verified with x=0.3 and u=1).
The general idea is that you can (in many cases) replace those logical constraints with inequalities, using the fact that if a and b are boolean variables, then the statement "a implies b" can be written as b>=a (if a=1, then b=1).

Return statement that works but doesn't make much sense

I have the following function:
int mult(int y, int z)
{
if (z == 0)
return 0;
else if (z % 2 == 1)
return mult(2 * y, z / 2) + y;
else
return mult(2 * y, z / 2);
}
What I need to do is prove its correctness by induction. Now the trouble I'm having is that even though I know it works since I ran it I can't follow each individual step.
What is confusing me is that y only shows up as an argument and in no place does it show up in a return except in the recursive part, and yet the function actually returns y as the answer.
How does this happen? I need to be able to follow everything that happens so that I can do the iterations of it for the proof.
Since this is obviously a homework question, I recommend you do what the assinment was likely meant fot you to do. Trace through the code.
1) give a starting value for y and z.
2) either on paper or in a debugger, trace what happens when you call the function.
3) repeat step 2 with your current y/z values until program completion.
#include <iostream>
using namespace std;
int mult(int y, int z)
{
if(z==0) {
cout<<"z is null! - y:"<<y<<" z: "<<z<<endl;
return 0;
}
else if (z%2==1)
{
cout<<"z is odd! - y:"<<y<<" z: "<<z<<endl;
// make z even
return mult(2*y,z/2)+y;
}
else
{
cout<<"z is even! - y:"<<y<<" z: "<<z<<endl;
return mult(2*y,z/2);
}
}
int main() {
cout<<"result: "<<mult(3,13)<<endl;
}
Output:
z is odd! - y:3 z: 13
z is even! - y:6 z: 6
z is odd! - y:12 z: 3
z is odd! - y:24 z: 1
z is null! - y:48 z: 0
result: 39
How it works for 3 and 13:
There's a switch for even and odd numbers (see comment in code).
When z is null, the recursion "starts to return to the initial call". If the number z is odd it adds y to the returned value of the recursive call, if it's even it justs returns the value from the recursive call.
odd: return 0 + 24
odd: return 24 + 12
even: return 36
odd: return 36 + 3
step-by-step analisis
final result: 100
mult(10, 10)
{
makes 100
mult(20, 5)
{
makes 100
mult(40, 2) + 20
{
makes 80
mult(80, 1)
{
makes 80
mult(160, 0) + 80
{
return 0;
}
}
}
}
}
Note: If this is homework, tag it as such.
So, we basically got three recursive cases. To make it all clearer, I'd rewrite the C-code into some functional pseudo-code. Replace mult with an intuitive operator sign and figure out descriptive explanations of low-level expressions like (z%2==1).
You'll come up with something like
a ** b =
| b is 0 -> 0
| b is even -> 2a ** (b/2)
| b is odd -> 2a ** (b/2) + a
Do you get the point now?
One approach would be to translate each line into "English". My translation would be something like this:
if z is zero, return zero
if z is odd, return mult(y*2, z/2) + y
if z is even, return mult(y*2, z/2)
The general pattern is to recursively call mult with the first parameter doubling, and the second parameter halving.
Note that here you're calling mult with z/2, but its arguments are integers, so if your function continues to recurse, the 2nd parameter will halve each time until it gets down to 1, and then finally 1/2 which rounds down to 0 - at which point recursion will stop because z==0.
With those clues, you should be able to understand how this algorithm works.
Demonstrations by induction are based on proving that the result is valid for the first value, and that if the principle is correct for a generic value N, it is provable that it holds for N+1.
To simplify, you can start by proving that it works for z in { 0, 1, 2 } which should be trivial with a manual test. Then to demonstrate the induction step, you start with a generic z=N, and prove that if mult( y, N ) is a valid result, then mult( y, N+1 ) is also a valid result in terms of the previous one. Since there are different branches for even and odd numbers, you will have to prove the induction step for both even and odd N numbers.
ya = ya
a = an even number
b = the next odd number (in other words a + 1)
So, if you want the equation above in terms of only even numbers (an 'a') when given an odd number (a 'b') you can do the following:
yb = y(a+1) = y*a + y
Now confuse everyone by writing 'a' as 2*(z/2).
y*a becomes (2*y)*(z/2)
y*b becomes ((2*y)*(z/2))+y
Since 'z' appears in the formula for both even and odd numbers, we want to think that the code is telling us that (2*y)*(z/2) = (2*y)*(z/2) + y which is obviously MADNESS!
The reason is that we have snuck in the fact that z/2 is an integer and so z can never be odd. The compiler will not let us assign z/2 to an integer when z is odd. If we try to make 'z' odd, the integer we will really be using is (z-1)/2 instead of z/2.
To get around this, we have to test to see if z/2 is odd and pick our formula based on that (eg. either ya or yb in terms of 'a').
In mult(y,z) both 'y' and 'z' are both integers. Using the symbols above mult(2*y,b/2) becomes mult(2*y,a/2) because b/2 will be truncated to a/2 by the compiler.
Since we are always going to get an 'a' as a parameter to 'mult', even when we send a 'b', we have to make sure we are only using formulas that require 'a'. So, instead of yb we use ya+1 as described above.
b/2 = a/2 + 1/2 but 1/2 cannot be represented as part of an int.
Not really an answer, but more of a suggestion.
You may want to reduce the recursion call from 2 to one:
int mult(int y, int z)
{
int result = 0;
if (z == 0)
return result;
result = mult(2 * y, z / 2); // Common between "then" and "else"
if ((z % 2) == 1)
{
result += y;
}
return result;
}
This could be simplified once more by observing the rule "one exit point only":
int mult(int y, int z)
{
int result = 0;
if (z != 0)
{
result = mult(2 * y, z / 2); // Common between "then" and "else"
if ((z % 2) == 1)
{
result += y;
}
}
return result;
}
Although many compilers will perform this simplification automatically, debugging is usually easier when the code is simplified. The debugger will match the code when single-stepping.
Sometimes simplifying will add clarity. Also, adding comments will help you figure out what you are doing as well as the next person who reads the code.

Turn while loop into math equation?

I have two simple while loops in my program that I feel ought to be math equations, but I'm struggling to convert them:
float a = someValue;
int b = someOtherValue;
int c = 0;
while (a <= -b / 2) {
c--;
a += b;
}
while (a >= b / 2) {
c++;
a -= b;
}
This code works as-is, but I feel it could be simplified into math equations. The idea here being that this code is taking an offset (someValue) and adjusting a coordinate (c) to minimize the distance from the center of a tile (of size someOtherValue). Any help would be appreciated.
It can be proved that the following is correct:
c = floor((a+b/2)/b)
a = a - c*b
Note that floor means round down, towards negative infinity: not towards 0. (E.g. floor(-3.1)=-4. The floor() library functions will do this; just be sure not to just cast to int, which will usually round towards 0 instead.)
Presumably b is strictly positive, because otherwise neither loop will never terminate: adding b will not make a larger and subtracting b will not make a smaller. With that assumption, we can prove that the above code works. (And paranoidgeek's code is also almost correct, except that it uses a cast to int instead of floor.)
Clever way of proving it:
The code adds or subtracts multiples of b from a until a is in [-b/2,b/2), which you can view as adding or subtracting integers from a/b until a/b is in [-1/2,1/2), i.e. until (a/b+1/2) (call it x) is in [0,1). As you are only changing it by integers, the value of x does not change mod 1, i.e. it goes to its remainder mod 1, which is x-floor(x). So the effective number of subtractions you make (which is c) is floor(x).
Tedious way of proving it:
At the end of the first loop, the value of c is the negative of the number of times the loop runs, i.e.:
0 if: a > -b/2 <=> a+b/2 > 0
-1 if: -b/2 ≥ a > -3b/2 <=> 0 ≥ a+b/2 > -b <=> 0 ≥ x > -1
-2 if: -3b/2 ≥ a > -5b/2 <=> -b ≥ a+b/2 > -2b <=> -1 ≥ x > -2 etc.,
where x = (a+b/2)/b, so c is: 0 if x>0 and "ceiling(x)-1" otherwise. If the first loop ran at all, then it was ≤ -b/2 just before the last time the loop was executed, so it is ≤ -b/2+b now, i.e. ≤ b/2. According as whether it is exactly b/2 or not (i.e., whether x when you started was exactly a non-positive integer or not), the second loop runs exactly 1 time or 0, and c is either ceiling(x) or ceiling(x)-1. So that solves it for the case when the first loop did run.
If the first loop didn't run, then the value of c at the end of the second loop is:
0 if: a < b/2 <=> a-b/2 < 0
1 if: b/2 ≤ a < 3b/2 <=> 0 ≤ a-b/2 < b <=> 0 ≤ y < 1
2 if: 3b/2 ≤ a < 5b/2 <=> b ≤ a-b/2 < 2b <=> 1 ≤ y < 2, etc.,
where y = (a-b/2)/b, so c is: 0 if y<0 and 1+floor(y) otherwise. [And a now is certainly < b/2 and ≥ -b/2.]
So you can write an expression for c as:
x = (a+b/2)/b
y = (a-b/2)/b
c = (x≤0)*(ceiling(x) - 1 + (x is integer))
+(y≥0)*(1 + floor(y))
Of course, next you notice that (ceiling(x)-1+(x is integer)) is same as floor(x+1)-1 which is floor(x), and that y is actually x-1, so (1+floor(y))=floor(x), and as for the conditionals:
when x≤0, it cannot be that (y≥0), so c is just the first term which is floor(x),
when 0 < x < 1, neither of the conditions holds, so c is 0,
when 1 ≤ x, then only 0≤y, so c is just the second term which is floor(x) again.
So c = floor(x) in all cases.
c = (int)((a - (b / 2)) / b + 1);
a -= c * b;
Test case at http://pastebin.com/m1034e639
I think you want something like this:
c = ((int) a + b / 2 * sign(a)) / b
That should match your loops except for certain cases where b is odd because the range from -b/2 to b/2 is smaller than b when b is odd.
Assuming b is positive, abs(c) = floor((abs(a) - b/2) / b). Then, apply sign of a to c.