I'm implementing a simple (virtual) ALU and some other chips (adder, multiplier etc.).
I'm using the 2's complement representation for my numbers.
For multiplication of x and y, two 16-bit numbers, I thought I'd use left shifts along these lines (this is of course performed without an actual loop):
set sum[0..15]=0
set x'=x
for i=0...15 //(y[0] is LSB and y[15] is MSB)
add x' to sum if y[i]=1 and shift x' left.
(Is this the standard way?)
My problem is with the left shifts:
If there's i s.t. x[i]=1, at some point the MSB of x' will become 1, and that negates it.
That's a problem since for example 2*2 using the method above gives "-4".
So, my actual question is: when shifting left do I also need to take into consideration the sign bit?
Yes, you do.
A simple approach could be to save the sign somewhere, convert to unsigned, perform the math, then convert back if it was negative.
Related
I have been reading a Elements of Programming Interview and am struggling to understand the passage below:
"The algorithm taught in grade-school for decimal multiplication does
not use repeated addition- it uses shift and add to achieve a much
better time complexity. We can do the same with binary numbers- to
multiply x and y we initialize the result to 0 and iterate through the
bits of x, adding (2^k)y to the result if the kth bit of x is 1.
The value (2^k)y can be computed by left-shifting y by k. Since we
cannot use add directly, we must implement it. We can apply the
grade-school algorithm for addition to the binary case, i.e, compute
the sum bit-by-bit and "rippling" the carry along.
As an example, we show how to multiply 13 = (1101) and 9 = (1001)
using the algorithm described above. In the first iteration, since
the LSB of 13 is 1, we set the result to (1001). The second bit of
(1101) is 0, so we move on the third bit. The bit is 1, so we shift
(1001) to the left by 2 to obtain (1001001), which we add to (1001) to
get (101101). The forth and final bit of (1101) is 1, so we shift
(1001) to the left by 3 to obtain (1001000), which we add to (101101)
to get (1110101) = 117.
My Questions are:
What is the overall idea behind this, how is it a "bit-by-bit" addition
where does (2^k)y come from
what does it mean by "left-shifting y by k"
In the example, why do we set result to (1001) just because the LSB of 13 is 1?
The algorithm relies on the way numbers are coded in binary.
Let A be an unsigned number. A is coded by a set of bits an-1an-2...a0 in such a way that A=∑i=0n-1ai×2i
Now, assume you have two numbers A and B coded in binary and you wand to compute A×B
B×A=B×∑i=0n-1ai×2i
=∑i=0n-1B×ai×2i
ai is equal to 0 or 1. If ai=0, the sum will not be modified. If ai=1, we need to add B×ai
So, we can simply deduce the multiplication algorithm
result=0
for i in 0 to n-1
if a[i]=1 // assumes a[i] is the ith bit
result = result + B * 2^i
end
end
What is the overall idea behind this, how is it a "bit-by-bit" addition
It is just an application of the previous method where you process successively every bit of the multiplicator
where does (2^k)y come from
As mentioned above from the way binary numbers are coded. If ith bit is set, then there is a 2i in the decomposition of the number.
what does it mean by "left-shifting y by k"
Left shift means "pushing" the bits leftwards and filling the "holes" with zeroes. Hence if number is 1101 and it is left shifted by three, it becomes 1101000.
This is the way to multiply the number by 2i (just as when "left shifting" by 2 a decimal number and putting zeroes at the right places is the way to multiply by 100=102)
In the example, why do we set result to (1001) just because the LSB of 13 is 1?
Because there is a 1 at right most position, that corresponds to 20. So we left shift by 0 and add it to the result that is initialized to 0.
I am a little desperate on how to detect an overflow when multiplying two 8-bit signed binary numbers? The result should also have 8-bit.
I multiply them in a microprogram using shift and add instructions. My algorithm works like this in pseudocode for multiplying binary numbers a * b, in addition I have an accumulator:
if least significant bit of b = 1 {
shift a to the left
add a to the accumulator
shift b to the right
jump to the if statement
} else {
shift b to the right
jump to the if statement
}
When shifting I fill with zeros and I stop this loop when b is zero. When I shift left I shift the most significant bit to the carry bit.
I already multiplied several binary numbers to see if I can find a pattern when the overflow should be set and when it should'nt, but I could not figure out when it should happen.
I also tried to find how the IMUL Assembler instruction sets its flags but I could not find anything that helped.
If anyone has any clue on how this works I would appreciate your help so much! Thanks in advance!
For bit-wise shift (or rotation, circulation) operations, we usually have an operator, i mean two of them, for instance
x << n
x >> n
for left or right shift of x by n bits.
We want to define a single function
bitshift(x, n)
Before that, we have to determine, which shift is to be used for positive and negative n - what is the "sign" of each shift (or rotation) direction.
Is there a definition or convention for that?
(Please note that this question has nothing to do with signed/unsigned types)
UPDATES
Please also note that i am not asking for implementation details of this function, even it might be somewhat related..
There are similar functions in scheme/lisp-like languages, like ash, which do left shift for positive n
Since shifting right by k places is equal to multiplying by 2^-k, and shifting left is equal to multiplying by 2^k, I think that should give you a hint.
Note: Reason I would argue for this way of looking at it is that it is common to consider multiplication as more fundamental operation in some sense than division is, although you could certainly argue the other way around.
You can use negative number as argument
For example
x << n
so pass n=2 if yuo want to left shift two positions
and pass n=-2 if you want to right shift two positions.
I know the "<<" is a bit operation. but I do not understand what it exactly functions in TCL, and when should we use it?
can anyone help me on this?
The << operator in Tcl's expressions is an arithmetic bit shift left. It's exceptionally similar to the equivalent in C and many other languages, and would be used in all the same places (it's logically equivalent to a multiply by a suitable power of 2, but it's usually advisable to use a shift when thinking about bits and a multiply when thinking about numbers).
Note that one key difference with many other languages (from Tcl 8.5 onwards) is that it does not “drop bits off the front”; the language implementation automatically uses wider number representations as necessary so that information is never lost. Bits are dropped by using a separate binary mask operation (e.g., & ((1 << $numBits) - 1)).
There are a number of uses for the << shift left operator. Some that come to my mind are :
Bit by bit processing. Shift a number and observe highest order bit etc. It comes in more handy than you might think.
If you add a zero to a number in the decimal number system you effectively multiply it by 10. shifting bits effectively means multiplying by 2. This actually translated into a low level assembly command of bit shifting which has lower compute cycles than multiplication by 2. This is used for efficiency in the gaming industry. Shift if twice (<< 2) to multiply it by 4 and so on.
I am sure there are many others.
The << operation is not much different from C's, for instance. And it's used when you need to shift bits of an integer value to the left. This can be occasionally useful when doing subtle number crunching like implemening a hash function or deserialising something from an input bytestream (but note that [binary scan] covers almost all of what's needed for this sort of thing). For a more general info refer to this Wikipedia article or something like this, this is not really Tcl-related.
The '<<' is a left bit shift. You must apply it to an integer. This arithmetic operator will shift the bits to left.
For example, if you want to shifted the number 1 twice to the left in the Tcl interpreter tclsh, type:
expr { 1 << 2 }
The command will return 4.
Pay special attention to the maximum integer the interpreter hold on your platform.
So I've just got a quick question on padding with 0's. The examples I made are below, just assumed that length doesn't matter and there is no sign bit.
a) 1000 = 00000001000
b) 110.101 = 110.00000101
c) 110.101 = 110.10100000
I know that padding the integer part of a binary number in front is fine (notwithstanding buffers and stuff like that). Its more when I deal with radix points that I can never remember how it works. Do you pad beside the radix (b) or at the end of the digit (c). Also, does padding like this effect the complements of these numbers?
Thanks
EDIT:
The reason I'm asking this is because I'm converting from binary to hex and binary to octal. To do this I have to group bits in groups of 4 or 3. I don't have enough bits so I need to add zeros somewhere.
Two's radix works the same way as the base-10 numbers (according to Wikipedia)
Thus, parts (a) and (c) are correct, but part (b) is not.
The bits to the left of the binary point should follow the same algorithm to find their complement, with the MSB of fractional bit being positive.