Печать битов в длинном длинном номере (C ++) - PullRequest
0 голосов
/ 01 мая 2018

Я хочу напечатать все биты длинного длинного числа. Когда я делаю это в 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 ]

0 голосов
/ 01 мая 2018

Как показывает ответ 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 -> 0000000000000000000000000000000000000000000000000000000000000000000000000001

Причина, по которой вы получаете этот вывод, в том, что для конкретного используемого вами аппаратного / компилятора:

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'
0 голосов
/ 02 мая 2018

Причина разных результатов в том, что компилятор (здесь 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 он не может оптимизировать этот путь, так как функция может быть вызвана из другого места. Таким образом, он выполняет сдвиг (с ошибочным результатом).

0 голосов
/ 01 мая 2018

Литерал 1 по умолчанию равен целому числу. Примените это долго долго, чтобы решить проблему.

std::cout<<(bool)(number&(((long long)1)<<i));
...