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

kifavi8024

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

Имам едно 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 изхода от компилатора, за повече яснота :)
« Последна редакция: Dec 03, 2012, 18:54 от !ntel »
Активен

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Re: Проблем с long long conversion to binary (std C99/ 32bit PC)
« Отговор #1 -: Dec 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 -: Dec 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.
Активен

kifavi8024

  • Новаци
  • *
  • Публикации: 0
    • Профил
Re: Проблем с long long conversion to binary (std C99/ 32bit PC)
« Отговор #3 -: Dec 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 -: Dec 03, 2012, 19:41 »
Защото побитовата ти операция не е коректна, няма да върне 1 или 0 както предполагаш. На 32-битова система дава коректен резултат, защото isOne е int, след 31-вата итерация, винаги ще връща 0, защото AND-ваш (int)i с 0.
Активен

"Knowledge is power" - France is Bacon

kifavi8024

  • Новаци
  • *
  • Публикации: 0
    • Профил
Re: Проблем с long long conversion to binary (std C99/ 32bit PC)
« Отговор #5 -: Dec 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 при побитовите операции иначе при компилирането прави неправилно (от моя гледна точка) конвертиране.

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

gat3way

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

"Knowledge is power" - France is Bacon

kifavi8024

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

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

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