views:

393

answers:

4

Hi I have a problem converting a string binary to a decimal

I was using bitset

bitstring ="1011010001111111";

unsigned long binToDec( string bitstring){
    bitset<32> dec (bitstring);
    return dec.to_ulong();
}

All of this works fine, but !! the problem comes when i try to do the same with a bits string with more of 32 bits. I know that bitset only does the conversion with 4 bytes, but i need to do the conversion with strings that has 48 or 56 bits (sometimes i need to get 14 or 15 digits )

string bitstring;
bitstring ="11100101001001000000100000100100110100110011010001111111";
i want to get this number: 64497387062899840

Any sugestion? anybody have a function to transform a binary string to decimal ?

Note: i can´t use boost because it´s not ported to the iphone.

Thanks for your help

+1  A: 

The simplest answer would be to chop your string in half, convert it to a pair of 32bit ints and then pack them together.

+1  A: 

This should do the trick, but is untested.

unsigned long binToDec(const std::string& s)
{
  unsigned long d = 0;
  for (int i = 0; i < s.size(); ++i)
  {
    d <<= 1;
    if (s[i] == '1')
      ++d;
  }
  return d;
}
Peter Alexander
That's what I would do too, no need to involve bitset here especially given it cant do the whole job.
John Dibling
This won't work due to overflow issues.
dirkgently
How so, dirkgently?
Peter Alexander
1) it starts with d == 0, the result of shift is 0 until you find 1 in the string, 2) you go from front to back should be from back to front e.g. 0010 should be 2, in your code it will be 1 I believe. Can you show output of the example number from the question?
stefanB
Under VC++ (either x86 or amd64), unsigned long is 32 bits. You'd need to use unsigned long long.
Peter
@Poita_ - since you use an unsigned long, this does not improve on `std::bitset<>`
R Samuel Klatchko
+1  A: 

You are probably hitting overflow whenever you cross ULONG_MAX. Use a bigger data type such as unsigned long long. However, if your number can be larger than the max this type can hold, you are probably looking at having to implement a bignum library.

Following cube's suggestion, vanilla C code:

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h> 

uint64_t binToDec(const char * s){
        uint64_t res = 0; size_t i, n;
        for (i = 0, n = strlen(s) - 1; i < n; ++i) {
                 res = (res | (unsigned int)(s[ i ] - '0')) << 1;
        }
        return res;
}

int main() {
   /* Note the special C99 format specifier macros defined in <inttypes.h> */
   printf("%"PRIu64"\n", 
     binToDec("11100101001001000000100000100100110100110011010001111111"));
}

Note: ISO C++ does not support long long.

dirkgently
maybe even better than using `unsigned long long` is to include `<cstdint>` and use `uint64_t`
cube
+1  A: 

I've just put together this and it seems to work with your example, I haven't tested any bigger values, compared result with calculator.

Outputs:

64497387062899839

Code:

#include <iostream>
#include <limits>

using namespace std;

unsigned long long convert(string& bits)
{
    if (bits.length() > (size_t)numeric_limits<unsigned long long>::digits)
        return 0;

    unsigned long long sum = 0;
    unsigned long long shift = 1;
    for (string::reverse_iterator it(bits.rbegin()), end(bits.rend());
         it < end; ++it)
    {
        if (*it == '1') sum += shift;
        shift = (shift << 1);
    }

    return sum;
}

int main()
{
    string bits("11100101001001000000100000100100110100110011010001111111");
    cout << "returned: " << convert(bits) << endl;
}
stefanB
I can't figure out why is it community wiki ...
stefanB
@stefanB - the "[made Community Wiki]" is on your original post, so either you accidentally clicked on the checkbox or yours was the 20th? 30th? (I can't remember the number) answer. The latter doesn't apply, so I can *only* assume the latter. I have no button to "un-wiki".
Marc Gravell