如何将十进制字符串转换为二进制字符串?

时间:2014-04-09 16:47:28

标签: c++ algorithm binary

我有一个像这样的小数字符串(长度<5000):

std::string decimalString = "555";

是否有将此字符串转换为二进制表示的标准方法?像这样:

std::string binaryString = "1000101011";

更新。

This post帮助我。

4 个答案:

答案 0 :(得分:2)

由于10不是2的力量(或反过来),你运气不好。你必须在base-10中实现算术。您需要以下两个操作:

  1. 整数除以2
  2. 检查除以2后的余数
  3. 两者都可以计算by the same algorithm。 或者,您可以使用C ++的各种大整数库之一,例如GNU MPBoost.Multiprecision

答案 1 :(得分:2)

由于数字非常大,你可以使用一个大的整数库(可能是?),或者自己编写必要的函数。

如果你决定自己实现这些功能,一种方法是在你的代码中实现旧的铅笔纸长分割方法,你需要在2重复划分十进制数并累积另一个字符串中的剩余部分。可能有点麻烦,但除以2应该不会那么难。

答案 2 :(得分:1)

我试图这样做..我不认为我的答案是正确的,但这是我想要做的事情背后的IDEA ..

假设我们有2位小数:

100和200 ..

要连接这些,我们可以使用公式:

a * CalcPower(b) + b其中CalcPower定义如下..

知道了这一点,我试图将非常长的十进制字符串拆分为4个块。我将每个字符串转换为二进制并将它们存储在一个向量中。

最后,我遍历每个字符串并应用上面的公式将每个二进制字符串连接成一个巨大的字符串..

我没有得到它的工作,但这里是代码..也许别人看到我出错的地方.. BinaryAddBinaryMulDecCalcPower完全正常。问题实际上在ToBinary

#include <iostream>
#include <bitset>
#include <limits>
#include <algorithm>

std::string BinaryAdd(std::string First, std::string Second)
{
    int Carry = 0;
    std::string Result;

    while(Second.size() > First.size())
        First.insert(0, "0");

    while(First.size() > Second.size())
        Second.insert(0, "0");

    for (int I = First.size() - 1; I >= 0; --I)
    {
        int FirstBit = First[I] - 0x30;
        int SecondBit = Second[I] - 0x30;
        Result += static_cast<char>((FirstBit ^ SecondBit ^ Carry) + 0x30);
        Carry = (FirstBit & SecondBit) | (SecondBit & Carry) | (FirstBit & Carry);
    }

    if (Carry)
        Result += 0x31;

    std::reverse(Result.begin(), Result.end());
    return Result;
}

std::string BinaryMulDec(std::string value, int amount)
{
    if (amount == 0)
    {
        for (auto &s : value)
        {
            s = 0x30;
        }
        return value;
    }

    std::string result = value;
    for (int I = 0; I < amount - 1; ++I)
        result = BinaryAdd(result, value);

    return result;
}

std::int64_t CalcPowers(std::int64_t value)
{
    std::int64_t t = 1;
    while(t < value)
        t *= 10;

    return t;
}

std::string ToBinary(const std::string &value)
{
    std::vector<std::string> sets;
    std::vector<int> multipliers;

    int Len = 0;
    int Rem = value.size() % 4;

    for (auto it = value.end(), jt = value.end(); it != value.begin() - 1; --it)
    {
        if (Len++ == 4)
        {
            std::string t = std::string(it, jt);
            sets.push_back(std::bitset<16>(std::stoull(t)).to_string());
            multipliers.push_back(CalcPowers(std::stoull(t)));
            jt = it;
            Len = 1;
        }
    }

    if (Rem != 0 && Rem != value.size())
    {
        sets.push_back(std::bitset<16>(std::stoull(std::string(value.begin(), value.begin() + Rem))).to_string());
    }

    auto formula = [](std::string a, std::string b, int mul) -> std::string
    {
        return BinaryAdd(BinaryMulDec(a, mul), b);
    };

    std::reverse(sets.begin(), sets.end());
    std::reverse(multipliers.begin(), multipliers.end());
    std::string result = sets[0];

    for (std::size_t i = 1; i < sets.size(); ++i)
    {
        result = formula(result, sets[i], multipliers[i]);
    }

    return result;
}

void ConcatenateDecimals(std::int64_t* arr, int size)
{
    auto formula = [](std::int64_t a, std::int64_t b) -> std::int64_t
    {
        return (a * CalcPowers(b)) + b;
    };

    std::int64_t val = arr[0];

    for (int i = 1; i < size; ++i)
    {
        val = formula(val, arr[i]);
    }

    std::cout<<val;
}

int main()
{
    std::string decimal = "64497387062899840145";
    //6449738706289984014 = 0101100110000010000100110010111001100010100000001000001000001110

    /*
    std::int64_t arr[] = {644, 9738, 7062, 8998, 4014};
    ConcatenateDecimals(arr, 5);*/

    std::cout<<ToBinary(decimal);

    return 0;
}

答案 3 :(得分:1)

我找到了解决运动编程任务的旧代码:

  

ai - &gt; AJ

     

2&lt; = i,j&lt; = 36; 0 <= a <= 10 ^ 1000

     

时间限制:1秒

在最坏的情况下,执行时间约为0,039。由于使用10 ^ 9作为计算系统,乘法,加法和除法算法非常快,但我认为实现可以很好地优化。

source link

#include <iostream>
#include <string>
#include <vector>
using namespace std;

#define sz(x) (int((x).size()))
typedef vector<int> vi;
typedef long long llong;

int DigToNumber(char c) {
   if( c <= '9' && c >= '0' )
      return c-'0';
   return c-'A'+10;
}

char NumberToDig(int n) {
   if( n < 10 )
      return '0'+n;
   return n-10+'A';
}

const int base = 1000*1000*1000;

void mulint(vi& a, int b) { //a*= b
   for(int i = 0, carry = 0; i < sz(a) || carry; i++) {
      if( i == sz(a) )
         a.push_back(0);
      llong cur = carry + a[i] * 1LL * b;
      a[i] = int(cur%base);
      carry = int(cur/base);
   }
   while( sz(a) > 1 && a.back() == 0 )
      a.pop_back();
}

int divint(vi& a, int d) { // carry = a%d; a /= d; return carry;
   int carry = 0;
   for(int i = sz(a)-1; i >= 0; i--) {
      llong cur = a[i] + carry * 1LL * base;
      a[i] = int(cur/d);
      carry = int(cur%d);
   }
   while( sz(a) > 1 && a.back() == 0 )
      a.pop_back();
   return carry;
}

void add(vi& a, vi& b) { // a += b
   for(int i = 0, c = 0, l = max(sz(a),sz(b)); i < l || c; i++) {
      if( i == sz(a) )
         a.push_back(0);
      a[i] += ((i<sz(b))?b[i]:0) + c;
      c = a[i] >= base;
      if( c ) a[i] -= base;
   }
}

int main() {

   ios_base::sync_with_stdio(0);
   cin.tie(0);

   int from, to; cin >> from >> to;
   string s; cin >> s;
   vi res(1,0); vi m(1,1); vi tmp;
   for(int i = sz(s)-1; i >= 0; i--) {
      tmp.assign(m.begin(), m.end());
      mulint(tmp,DigToNumber(s[i]));
      add(res,tmp); mulint(m,from);
   }
   vi ans;
   while( sz(res) > 1 || res.back() != 0 )
      ans.push_back(divint(res,to));
   if( sz(ans) == 0 )
      ans.push_back(0);
   for(int i = sz(ans)-1; i >= 0; i--)
      cout << NumberToDig(ans[i]);
   cout << "\n";

   return 0;
}

“from - &gt; to”如何适用于字符串“s”:

  1. 使用s [i] *从^(| s | -i-1)累积大数(向量&lt; int&gt;)“res”,i = | s | -1..0
  2. 通过将“res”除以“to”直到res&gt;来计算数字。 0并将它们保存到另一个向量
  3. 将其逐位输出(您可以使用ostringstream)
  4. PS我已经注意到线程启动器的昵称是Denis。我认为link也可能有用。

相关问题