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

How to convert a decimal string to binary string?

本文关键字:字符串 转换 二进制 十进制      更新时间:2023-10-16

我有一个像这样的十进制字符串(长度<5000):

std::string decimalString = "555";

有没有一种标准的方法可以将这个字符串转换为二进制表示?像这样:

std::string binaryString = "1000101011";

更新

这篇文章帮助了我。

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

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

由于10不是2的幂(或相反),所以你运气不好。你必须用10进制来实现算术运算。您需要以下两种操作:

  1. 整数除以2
  2. 检查除以2后的余数

两者都可以通过相同的算法进行计算。或者,您可以使用C++的各种大整数库之一,如GNU MP或Boost.Multiprecision.

我试过了。。我认为我的答案不对,但这是我试图做的事情背后的想法。。

假设我们有两个小数:

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;
}

我找到了解决体育编程任务的旧代码:

ai->aj

2<=i、 j<=36;0<=a<=10^1000

时限:1秒

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

源链路

#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;
}

如何"从->至";为字符串"工作";s":

  1. 累加大数(vector<int>)"res";其中s[i]*来自^(|s|-i-1),i=|s|-1..0
  2. 通过除以"0"来计算数字;res";通过";至";直到res>0并将其保存到另一个矢量
  3. 将其逐位发送到输出(您可以使用ostringstream)

PS我注意到线程启动器的昵称是Denis。我认为这个链接可能也很有用。