在没有外部库的情况下,如何在C++中将一个数字(std::string类型)转换为std::vector中的二进制表示< bool>?

aurhwmvo  于 2023-04-01  发布在  其他
关注(0)|答案(1)|浏览(108)

我试图将一个字符串(如“12345”)转换为布尔向量中的二进制表示(因此它将是{1,1,0,0,0,0,0,0,1,1,1,0,0,1},但目前的尝试仅适用于“0”到“9”的字符串输入。对于“10”到“19”,它关闭了2(例如:10应该是1,0,1,0,但我得到的是1,0,0,0),对于“20”到“29”,它的值多减2(例如:20应该是1,0,1,0,0,我得到1,0,0,0,0)。
这是我目前的尝试,但我愿意完全重新设计。我希望这是一个简单的修复(感觉应该很容易,就像......每10个增加2个?)但有一个警告,这一直在破坏一切:
我不能将字符串输入转换为int或long long,因为字符串将包含一个对于内置类型来说太大的数字(它将有数千位数字),并且我试图在没有任何外部库(如boost)的情况下做到这一点。

std::vector<bool> stringToBinary(std::string num) {
        std::vector<bool> bin;
        int n = ceil(log2(pow(10, num.size())));
        for (int i = 0; i < num.size(); i++) {
            int x = num[i] - '0';
            std::vector<bool> bits;
            while (x > 0) {
                bits.push_back(x % 2);
                x /= 2;
            }
            std::reverse(bits.begin(), bits.end());
            int m = bits.size();
            for (int j = 0; j < n - 4 * i - m; j++) {
                bin.push_back(false);
            }
            for (int j = 0; j < m; j++) {
                bin.push_back(bits[j]);
            }
        }
        while (bin.size() > 1 && bin.front() == false) {
            bin.erase(bin.begin());
        }
        return bin;
    }

先谢谢你了!

hi3rlvi2

hi3rlvi21#

既然你要求在C中完成这个,我假设你可以使用C库。在这种情况下,你可以做以下事情:

#include <iostream>
#include <string>
#include <bitset>

int main()
{
    std::string strNumber = "20";
    int number = atoi(strNumber.c_str());
    std::string s = std::bitset< 64 >(number).to_string(); // string conversion
    std::cout<< s << std::endl;
    
    return 0;
}

您应该很容易将最后一个std::string转换为std::vector
好吧,在你的评论中提供的信息,这里是一个修订版本,你应该能够得到任何整数的二进制表示:

#include <iostream>
#include <string>
#include <bitset>
#include <vector>

// Multiplies str1 and str2, and prints result.
std::string multiply(std::string num1, std::string num2)
{
    int len1 = num1.size();
    int len2 = num2.size();
    if (len1 == 0 || len2 == 0)
    return "0";
 
    // will keep the result number in vector
    // in reverse order
    std::vector<int> result(len1 + len2, 0);
 
    // Below two indexes are used to find positions
    // in result.
    int i_n1 = 0;
    int i_n2 = 0;
     
    // Go from right to left in num1
    for (int i=len1-1; i>=0; i--)
    {
        int carry = 0;
        int n1 = num1[i] - '0';
 
        // To shift position to left after every
        // multiplication of a digit in num2
        i_n2 = 0;
         
        // Go from right to left in num2            
        for (int j=len2-1; j>=0; j--)
        {
            // Take current digit of second number
            int n2 = num2[j] - '0';
 
            // Multiply with current digit of first number
            // and add result to previously stored result
            // at current position.
            int sum = n1*n2 + result[i_n1 + i_n2] + carry;
 
            // Carry for next iteration
            carry = sum/10;
 
            // Store result
            result[i_n1 + i_n2] = sum % 10;
 
            i_n2++;
        }
 
        // store carry in next cell
        if (carry > 0)
            result[i_n1 + i_n2] += carry;
 
        // To shift position to left after every
        // multiplication of a digit in num1.
        i_n1++;
    }
 
    // ignore '0's from the right
    int i = result.size() - 1;
    while (i>=0 && result[i] == 0)
    i--;
 
    // If all were '0's - means either both or
    // one of num1 or num2 were '0'
    if (i == -1)
    return "0";
 
    // generate the result string
    std::string s = "";
     
    while (i >= 0)
        s += std::to_string(result[i--]);
 
    return s;
}

// A function to perform division of large numbers
std::string longDivision(std::string number, int divisor)
{
    // As result can be very large store it in string
    std::string ans;
 
    // Find prefix of number that is larger
    // than divisor.
    int idx = 0;
    int temp = number[idx] - '0';
    while (temp < divisor)
        temp = temp * 10 + (number[++idx] - '0');
 
    // Repeatedly divide divisor with temp. After
    // every division, update temp to include one
    // more digit.
    while (number.size() > idx) {
        // Store result in answer i.e. temp / divisor
        ans += (temp / divisor) + '0';
 
        // Take next digit of number
        temp = (temp % divisor) * 10 + number[++idx] - '0';
    }
 
    // If divisor is greater than number
    if (ans.length() == 0)
        return "0";
 
    // else return ans
    return ans;
}

int main()
{
    std::string strNumber = "174981883239023362650696299580"; //
    std::vector<bool> boolean;
    while (strNumber.size() > 0 && strNumber[0] != '0')
    {
        std::string temp = longDivision(strNumber, 2);
        if (multiply(temp, "2") == strNumber)    // if this is tre there was no reminder on the division
            {boolean.push_back(0); std::cout << "0";}
        else 
            {boolean.push_back(1);std::cout << "1";}
        strNumber = temp;
    }
    std::cout<< std::endl;
    
    std::cout << "The number you are after: "; 
    for (int i = boolean.size()-1; i >= 0; i--)
    {
        std::cout << (int)boolean[i];
    }
    std::cout<< std::endl;
    
    return 0;
}

以下是我从中找到有用信息的一些参考资料:
How to convert a string that represents a decimal number to a string that represents its binary form?
https://www.geeksforgeeks.org/divide-large-number-represented-string/
https://www.geeksforgeeks.org/multiply-large-numbers-represented-as-strings/

相关问题