3

Imagine that we have e.g. 1000 bit word in our memory. I'm wondering if there is any way to calcuate a square root of it (not necessarily accurate, lets say without floating point part). Or we've got only memory location and later specified various size.

I assume that our large number is one array (most significant bits at the beginning?). Square root is more or less half of original number. When trying to use Digit-by-digit algorithm there is a point when usnigned long long is not enough to remember partial result (subtraction with 01 extended number). How to solve it? What with getting single digit of the large number? Only by bitmask?

While thinking about pseudocode stucked at this questions. Any ideas?

rink.attendant.6
  • 44,500
  • 61
  • 101
  • 156
Prolatser
  • 31
  • 1
  • 1
    First idea: Newton's method. Then you only need to implement division and addition. Those are not so hard to make. – Gábor Buella Apr 06 '14 at 12:56
  • @BuellaGábor Division is :) – Rontogiannis Aristofanis Apr 06 '14 at 13:03
  • It isn't :) A bit tricky maybe, but fairly simple I think. – Gábor Buella Apr 06 '14 at 13:12
  • look for bignum/bigint algorithms. for binary search algorithm (is in one of the answers below) sqrt you need operations AND,OR,and Multiply or Square. AND and OR are easy, the MUL or SQR can be also done by binary algorithms just google a little ... if you have fixed point or integer numbers only the algorithm is the same for both. with FPU you need to add some tweaking with mantisa/exponent – Spektre Apr 06 '14 at 17:32

4 Answers4

1

How would you do it by hand? How would you divide a 1000 digit number by a 500 digit by hand? (Just think about the method, obviously it would be quite time consuming). Now with a square root, the method is very similar to division where you "guess" the first digit, then the second digit and so on and subtract things. It's just that for a square root, you subtract slightly different things (but not that different, calculating a square root can be done in a way very similar to a division except that with each digit added, the divisor changes).

I wouldn't want to tell you exactly how to do it, because that spoils the whole fun of discovering it yourself.

The trick is: Instead of thinking about the square root of x, think about finding a number y such that y*y = x. And as you improve y, recalculate x - y*y with the minimum effort.

gnasher729
  • 51,477
  • 5
  • 75
  • 98
1

Calculating square roots is very easily done with a binary search algorithm.

A pseudo-code algorithm:

  • Take a guess c: the 1000 bit value divided by 2 (simple bitshift).
  • Square it:
    • If the square (almost) equals your 1000 bit number you've got your answer
    • If the square is smaller than your number, you can be sure the root is between c and your upper bound.
    • If the square is larger than your number, you know that the root lies between your lower bound and c.
  • Repeat until you have found your root, while keeping track of your upper and lower bound.

This kind of algorithm should run in log (N) time.

Hidde
  • 11,493
  • 8
  • 43
  • 68
1

Kind of depends on how accurate you want it. Consider that the square root of 2^32 == 2^16. So one thing you could do is shift the 1000-bit number 500 bits to the right, and you have an answer that would be in the ballpark.

How well does this work? Let's see. The number 36 in binary is 100100. If I shift that to the right 3 bits, then I get 4. Hmmm ... should be 6. Pretty big error of 33%. The square root of 1,000,000 is 1,000. In binary, 1,000,000 is 1111 0100 0010 0100 0000. That's 20 bits. Shifted right 10 bits, it's 1111 0100 00, or 976. The error is 24/1000, or 2.4%.

When you get to a 1,000 bit number, the absolute error might be large, but the percentage error is going to be very small.

Depending on how you're storing the numbers, shifting a 1,000 bit number 500 bits to the right shouldn't be terribly difficult.

Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
  • It seems like a good guess start : ) Then just compare and increment/decrement in loop... now time to find out 500+ bit multiplication way : ) – Prolatser Apr 06 '14 at 14:45
0

Newton's method is probably the way to go. At some point with Newton's method you're going to have to perform a division (in particular, when finding the next point to test), but it might be okay to approximate this to the nearest power of two and just do a bitshift instead.

Clinton
  • 22,361
  • 15
  • 67
  • 163