0

For instance, given a word size of 4 bits:

0b1001 * 0b0111 = 0b1111 // -7 * 7 = -1
0b0111 * 0b0111 = 0b0001 // 7 * 7 = 1
0b0111 * 0b0110 = 0b1010 // 7 * 6 = -6
0b1001 * 0b0110 = 0b0110 // -7 * 6 = 6

There's undoubtedly some modular arithmetic going on here, but the way you take mod seems to be quite inconsistent. Is there a neat mathematical formulation of two's complement multiplication?

Frank
  • 414
  • 4
  • 15
  • By discarding the high-order bits you are effective taking the result of the multiplication mod 16 (=2^4). As unsigned integers you take the residue system as {0,1,.., 15} in the natural way. If you treat them as twos-complement integers then the residue system becomes {-8, -7, ..., -1, 0, 1, ..., 7} – President James K. Polk Apr 08 '20 at 01:59
  • Hmm, I see. But how do I know if the is (i.e.) -2 or +6? It doesn't seem to be based on the sign of the operands. – Frank Apr 08 '20 at 02:23
  • Ok, I think I understand what you're asking. And offhand I don' see anyway to predict the sign of the result. You are taking an 8-bit product and throwing away the high-order 4 bits. I'm tempted to say that whether the 4th bit is a 1 or 0 is somewhat random. – President James K. Polk Apr 08 '20 at 02:28
  • Does this answer your question? [How do you detect 2's complement multiplication overflow?](https://stackoverflow.com/questions/50684187/how-do-you-detect-2s-complement-multiplication-overflow) – phuclv Apr 08 '20 at 06:57
  • No, I’m asking for a formula for computing overflow, and that question only seems to determine how to detect overflow. – Frank Apr 10 '20 at 00:47

1 Answers1

0

The nice thing about twos complement is that addition, subtraction, and multiplication of signed operands are exactly the same operations, bit-for-bit, as the ones for unsigned operands, so the computer doesn't need to care whether you think of them as signed or not.

In terms of modular arithmetic as well, the operations mean exactly the same thing. With 4 bit words, when you say:

r = a * b;

You get r = a * b mod 16.

The only difference between signed and unsigned is the value we assign in our heads to the residues mod 16. If we think of the words as unsigned then we have values 0-15. But 15 = -1 mod 16, 14 = -2 mod 16, etc, and if we think of the words as signed, then we just think of the values -8 to 7 instead of 0 to 15.

The reminder operator % that you get in C, java, etc, is annoying in the way it handles negative numbers. If you wanted to express your 4-bit multiply using that operator in larger words, then you could say:

a * b =  ( (a * b % 16) + 24 ) % 16 - 8

If the remainder operator worked "properly" so that -1 % 16 == 15, then you could write a * b = (a * b + 8) % 16 - 8

Matt Timmermans
  • 53,709
  • 3
  • 46
  • 87
  • How did you `a * b = ( (a * b % 16) + 24 ) % 16 - 8`? Seems a bit random to me. Is there a way to logically construct this? – Frank Apr 08 '20 at 04:29
  • @Frank, the first `%16` returns a result from -15 to 15. The `+24` is +16 to make that positive, and +8 to offset the subtraction at the end. – Matt Timmermans Apr 08 '20 at 12:09
  • How are we able to treat the product like this? Some products don’t really make any sense when they overflow. For instance, 7 * -7 is 0b111111 (63 reading as unsigned) before truncating, which doesn’t really seem possible to interpret in any meaningful way. – Frank Apr 10 '20 at 00:55
  • 7*-7 is not 0b111111. If you want to do a 4-bit multiplication, then it's 0b1111, because -49 = 15 mod 16. If you want to do a 6-bit multiplication, then -7 is 111001 and 7 * -7 = 0b001111, because 49 = 15 mod 64 – Matt Timmermans Apr 10 '20 at 03:36
  • Hmm.. I realize that was a stupid comment. However, I'm still not sure how you are able to take (a * b) and perform %16. Wouldn't you need to convert a and b to unsigned integers first? – Frank Apr 10 '20 at 05:17