4

The most common way is to get the power of 2 for each non-zero position of the binary number, and then sum them up. This is not workable when the binary number is huge, say,

10000...0001 //1000000 positions

It is impossible to let the computer compute the pow(2,1000000). So the traditional way is not workable.

Other way to do this?

Could someone give an arithmetic method about how to compute, not library?

Buzz
  • 1,549
  • 3
  • 16
  • 31

6 Answers6

3

As happydave said, there are existing libraries (such as GMP) for this type of thing. If you need to roll your own for some reason, here's an outline of a reasonably efficient approach. You'll need bigint subtraction, comparison and multiplication.

Cache values of 10^(2^n) in your binary format until the next value is bigger than your binary number. This will allow you to quickly generate a power of ten by doing the following:

Select the largest value in your cache smaller than your remaining number, store this
in a working variable.
do{
  Multiply it by the next largest value in your cache and store the result in a
  temporary value.
  If the new value is still smaller, set your working value to this number (swapping 
  references here rather than allocating new memory is a good idea),
  Keep a counter to see which digit you're at. If this changes by more than one
  between instances of the outer loop, you need to pad with zeros
} Until you run out of cache
This is your next base ten value in binary, subtract it from your binary number while
the binary number is larger than your digit, the number of times you do this is the 
decimal digit -- you can cheat a little here by comparing the most significant bits
and finding a lower bound before trying subtraction.
Repeat until your binary number is 0

This is roughly O(n^4) with regards to number of binary digits, and O(nlog(n)) with regards to memory. You can get that n^4 closer to n^3 by using a more sophisticated multiplication algorithm.

1

You could write your own class for handling arbitrarily large integers (which you can represent as an array of integers, or whatever makes the most sense), and implement the operations (*, pow, etc.) yourself. Or you could google "C++ big integer library", and find someone else who has already implemented it.

happydave
  • 7,127
  • 1
  • 26
  • 25
1

It is impossible to let the computer compute the pow(2,1000000). So the traditional way is not workable.

It is not impossible. For example, Python can do the arithmetic calculation instantly, and the conversion to a decimal number in about two seconds (on my machine). Python has built in facilities for dealing with large integers that exceed the size of a machine word.

In C++ (and C), a good choice of big integer library is GMP. It is robust, well tested, and actively maintained. It includes a C++ wrapper that uses operator overloading to provide a nice interface (except, there is no C++ operator for the pow() operation).

Here is a C++ example that uses GMP:

#include <iostream>
#include <gmpxx.h>

int main(int, char *[])
{
    mpz_class a, b;
    a = 2;
    mpz_pow_ui(b.get_mpz_t(), a.get_mpz_t(), 1000000);
    std::string s = b.get_str();
    std::cout << "length is " << s.length() << std::endl;
    return 0;
}

The output of the above is

length is 301030

which executes on my machine in 0.18 seconds.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
1

"This is roughly O(n^4) with regards to number of binary digits, and O(nlog(n)) with regards to memory". You can do O(n^(2 + epsilon)) operations (where n is the number of binary digits), and O(n) memory as follows: Let N be an enormous number of binary length n. Compute the residues mod 2 (easy; grab the low bit) and mod 5 (not easy but not terrible; break the binary string into successive strings of four bits; compute the residue mod 5 of each such 4-tuple, and add them up as with casting out 9's for decimal numbers.). By computing the residues mod 2 and 5 you can read off the low decimal digit. Subtract this; divide by 10 (the internet documents ways to do this), and repeat to get the next-lowest digit.

0

I calculated 2 ** 1000000 and converted it to decimal in 9.3 seconds in Smalltalk so it's not impossible. Smalltalk has large integer libraries built in.

2 raisedToInteger: 1000000

As mentioned in another answer, you need a library that handles arbitrary precision integer numbers. Once you have that, you do MOD 10 and DIV 10 operations on it to compute the decimal digits in reverse order (least significant to most significant).

The rough idea is something like this:

LargeInteger *a;
char *string;


while (a != 0) {
    int remainder;
    LargeInteger *quotient;

    remainder = a % 10.
    *string++ = remainder + 48.
    quotient = a / 10.
    } 

Many details are missing (or wrong) here concerning type conversions, memory management and allocation of objects but it's meant to demonstrate the general technique.

David Buck
  • 2,847
  • 15
  • 16
0

It's quite simple with the Gnu Multiprecision Library. Unfortunately, I couldn't test this program because it seems I need to rebuild my library after a compiler upgrade. But there's not much room for error!

#include "gmpxx.h"
#include <iostream>

int main() {
    mpz_class megabit( "1", 10 );
    megabit <<= 1000000;
    megabit += 1;
    std::cout << megabit << '\n';
}
Potatoswatter
  • 134,909
  • 25
  • 265
  • 421