Отображение 1024-битного двоичного числа в базе 10 с ++ - PullRequest
1 голос
/ 28 мая 2020

Я постараюсь объяснить мою проблему как можно лучше. Для начала вот мой код для написанной мной программы, которая генерирует массив длиной n, где каждый элемент имеет значение 1 или 0. Следующий метод принимает массив, созданный из первого метода, и форматирует его в двоичное число. которые можно вывести на консоль.

#include "bigNum.h"
#include <iostream>
#include <cstdlib>

short* genArr(int bits)
{
        static short *numArr = new short[bits];
        srand(time(0));
        int i;
        for (i = 0; i<bits; i++) {
                numArr[i] = rand() % 2;
        }
        return numArr;
}

void formatNum(short arr[], int size) {
        int i;
        for (i = 0; i<size; ++i) {
                std::cout<<arr[i];
        }
        std::cout<<"\n";
}

Основная причина, по которой я создал эту программу, заключается в генерации больших случайных чисел порядка 1024 бит и выше. Я не думаю, что простое преобразование двоичного кода в int будет работать, потому что размер моего двоичного числа непостоянен и явно может быть больше 64 бит.

Например, если я генерирую 1024-битный двоичный номер, он выводит на консоль:

./test 1024
00100110110011111111000111011111001001010001110111011001100010110010110010111000101101011011000100101101110110110100001000110100110110000011010000000101110110101010011010                     01101111010001000100100100011001111110010110011101101110111011111100101110000110000011001110101011010101101110000001000111101101000010011100000010010000110001111111010110                         11101001111110011100000110111010100001010101010101101110101000111101001011110000100010010111100000000110001100110011010000100000001110100011000000001010000100111000010111                         00000000101001000100010001100000000101111011001011011111001001011000111001101000011100000100101001001001101001000110110110100101011111001100100110001010100111000111101011                         00110010000111111101101010000011000001001110010100111010001000101111010001010000111011011101011110010010001000111011100010110101110110010100110111011011110101010011011001                         10011101001010111101000100011100101011101000110000001001000110100001011101010010011111001011011010011111110110011111011100001011010101110111111100001111100101000010000001 

РЕДАКТИРОВАТЬ: извините, я не могу удалить длинные вкладки. Я думаю, это произошло из-за ошибки форматирования копирования / вставки.

Я хочу преобразовать это длинное двоичное число в строку, отображающую его представление по основанию 10. Мне не удалось найти подобных проблем в Интернете, поэтому я решил задать здесь вопрос. Надеюсь, я подробно описал свою проблему.

1 Ответ

2 голосов
/ 28 мая 2020

Вам понадобится поддержка из большой целочисленной библиотеки. Но только крошечная его часть. Такая маленькая часть, что мы можем реализовать ее вместе.

Во-первых, давайте немного изменим ваш код, чтобы сделать его управляемым:

#include <iostream>
#include <cstdlib>
#include <vector>

std::vector<short> genArr(int bits)
{
    std::vector<short> numArr(bits);
    srand(time(0));
    int i;
    for (i = 0; i<bits; i++) 
    {
        numArr[i] = rand() % 2;
    }
    return numArr;
}

void formatNum(std::vector<short> arr)
{
    int i;
    for (i = 0; i<arr.size(); ++i) 
    {
        std::cout<<arr[i];
    }
    std::cout<<"\n";
}

Практически то же самое, что и раньше, только используя векторы . Затем вы можете просто реализовать очень высокоуровневый logi c, предполагая, что у вас есть большая библиотека int:

void formatNumDec(std::vector<short> arr)
{
    LargeNum n;
    for(int i = 0; i < arr.size(); i++)
    {
        n = n * 2;
        if (arr[i])
        {
            ++n;
        }
    }
    std::cout << n << std::endl;
}

Все, что мы сделали: для каждого di git умножаем текущее значение на 2 , затем добавьте ноль или единицу, в зависимости от следующего бита.

Мы полагались на:

  • оператор присваивания
  • оператор увеличения
  • оператор звездочки (для умножения)

Давайте использовать это:

class LargeNum
{
public:
    int base;
    std::vector<int> digits;

мы получаем оператор присваивания по умолчанию. Давайте добавим конструктор:

    LargeNum():base(10) {}

Давайте реализуем инкремент, добавив единицу к последнему di git и перенеся его. Это работает только для небольшого значения, но 1 - это небольшое значение.

    LargeNum& operator++()
    {
        int pos = 0;
        bool carry = false;
        do
        {
            carry = false;
            if (pos >= digits.size())
            {
                digits.push_back(0);
            }
            digits[pos]++;
            if (digits[pos] == base)
            {
                digits[pos] = 0;
                carry = true;
            }
        }
        while(carry);

        return *this;
    }

И последний бит, который нам нужен, это умножение на 2. Давайте реализуем умножение на любое маленькое значение (скажем, от 1 до 10) на умножение каждого di git и перенос:

    LargeNum& operator*(int mult)
    {
        int carry = 0;
        for(int pos = 0; pos < digits.size(); pos++)
        {
            digits[pos] = digits[pos] * mult + carry;
            carry = digits[pos] / 10;
            digits[pos] %= 10;
        }
        if (carry)
        {
            digits.push_back(carry);
        }

        return *this;
    }
};

Это дает нам решение с использованием большой целочисленной библиотеки, которая работает в очень ограниченных случаях. Но достаточно для вашего случая использования. Если протестировать:

int main()
{
    auto num = genArr(13);
    formatNum(num);
    formatNumDec(num);
}

, мы получим:

1100011100011
6371(10)

или, с большими значениями:

1101110010011010101101000111001011011010010001110000101101011000011111001011010101011111001010111011111001110100110110111101000101001111000000110000000111111000010110101100110100111001101101101111010011001100111011001101110000100010110010010101111100101110000101000110111101000101001100001110001010111110101001111101111100010110011111111111010100010110000010001000001001000010111010101100111000001000000100101010111111110100110101001111101100000100001000010011111011011100111101011011111000001111001001011011010111101101000101000101100111001000111100010001001010101110101001110001110000011101000001010010001110011110100000011111100011001010111111101010100011010000011100100110001001111110010011110001011111101111001010000000101000010100010000110101000111100001001111011110111111000100100010000011111000001111110001111011011000100101111101111111100011111001101100001011100111111011011010111111001100001110011100101001101011111011101000110001110010000010010111110101001111111111100010000110011111010010011
73868569780955456124228707899822160955495544892638015310179220061186136753214543146234756723216826639708631800432713243173835264416984333326210886331495933792989604726456910722925688428304932474264611559781633323648147423739204040611247483503242836728251464923462071095422092950093094774327508960755347(10)

Я не беспокоился, в каком направлении (из наименьший или наибольший di git, который вы обрабатывали в своем двоичном файле. Отрегулируйте его соответствующим образом).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...