Циклический сдвиг влево на указанное количество бит: проблема с граничными значениями

Мне необходимо реализовать циклический побитовый сдвиг влево, с маленькими числами все отлично работает, но когда ввожу максимальное число для 64бит (9223372036854775807) то мне выдается другое число. Проблема именно в том, что когда я ввожу это максимальное число и сдвигаю на 64 бит (по кругу то есть), код новое число переводит из двоичной в десятичной неправильно

#include <iostream>
#include <sstream>
using namespace std;
 
 
//Преобразуем число в массив символов, которые представляют число в двоичном виде
void NumToChars(long long num, char num2[], int arr_size) {
    long long one = 1;
    for (int i = arr_size - 1; i >= 0; i--) {
        if (num & (one << i)) {//сдвигаем биты
            num2[arr_size - 1 - i] = '1';
        }
        else {
            num2[arr_size - 1 - i] = '0';
        }
    }
}
//создаем строку из двоичного представления числа, добавляя пробелы для удобства
string CharsToString(char num2[], int arr_size) {
    string s = "";
    for (int i = 0; i < arr_size; i++) {
        s += num2[i];
        if ((i + 1) % 8 == 0)s += " ";
    }return s;
}
//Меням биты в двоичном представлении числа
long long ShiftBits(unsigned long long num, int shift) {
    unsigned long long res = (num << shift) | (num >> (64 - shift));
    return res;
}
//преобразуем двоичное представление в десятиричное число
long long CharsToLongLong(char arr[], int arr_size) {
    long long res = 0;
    int deg;
    for (int i = arr_size - 1; i >= 0; i--) {
        if (arr[i] == '1') {
            deg = arr_size - 1 - i;
            res += pow(2, deg);
        }
    }return res;
}
 
 
int main(int argc, char* argv[]) {
    setlocale(LC_ALL, "ru");
 
    //Если количество аргументов указано верно
    if (argc == 3) {
        unsigned long long num;
        int shift;
        bool correct[2] = { true,true };
        //Создаем из массива символов потоки строк
        stringstream convert[2];
        for (int i = 0; i < 2; i++) {
            convert[i].str(argv[i + 1]);
        }
        //Конвертируем значения
        //конвертируем исходное число
        if (!(convert[0] >> num)) // выполняем конвертацию
            correct[0] = false; // если конвертация терпит неудачу, то отмечаем это
 
        //конвертируем число для сдвига
        if (!(convert[1] >> shift)) // выполняем конвертацию
            correct[1] = false; // если конвертация терпит неудачу, то отмечаем это
 
        //Если конвертация прошла успешно
        if (correct[0] && correct[1]) {
 
            //Если позиция указана верно
            if (shift > 0) {
                //Перевод в двоичный вид
                char input[64];
                NumToChars(num, input, 64);
                cout << "Исходное число в десятиричном виде: " << endl << num << endl;
                cout << "Исходное число в двоичном виде: " << endl << CharsToString(input, 64) << endl;
                //сдвиг
                cout << "Сдвиг влево на число бит: " << shift << endl;
                char res[64];
                unsigned long long r = ShiftBits(num, shift);
                NumToChars(r, res, 64);
                cout << "Результат сдвига:" << endl << CharsToString(res, 64) << endl;
                //перевод из двоичного в лонг лонг
                unsigned long long new_num = CharsToLongLong(res, 64);
                cout << "Получившееся число: " << endl << new_num << endl;
            }
            else { cout << "Число сдвига должно быть больше 0" << endl; }
        }
        //Если конвертация прошла неуспешно
        else {
            cout << "Не получилось преобразовать следующие числа:" << endl;
            if (!correct[0]) { cout << "Исходное число - " << argv[1] << endl; }
            if (!correct[1]) { cout << "Число сдвига - " << argv[2] << endl; }
        }
    }
    //если количество аргументов было другое - говорим какие аргументы и в каком порядке должны быть
    else {
        cout << "Аргументы программы:" << endl;
        cout << "1) Исходное число" << endl;
        cout << "2) число, на которое нужно сдвинуть влево" << endl;
    }
}

Прилагаю пример выполнения

введите сюда описание изображения


Ответы (1 шт):

Автор решения: AdolfDFO

Нашёл проблему. Проблема была в функции CharsToLongLong, из-за

res += pow(2, deg);

Функция pow работает с типом double. Чтобы получить степень двойки, необходимо было использовать побитовый сдвиг и заменить тип данных у deg из int на unsigned long long. Вместо сложения использовать дизъюнкцию

deg = (1ULL <<arr_size- 1-i);
res = res | deg;
→ Ссылка