Печать битов в длинном длинном номере (C++)
Я хочу напечатать все биты длинного длинного числа. Когда я делаю это в main(), все в порядке, но в функции printBits() (где код один и тот же) есть дополнительный 1 на 32-й бит.
Код:
#include <iostream>
void printBits(long long number)
{
std::cout<<number<<" -> ";
for (char i=63; i>=0; --i)
{
std::cout<<(bool)(number&(1<<i));
}
std::cout<<std::endl;
}
int main()
{
long long number=1;
std::cout<<number<<" -> ";
for (char i=63; i>=0; --i)
{
std::cout<<(bool)(number&(1<<i));
}
std::cout<<std::endl;
printBits(number);
return 0;
}
Результат:
1 -> 0000000000000000000000000000000000000000000000000000000000000001
1 -> 0000000000000000000000000000000100000000000000000000000000000001
Process returned 0 (0x0) execution time : 0.012 s
Press any key to continue.
3 ответа
Литерал 1 по умолчанию является целым числом. Примените это долго долго, чтобы решить проблему.
std::cout<<(bool)(number&(((long long)1)<<i));
Причина разных результатов в том, что компилятор (здесь clang 6.0) может выдавать другой код в основной функции и в printBits
,
В main
известно, что number
всегда 1 и никогда не меняется. Также "очевидно", что это может произвести только один 1
на выходе. Таким образом, оптимизатор переписывает цикл следующим образом:
for (char i=64; i > 0; --i)
{
std::cout<< (i == 1 ? 1 : 0);
}
Смотри, мама, без сдвигов!
Сборка выглядит так
012B13CC mov bl,40h ; i = 40h = 64
012B13CE xchg ax,ax ; nop to align the loop
main+30h:
012B13D0 xor eax,eax
012B13D2 cmp bl,1 ; i == 1?
012B13D5 mov ecx,esi
012B13D7 sete al
012B13DA push eax
012B13DB call edi ; edi -> operator<<
012B13DD dec bl
012B13DF jg main+30h (012B13D0h)
В printBits
он не может оптимизировать этот путь, так как функция может быть вызвана из другого места. Так что там он выполняет сдвиг (с ошибочным результатом).
Как показывает ответ Cpp plus 1, вам нужно изменить (по умолчанию int) литерал 1
к длинному длинному буквальному 1LL
или же 1ll
,
Тем не менее, вам может быть лучше использовать std::bitset
вместо вашей функции:
#include <bitset>
long long number = 1; // int number = 1; also works
std::bitset<64> bits(number);
std::cout << number << " -> " << bits << std::endl;
выходы:
1 -> 0000000000000000000000000000000000000000000000000000000000000001
Причина, по которой вы получаете этот вывод, заключается в том, что для конкретного используемого вами оборудования / компилятора:
a << x
Работа работает следующим образом: a << (x mod (8 * sizeof(a))
, Поэтому для 1
ты получаешь 1 << (x mod 32)
, Это означает, что на 32-й итерации цикла:
std::cout << (bool)(number & (1 << 32));
// becomes
std::cout << (bool)(number & (1 << 0));
// printing '1'