1

Recently I was trying to implement Karatsuba multiplication for large numbers. Then I tried comparing my implementation with the Java BigInteger implementation. I could not follow this line of code:

// result = p1 * 2^(32*2*half) + (p3 - p1 - p2) * 2^(32*half) + p2
BigInteger result = p1.shiftLeft(32*half).add(p3.subtract(p1).subtract(p2)).shiftLeft(32*half).add(p2);

According to Karatsuba algorithm, result = (p1 * 10 ^ (2*half) ) + ( (p3 -p1 - p2) * 10 ^ (half)) + (p2)

Since the implementation used int[], I believe 32 is the number of bits in Java integer.

But I didn't understand the part that involves shifting the bits to the left. Can you someone help me understand what is going on here?

chandra_cst
  • 307
  • 2
  • 13
  • @djxak Can you tell me which portion of that post I should look at? It appears like not relevant. – chandra_cst Jan 09 '17 at 07:23
  • @djxak You are talking absolute, complete, and utter rubbish. This is a Java question about Karatsuba multiplication in `BigDecimal`. It has exactly nothing whatsoever to do with either Javascipt or global error handling. – user207421 Jan 09 '17 at 07:23
  • Isn't comment above the line answers this question? The left shift is like multiply by 2. – Ruslan Stelmachenko Jan 09 '17 at 07:23
  • Guys, of course it is not relevant. Just wrong browser tab, I revoked the flag asap, don't know why the comment isn't auto-deleted. Deleted it now. – Ruslan Stelmachenko Jan 09 '17 at 07:26
  • @djxak, Sure. I'm aware of that. But I'm trying to understand how the term (p1 * 10 ^ (2*half)) is translated to (p1.leftShift(32*half)). Like you said, left shift should multiplies by 2. – chandra_cst Jan 09 '17 at 07:29
  • 1
    The algorithm you gave is for base ten. The Java implementation is in base 2^32. – user207421 Jan 09 '17 at 07:29
  • @EJP oh, ok. in that case the term should be (p1 * 2 ^ (2 * 32 * half)) right? – chandra_cst Jan 09 '17 at 07:33
  • Or the shifting equivalent of that, which is what is actually used. – user207421 Jan 09 '17 at 07:34
  • @EJB, lets assume half is 2 and ignore 32 as it is constant anyways, if I try these two statements I get different results. System.out.println(10 * Math.pow(2, (2 * 2))); System.out.println(10 << 2); – chandra_cst Jan 09 '17 at 07:43
  • The left shift by `n` is like multiply by `2^n`. In your example you multiply by `2^(2*2)` = `2^4`. So it should be `10 << 4`. See a more detailed answer below. – Ruslan Stelmachenko Jan 09 '17 at 07:47
  • @djxak explain how does the term `p1 * 2^(32*2*half)` translates to `p1.shiftLeft(32*half)`. – chandra_cst Jan 09 '17 at 08:18
  • Ah, I understand now. You asking where is the `2` gone? I don't know really, but I suspect the order of operations is the case. The `BigDecimal`'s method `add()` is just a method. It is called in order, as usual methods. But the next multiply operation in the comment has precedence. So the code under comment is not exactly repeat the comment's expression. It's more like `(p1 * 2^(32*half) + (p3 - p1 - p2)) * 2^(32*half) + p2`. Maybe it is mathemathically equals to `p1 * 2^(32*2*half) + ((p3 - p1 - p2) * 2^(32*half)) + p2`? I don't know. – Ruslan Stelmachenko Jan 09 '17 at 08:38
  • You don't have any reason to assume that `half`` is 2. You have the source code. Read it, – user207421 Jan 09 '17 at 08:51
  • @EJP why do you think that he assume that `half` is 2? He talking about difference between comment above the code `2^(32*2*half)` and the code itself `shiftLeft(32*half)`. It's not the `half` is 2. The 2 is in the formula. – Ruslan Stelmachenko Jan 09 '17 at 08:56
  • @djxak He explicitly assumed that `half` is 2. Read it. "Let's assume `half` is 2". It's up there in black and white. – user207421 Jan 09 '17 at 09:11
  • @EJP you are talking about his previous comment which I already answered. He assume that `half` is 2 (just for concrete example) and asked why then `10 * Math.pow(2, (2 * 2))` is not equal to `10 << 2`. And it is because `2*2` is 4. :) It is obvious so I thought you talked about his last comment (which is another question). But let's stop the discussion in the comments. They are not for that. – Ruslan Stelmachenko Jan 09 '17 at 09:18
  • @djxak What part of "let's assume `half` is 2" didn't you understand? – user207421 Jan 09 '17 at 09:23

1 Answers1

0

Arithmetic shift

Arithmetic shifts can be useful as efficient ways to perform multiplication or division of signed integers by powers of two. Shifting left by n bits on a signed or unsigned binary number has the effect of multiplying it by 2^n. Shifting right by n bits on a two's complement signed binary number has the effect of dividing it by 2^n, but it always rounds down (towards negative infinity).

Ruslan Stelmachenko
  • 4,987
  • 2
  • 36
  • 51