4

A shell of the desired code:

#include <iostream>
#include <string>

std::string str_to_bin(const std::string& str)
{
    //...
}

int main()
{
    std::string str = "123";

    std::cout << str_to_bin(str); //would print 1111011
}

Question title says it all. I've been stuck on this for a while. Is there a solution for this in the STL? Or something simple that I'm missing? If not, how would I go about doing this? Maybe a direction you could point me to? Also, speed is of great importance.

EDIT: The number can be of any size (larger than long long as well), so std::stoi and std::bitset<> are off the table.

DeiDei
  • 10,205
  • 6
  • 55
  • 80
  • Tried this : http://stackoverflow.com/questions/10184178/fastest-way-to-convert-string-to-binary ? – loxxy Dec 20 '15 at 12:31
  • You need multiple precision arithmetic for this: https://en.wikipedia.org/wiki/List_of_C%2B%2B_multiple_precision_arithmetic_libraries –  Dec 20 '15 at 12:56
  • Use `boost::dynamic_bitset` then if size is a problem. – edmz Dec 20 '15 at 13:23

2 Answers2

3

You can do it using GMP (GNU Multi-Precision). Something like this:

#include <gmpxx.h>

std::string str_to_bin(const std::string& str)
{
    mpz_class bignum;
    int rc = bignum.set_str(str, 10);
    if (rc != 0)
        throw std::invalid_argument("bad number: " + str);

    return bignum.get_str(2);
}

Or using the traditional C API:

#include <gmp.h>

std::string str_to_bin(const std::string& str)
{
  mpz_t bignum;
  int rc = mpz_set_str(bignum, str.c_str(), 10);
  if (rc != 0)
    throw std::invalid_argument("bad number: " + str);

  char* rawstr = mpz_get_str(nullptr, 2, bignum);
  std::string result(rawstr);
  free(rawstr);
  return result;
}
John Zwinck
  • 239,568
  • 38
  • 324
  • 436
0

Okay let's break down the process you require here. (only one of an infinite number of ways to do this)

  1. Conversion of a number represented as a string type into an integer type.
  2. Conversion of the intermediary integer type into a binary number which is held in another string type. (judging by the return type of your function, which could just as easily return an integer by the way and save the headache of representing the binary equivalent as a string)

For step 1:

Use the standard library function stoi(). It does what you might imagine, extracts the numerical data from the string and stores it in an integer.

std::string numberstr = "123";
int numberint = std::stoi(numberstr);
std::cout << numberint << "\n";

Now you have the number as an integer.

For step 2:

  1. This process involves the conversion of a number from base 10 (decimal) to base 2 (binary).
  2. Divide the number by 2.
  3. Store the remainder and the quotient of this division operation for further use.
  4. The remainder becomes part of the binary representation, while the quotient is used as the next dividend.
  5. This process repeats until the dividend becomes 1, at which point it too is included in the binary representation.
  6. Reverse the string, and voila! You now have the binary representation of a number.

  7. If you want to handle negative numbers (which I imagine you might), simply perform a check before the conversion to see if the converted integer is negative, and set a flag to true if it is.

  8. Check this flag before reversing, and add a negative sign to end of the string before reversing.

The final function looks like this:

std::string str_to_bin(const std::string& str)
{
    std::string binarystr = ""; // Output string

    int remainder;
    int numberint = std::stoi(str);
    bool flagnegative = false;
    // If negative number, beginning of binary equivalent is 1
    if (numberint < 0)
    {
        numberint = abs(numberint);
        flagnegative = true;
    }
    // If number is 0, don't perform conversion simply return 0
    if (numberint == 0)
    {
        binarystr = "0";
        return binarystr;
    }
    std::cout << numberint << "\n";

    while (numberint != 1)
    {
        remainder = numberint % 2;
        numberint /= 2;
        std::ostringstream convert; // stream used for the conversion
        convert << remainder;      // insert the textual representation of 'remainder' in the characters in the stream
        binarystr += convert.str();
    }
    std::ostringstream final;
    final << numberint;         // To insert the last (or rather first once reversed) binary number
    binarystr += final.str();
    if (flagnegative == true)
        binarystr += "-";
    std::reverse(binarystr.begin(), binarystr.end());
    return binarystr;
}

Other people have posted the STL method using bitset, which might be of value to you, but I believe there's no fun in simply copy pasting a function found online.

This way, you understand exactly whats going on under the hood! However I cannot provide a guarantee for speed, especially since this is using streams. Bit operations would definitely be more efficient.

Anywho, hope this helps! I had quite a bit of fun writing this.

Varaquilex
  • 3,447
  • 7
  • 40
  • 60
Sai Narayan
  • 300
  • 4
  • 15
  • Okay, this was posted before the edit. This solution would indeed not work with variables beyond a certain size (I believe). – Sai Narayan Dec 20 '15 at 13:24