Are unsigned vs. signed multiply performed differently? - binary

I'm trying to multiply two numbers together. One is 3'b111 and the other is 2'b11 (using Verilog syntax). If we assume those are unsigned, the result is:
111
x 11
-----
10101
This makes sense, since 3'b111 is 7, and 2'b11 is 3, and 7 * 3 = 21, which is 5'b10101. I'm good up to this point. But let's assume now that we're multiplying two signed numbers together. Now we have 3'b111 which is -1, and 2'b11 which is -1. We produce a 5-bit result, which is 5'b10101, the same result as the unsigned case. But here, we're getting -11 for our answer, rather than 1.
The code is producing the correct result, namely 5'b00001, but when you do it by hand I'm unable to get this. Why is this? Is the signed case treated differently than the unsigned case?

When implementing multiplication, the question always is:
How many bits must the adders have?
How many additions do I have to perform?
The answers are:
The adders must have the bit width of the product.
The number of additions is identical to the number of bits
the original multiplier has (this is even correct, if the operands
are in 2's complement).
So in terms of "how many adder bits and "how many additions"
signed and unsigned multiplication are handled identical.
But of course, as 2's complement represents negative numbers
by "too big" numbers, the algorithms of "how to add" are different.

Related

two's complement - what if there's one more bit needed to represent a binary in 2's complement form

I’m doing computer science A-level course in a high school and currently working on two’s complement arithmetic. For some reason I don’t quite get it. I know how to convert a signed integer into its two’s complement equivalent, but here’re my confusions:
I’ve done some research and people say the op-code which is the carry-bit tells the CPU if a 2’s complement code represents a positive integer or a negative, but sometimes the carry-bit is ignored according to some people; for instance, adding 1111 (-1) to 1000 (-8) you get 10111 (-9), but if it’s a 4-bit computer, the most significant bit which is the 5th bit cannot be stored, so how does the computer deal with that ?
A somewhat trivial question is if it’s given that 00110011 represent a signed integer in two’s complement form, how do I know if the actual code is 0110011, which is a positive number (in 2’s complement form), or 110011, which is a negative number (in 2’s complement form) ?
Thanks!
Typically, what doesn't fit is lost. So, 11112 + 10002 = 01112. However, some CPUs have special flags which get set to 0 or 1 depending on whether or not there's unsigned overflow (the carry flag) and signed overflow (the overflow flag). Some CPUs may be able to automatically raise an overflow exception when an arithmetic instruction can't produce result without overflow.
Typically, the CPU does not care if 11112 is -110 or 1510. Binary addition and subtraction of two N-bit integers gives you the same N-bit sum or difference irrespective of whether you're operating on unsigned integers or 2's complement signed integers. The same is true when multiplying two N-bit signed 2's complement or unsigned integers: the N least significant bits of the product is the same in both cases.
IOW, it's your job to keep track of what types you're manipulating, to take care of overflows (if they're possible) and to select proper instructions for those types (e.g. you typically have signed and unsigned division, signed and unsigned comparison, etc).

Binary Numbers - Difference between 15 and -1

I was learning binary numbers and 2's complement.
Lets say I have the binary number 1111. This is 15, but is also -1 (got from 2's complement method).
Can you explain how do i tell if it is 15 or -1?
Depends on the data type you use. Most programming languages offer signed and unsigned types.
A series of bits means nothing without a data type. E.g. an unsigned Int16 would contain only positive numbers up to 16 bits, while a signed Int16 would also contain negative numbers (but of course, less positive ones).
It's a matter of definition. If I write 10, you could read ten (decimal) or two (binary) or a whole bunch of other numbers, depending on the number system. If you don't know which system I use, there's no way you can tell what I mean. In your case, 15 is an answer in a unsigned binary system, -1 is an answer in a 2's compliment binary system.
If the register is 4-bit 2's complement, then the maximum range of values possible to be achieved is -8 to 7, so 15 is out of the question. For 15 to be represented, an unsigned register has to be used.

what would indicate an overflow?

Im doing this question and some clarification would be super helpful. What exactly would an overflow entail? If when converting to decimal notation an extra bit would be needed? Fro part 3 "consider the bits as two's complement numbers" does he mean find the 2's complement? Thanks a bunch.
For number 3 he does not mean find the 2's complement. He is telling you to treat the values as signed numbers using 2's complement notation. That would mean the first value in a) is positive and the other three are negative.
For overflow it is different for 2 and 3. For 2, unsigned numbers, overflow occurs if there is a carry out of the high bit. For 3, 2's complement signed numbers, overflow occurs if the sign of the result is not correct. For example, if you add two positive numbers and the result is negative, there was overflow.
If you add x and y and get a result that is less than x or less than y, then the addition has overflowed (wrapped-around).
An overflow would be if the resulting sum is a larger number than can be expressed in an 8 bit system. I believe that would be any number greater than 255 (1 << 8).
Your assumption "an extra bit" is mostly correct. In an 8 bit system, all numbers are stored in 8 bits. Any operation that results in a number greater than the maximum that can be represented will be an overflow. This doesn't happen when you convert to decimal, but when you actually perform the sum with the binary values. If all numbers are 8 bits, you can't just add an additional bit when you need to store a larger number.
Yes, "two's complement" is the same as "2's complement". I'm not aware of any distinction between whether you spell it out or use the numeral.

when two 16-bit signed data are multiplied, what should be the size of resultant?

I have faced an interview question related to embedded systems and C/C++. The question is:
If we multiply 2 signed (2's complement) 16-bit data, what should be the size of resultant data?
I've started attempting it with an example of multiplying two signed 4-bit, so, if we multiply +7 and -7, we end up with -49, which requires 7 bits. But, I could not formulate a general relation.
I think I need to understand binary multiply deeply to solve this question.
First, n bits signed integer contains a value in the range -(2^(n-1))..+(2^(n-1))-1.
For example, for n=4, the range is -(2^3)..(2^3)-1 = -8..+7
The range of the multiplication result is -8*+7 .. -8*-8 = -56..+64.
+64 is more than 2^6-1 - it is 2^6 = 2^(2n-2) ! You'll need 2n-1 bits to store such POSITIVE integer.
Unless you're doing proprietary encoding (see next paragraph) - you'll need 2n bits:
One bit for the sign, and 2n-1 bits for the absolute value of the multiplication result.
If M is the result of the multiplication, you can store -M or M-1 instead. this can save you 1 bit.
This will depend on context. In C/C++, all intermediates smaller than int are promoted to int. So if int is larger than 16-bits, then the result will be a signed 32-bit integer.
However, if you assign it back to a 16-bit integer, it will truncate leaving only bottom 16 bits of the two's complement of the new number.
So if your definition of "result" is the intermediate immediately following the multiply, then the answer is the size of int. If you define the size as after you've stored it back to a 16-bit variable, then answer is the size of the 16-bit integer type.

negative integers in binary

5 (decimal) in binary 00000101
-5 (two's complement) in binary 11111011
but 11111011 is also 251 (decimal)!
How does computer discern one from another??
How does it know whether it's -5 or 251??
it's THE SAME 11111011
Thanks in advance!!
Signed bytes have a maximum of 127.
Unsigned bytes cannot be negative.
The compiler knows whether the variable holding that value is of signed or unsigend type, and treats it appropriately.
If your program chooses to treat the byte as signed, the run-time system decides whether the byte is to be considered positive or negative according to the high-order bit. A 1 in that high-order bit (bit 7, counting from the low-order bit 0) means the number is negative; a 0 in that bit position means the number is positive. So, in the case of 11111011, bit 7 is set to 1 and the number is treated, accordingly, as negative.
Because the sign bit takes up one bit position, the absolute magnitude of the number can range from 0 to 127, as was said before.
If your program chooses to treat the byte as unsigned, on the other hand, what would have been the sign bit is included in the magnitude, which can then range from 0 to 255.
Two's complement is designed to allow signed numbers to be added/substracted to one another in the same way unsigned numbers are. So there are only two cases where the signed-ness of numbers affect the computer at low level.
when there are overflows
when you are performing operations on mixed: one signed, one unsigned
Different processors take different tacks for this. WRT orverflows, the MIPS RISC architecture, for example, deals with overflows using traps. See http://en.wikipedia.org/wiki/MIPS_architecture#MIPS_I_instruction_formats
To the best of my knowledge, mixing signed and unsigned needs to avoided at a program level.
If you're asking "how does the program know how to interpret the value" - in general it's because you've told the compiler the "type" of the variable you assigned the value to. The program doesn't actually care if 00000101 as "5 decimal", it just has an unsigned integer with value 00000101 that it can perform operations legal for unsigned integers upon, and will behave in a given manner if you try to compare with or cast to a different "type" of variable.
At the end of the day everything in programming comes down to binary - all data (strings, numbers, images, sounds etc etc) and the compiled code just ends up as a large binary blob.