Автор Тема: Проблем с long long conversion to binary (std C99/ 32bit PC)  (Прочетена 1270 пъти)

!ntel

  • Участник
  • *****
  • Публикации: 444
    • Профил
Въпроса ми може да е тъп, но все пак ми се иска да разбера защо се получава така.
Постановката е следната:

Имам едно 32bit PC/Linux и програма на C, която конвертира тип long long към бинарна репрезентация.
Това което прави програмата е да принтира всеки един бит на променливата от тип long long, като за целта се ползват цикъл, условен оператор и бинарни оператори.

Това е кода на програмата:
Код
GeSHi (C):
  1. #include <stdio.h>
  2.  
  3. int main(void)
  4. {
  5.    long long i = -1;
  6.    int isOne;
  7.  
  8.    i = (( i^( i << 31)) + 2);
  9.    printf("Value: %lld\n", i);
  10.  
  11.    int numBits = sizeof(long long) * 8;
  12.    printf("numBits value: %d\n", numBits);
  13.  
  14.    for (int j = numBits - 1; j >= 0; j--)
  15.    {
  16.        isOne = i & (1 << j);
  17.        if(isOne)
  18.            printf("1");
  19.        else
  20.            printf("0");
  21.  
  22.        if(!(j%4))
  23.            printf(" ");
  24.    }
  25.  
  26.    printf("\n");
  27.    return 0;
  28. }

И тук идва проблема - изхода от програмата е следният:
Код:
Value: 2147483649
numBits: 64
Binary: 1000 0000 0000 0000 0000 0000 0000 0001 1000 0000 0000 0000 0000 0000 0000 0001

Проблемът е, че числото 2147483649 в бинарен вид е: 0000 0000 0000 0000 0000 0000 0000 0000 1000 0000 0000 0000 0000 0000 0000 0001
Въпросът ми е, защо се получава такъв изход. За съжаление не можах да намеря отговора сам чрез Интернет и затова пускам тема тук.
От чисто любопитство искам да разбера защо се получава така, когато ползвам тип long long.

PS: Проблема не е нещо от сорта на overflow, защото стойността на LLONG_MAX e 9223372036854775807.
Добавих и assembly изхода от компилатора, за повече яснота :)
« Последна редакция: Дек 03, 2012, 18:54 от !ntel »
Активен

gat3way

  • Участник
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Re: Проблем с long long conversion to binary (std C99/ 32bit PC)
« Отговор #1 -: Дек 03, 2012, 19:21 »
Замени това:

isOne = i & (1 << j);

с това:

isOne = (i >>j)&1;

И ще стане.
Активен

"Knowledge is power" - France is Bacon

bvbfan

  • Участник
  • *****
  • Публикации: 1056
  • Distribution: KaOS
  • Window Manager: Plasma 5
    • Профил
Re: Проблем с long long conversion to binary (std C99/ 32bit PC)
« Отговор #2 -: Дек 03, 2012, 19:25 »
Редът
Код
GeSHi (C):
  1. i = (( i^( i << 31)) + 2);
продуцира числото 0x8000000180000001 точно както го виждаш по битове, тъй като изместваш i с 32 бита xor-ваш и прибавяш 2, числото е -9,22337203041e+18, което е по-малко от -9,223,372,036,854,775,807 => LLONG_MIN.
Активен

!ntel

  • Участник
  • *****
  • Публикации: 444
    • Профил
Re: Проблем с long long conversion to binary (std C99/ 32bit PC)
« Отговор #3 -: Дек 03, 2012, 19:32 »
gat3way Благодаря за отговора.
Aко не е прекалено нахално, може ли да обясниш защо се получава така?
Просто ми е странно как тази имплементация работи за int (32bit), а за long long(64 bit) се получава този резултат :)
Активен

gat3way

  • Участник
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Re: Проблем с long long conversion to binary (std C99/ 32bit PC)
« Отговор #4 -: Дек 03, 2012, 19:41 »
Защото побитовата ти операция не е коректна, няма да върне 1 или 0 както предполагаш. На 32-битова система дава коректен резултат, защото isOne е int, след 31-вата итерация, винаги ще връща 0, защото AND-ваш (int)i с 0.
Активен

"Knowledge is power" - France is Bacon

!ntel

  • Участник
  • *****
  • Публикации: 444
    • Профил
Re: Проблем с long long conversion to binary (std C99/ 32bit PC)
« Отговор #5 -: Дек 03, 2012, 21:03 »
Тука вече съвсем се обърках.
Пробвах следният код:

Код
GeSHi (C):
  1. #include <stdio.h>
  2.  
  3. int main(void)
  4. {
  5.    long long isOne = (1 << 31);
  6.    printf("isOne value: %lld\n", isOne);
  7.    printf("Size of Long Long on this machine: %d  bytes", sizeof(long long));
  8.    return 0;
  9. }

И изхода:

Код:
isOne value: -2147483648
Size of Long Long on this machine: 8 bytes

WTF??? Нали уж имаме 8 байта (64 бита) - какви са тия отрицателни стойности?
Направо не знам какво да мисля вече...

PS: Дам, работата почва да се избистря...
Код
GeSHi (C):
  1.    long long isOne = 1;
  2.    isOne <<= 32;

С този код нещата се наредиха.
Нещата се нареждат и с другият код, когато добавя задължително кастване:
Код
GeSHi (C):
  1. long long isOne = ((long long)1 << 32);  // long long isOne = (1LL << 32);

Т.е. това значи следното:

Само 1 = good old int - bad things will happen when work with long long conversions.
Иначе 1LL = long long int - good things will happen when work with long long conversions.

PS:

И за да обобщя: Проблема беше породен едновременно от моята глупост (isOne трябва да е long long, но понеже преправях готов пример...) и заедно с това, трябва да оказвам на компилатора, че искам да работа с long long при побитовите операции иначе при компилирането прави неправилно (от моя гледна точка) конвертиране.

Като извод: Компютрите правят само това, което им кажеш, но когато и друг освен теб им е казал разни неща, трябва да ги разбираш по трудния начин и то в движение :)
« Последна редакция: Дек 03, 2012, 22:09 от !ntel »
Активен

gat3way

  • Участник
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Re: Проблем с long long conversion to binary (std C99/ 32bit PC)
« Отговор #6 -: Дек 03, 2012, 22:57 »
Не, isOne спокойно може да продължи да си е int, просто не трябва да го "захранваш" по този начин. В крайна сметка ти искаш да съдържа 1 или 0, 32 бита са предостатъчно :)
Активен

"Knowledge is power" - France is Bacon

!ntel

  • Участник
  • *****
  • Публикации: 444
    • Профил
Re: Проблем с long long conversion to binary (std C99/ 32bit PC)
« Отговор #7 -: Дек 03, 2012, 23:07 »
Така де  ;D Въпроса е принципен...
Понеже гледам тука едни уроци и веднага почнах да ги мисля едни извратени, та просто ми беше интересно да зачекна в тая посока.

Аз затова ти благодарих и за предложението, но въпреки това исках да видя защо е счупена другата имплементация :)
Активен

Подобни теми
Заглавие Започната от Отговора Прегледи Последна публикация
Binary files
Общ форум
hippo 4 963 Последна публикация Юли 16, 2004, 13:44
от hippo
Декодиране на binary текст от mysql
Живота, вселената и някакви други глупости
Regia 0 877 Последна публикация Авг 23, 2006, 15:21
от Regia
Long live openSuSE
Коментар
Vatman 0 864 Последна публикация Ное 13, 2009, 10:02
от Vatman
Very long int - C++
Общ форум
borovaka 25 3439 Последна публикация Окт 27, 2010, 03:33
от arda_kj
mount.nfs: Argument list too long
Настройка на програми
sash 26 3061 Последна публикация Яну 21, 2012, 21:55
от ieti