Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.60/5: Рейтинг темы: голосов - 5, средняя оценка - 4.60
0 / 0 / 0
Регистрация: 10.10.2021
Сообщений: 15
1

Реализовать циклический сдвиг влево на указанное количество бит

05.12.2022, 22:09. Показов 872. Ответов 16
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Доброе время! У меня проблема. Мне необходимо реализовать циклический побитовый сдвиг влево, с маленькими числами все отлично работает, но когда ввожу максимальное число для 64 бит(9223372036854775807) то мне выдает другое число
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#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;
    }
}
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
05.12.2022, 22:09
Ответы с готовыми решениями:

Осуществить сдвиг элементов матрицы на указанное количество позиций влево
Дана целочисленная прямоугольная матрица. Осуществить сдвиг элементов матрицы на указанное...

Циклический сдвиг влево элементов массива на заданное количество позиций
Осуществить циклическое смещение компонентов вектора A(a1,a2,...,an) на l позиций влево таким...

Циклический побитовый сдвиг числа вправо на указанное количество бит, но только для нечетных битов
Реализовать циклический побитный сдвиг числа вправо на указанное число(n), но только для нечетных...

Циклический сдвиг на 11 бит влево
Здравствуйте форумчане, ломаю голову, как можно выполнить сдвиг на 11 бит влево вот этого двоичного...

16
фрилансер
5843 / 5372 / 1102
Регистрация: 11.10.2019
Сообщений: 14,355
05.12.2022, 22:32 2
Mentiorowski, чуток упростить можно

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <bitset>
#include <climits>
 
int main()
{
    uint64_t value=0b1100111000111100001111001100110011111111000000001111000010101010;
    size_t leftshift=3;
    
    constexpr size_t len=sizeof(value)*CHAR_BIT;
    
    uint64_t right_mask=std::numeric_limits<uint64_t>::max()>>leftshift;
    uint64_t left_mask=~right_mask;
    
    uint64_t result=((value&right_mask)<<leftshift) | ((value&left_mask)>>(len-leftshift));
    
    std::cout<<"value ="<<std::bitset<len>{value }<<'\n';
    std::cout<<"result="<<std::bitset<len>{result}<<'\n';
}
value =1100111000111100001111001100110011111111000000001111000010101010
result=0111000111100001111001100110011111111000000001111000010101010110
0
0 / 0 / 0
Регистрация: 10.10.2021
Сообщений: 15
05.12.2022, 22:37  [ТС] 3
Проблема именно в том, что когда я ввожу это максимальное число и сдвигаю на 64 бит(по кругу то есть) , он новое число переводит из двоичной в десятичной неправильно. Пример:
Input: 9223372036854775803(введеное число) 64(сдвиг влево на 64)
Output: Исходное число в двоичном виде:
01111111 11111111 11111111 11111111 11111111 11111111 11111111 11111011
Сдвиг влево на число бит: 64
Результат сдвига:
01111111 11111111 11111111 11111111 11111111 11111111 11111111 11111011
Получившееся число:
9223372036854775808
То есть не соответсвует введеному мною числу, хотя именно в двоичном коде сдвиг организован верно
0
6340 / 3511 / 1427
Регистрация: 07.02.2019
Сообщений: 8,977
05.12.2022, 22:43 4
Цитата Сообщение от Mentiorowski Посмотреть сообщение
он новое число переводит из двоичной в десятичной неправильно
Вот из-за этого гомнокода:
Цитата Сообщение от Mentiorowski Посмотреть сообщение
res += pow(2, deg);
0
0 / 0 / 0
Регистрация: 10.10.2021
Сообщений: 15
05.12.2022, 23:02  [ТС] 5
Но это же и есть перевод в десятиричное число, как где у меня единицы, там сумма двух степени, так же и переводит, не совсем понимаю
0
6340 / 3511 / 1427
Регистрация: 07.02.2019
Сообщений: 8,977
05.12.2022, 23:44 6
Цитата Сообщение от Mentiorowski Посмотреть сообщение
не совсем понимаю
Функция pow работает с типом double.
У double мантисса всего 52 бита.
Для получения натуральной степени двойки используй битовый сдвиг.
2n = (1ULL << n)

А вместо сложения - побитовое ИЛИ.
0
0 / 0 / 0
Регистрация: 10.10.2021
Сообщений: 15
06.12.2022, 00:02  [ТС] 7
Я воспользовался, стал получать совсем иные значения
C++
1
2
deg = (1ULL << i);
 res = res | deg;
Input: 9223372036854775903 64
Исходное число в десятиричном виде:
9223372036854775903
Исходное число в двоичном виде:
10000000 00000000 00000000 00000000 00000000 00000000 00000000 01011111
Сдвиг влево на число бит: 64
Результат сдвига:
10000000 00000000 00000000 00000000 00000000 00000000 00000000 01011111
Получившееся число:
1
То есть проблема также с переводом. Я как-то неправильно реализовал?
0
6340 / 3511 / 1427
Регистрация: 07.02.2019
Сообщений: 8,977
06.12.2022, 00:18 8
Цитата Сообщение от Mentiorowski Посмотреть сообщение
deg = (1ULL << i);
А deg у тебя какого типа?
0
0 / 0 / 0
Регистрация: 10.10.2021
Сообщений: 15
06.12.2022, 00:19  [ТС] 9
integer
0
6340 / 3511 / 1427
Регистрация: 07.02.2019
Сообщений: 8,977
06.12.2022, 00:20 10
Цитата Сообщение от Mentiorowski Посмотреть сообщение
integer
Что это? Нет такого типа в С++.
0
0 / 0 / 0
Регистрация: 10.10.2021
Сообщений: 15
06.12.2022, 00:20  [ТС] 11
Целое число, int
0
6340 / 3511 / 1427
Регистрация: 07.02.2019
Сообщений: 8,977
06.12.2022, 00:22 12
Цитата Сообщение от Mentiorowski Посмотреть сообщение
int
Ну и как думаешь, поместится, например, 240 в int?
0
0 / 0 / 0
Регистрация: 10.10.2021
Сообщений: 15
06.12.2022, 00:25  [ТС] 13
А, то есть меня интересует long long? Но переменная deg же вмещает в себя значение степени, а не само число возведенную в неё
0
6340 / 3511 / 1427
Регистрация: 07.02.2019
Сообщений: 8,977
06.12.2022, 00:29 14
Цитата Сообщение от Mentiorowski Посмотреть сообщение
Но переменная deg же вмещает в себя значение степени, а не само число возведенную в неё
Я не знаю, что она там по твоей задумке вмещает, но справа от оператора присваивания находится именно чило 2 возведенное в степень i и имеет тип unsigned long long.
0
0 / 0 / 0
Регистрация: 10.10.2021
Сообщений: 15
06.12.2022, 00:37  [ТС] 15
Такая проблема возникла: я изменил тип переменной deg на long long, я все равно получаю вывод совсем рандомного содержания в десятиричном виде
C++
1
2
3
4
5
6
7
8
9
10
long long CharsToLongLong(char arr[], int arr_size) {
    long long res = 0;
   unsigned long long deg;
    for (int i = arr_size - 1; i >= 0; i--) {
        if (arr[i] == '1') {
            deg = (1ULL << i);
            res = res | deg;
            
        }
    }return res;
Я всё таки что-то упускаю?
0
6340 / 3511 / 1427
Регистрация: 07.02.2019
Сообщений: 8,977
06.12.2022, 00:41 16
Лучший ответ Сообщение было отмечено Mentiorowski как решение

Решение

Mentiorowski, ну наверное потому, что у тебя i отображает не степень. Почему в оригинале у тебя зависимость степени от i была такой:
Цитата Сообщение от Mentiorowski Посмотреть сообщение
arr_size - 1 - i
А тут вдруг стала просто i?
1
0 / 0 / 0
Регистрация: 10.10.2021
Сообщений: 15
06.12.2022, 00:47  [ТС] 17
Благодарю за помощь!) Совсем забыл про arr_size
0
06.12.2022, 00:47
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
06.12.2022, 00:47
Помогаю со студенческими работами здесь

Циклический сдвиг списка вправо или влево на указанное число позиций
def func(l, n): return l + l try: s=input('Введите список чисел через пробел: ') l...

Циклический сдвиг в целом числе на n бит влево и вправо
Написать функцию циклического сдвига в 2𝑝 разрядном целом числе на 𝑛 бит влево и вправо.

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

Циклический сдвиг элементов массива влево на заданное количество позиций
Составить процедуру (или функцию), которая переставляет первые k элементов массива A в конец...

Циклический сдвиг содержимого цепочки слов на заданное количество бит вправо
Написать подпрограмму циклического сдвига содержимого цепочки слов на заданное количество бит...

Логический сдвиг влево,логический сдвиг вправо,алгоритм обмена двух переменных,циклический сдвиг
Битовые сдвиги.FW4,msstudio 13,на C# 1)Реализовать быстрое умножение на 2(логический сдвиг влево)...

Сдвиг влево на один бит
void Bitstring::shl() { int carry=!!(str&amp;0x80000000); str&lt;&lt;=1; str|=carry; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru