Zamiana z dziesiętnego na dwójkowy!

0

Witam! Za zadanie mam wczytać liczbę w zakresie od 0 do 2^64-1, następnie zamienić na postać dwójkową, odwrócić kolejność np. 110 na 011 i tą odwróconą liczbę w systemie dwójkowym zamienić na liczbę w systemie dziesiętnym. Zrobiłem taki programik, lecz raz: przekracza limit czasowy, dwa: podobno wyskakują błędne odpowiedzi :O Czy ktoś mógłby pomóc mi znaleźć szybszy sposób na wykonanie tego zadania? I ewentualnie powiedzieć co jest źle już w tym istniejącym :D
Pozdrawiam

 #include <stdio.h>

int potega(int j);

int main(void){
    char nap[64];
    int i,j;
    unsigned long long x,wynik;
    while(scanf("%llu",&x)!=EOF){
        for(i=0;i<64;i++){
            if(x==0){
                nap[i]='0';
                break;
            }
            if(x%2==1)nap[i]='1';
            else nap[i]='0';
            x=x/2;
        }
    wynik=0;
    for(j=0;i>=0;j++){
        if(nap[j]=='1')wynik+=potega(i-1);
        i--;
    }
printf("%llu\n",wynik);
    }
    return 0;
}

int potega(int j){
    if(j==0)return 1;
    return 2*potega(j-1);
}
0

Bardzo niewydajnie liczysz potęgi. Tak będzie szybciej:

    wynik=0;
    int potega = 1;
    for(j=0;i>=0;j++){
        if(nap[j]=='1')wynik+=potega;
        potega*=2;
        i--;
    }

A jeszcze szybciej będzie gdy mnożenie przez 2 zastąpisz przesunięciem bitowym.
Nie widzę też żebyś zmieniał kolejność cyfr w zapisie dwójkowym.

0

Poczekamy na jakiegoś specjalistę od C++. Twój oryginalny program (z pętlą for) i mój (z pętlą while) nie wychodzi z pętli gdy x == 0 jeżeli x jest typu unsigned long long.

 #include <stdio.h>

int main(void)
{
    char nap[64];
    int i,j;
    unsigned long long wynik;
    int x;
    while(scanf("%llu",&x)!=EOF)
    {
        for(i=0;i<64;i++)
            nap[i]='0';
        i = 0;
        while(x>0)
        {
            if(x%2==1)
            {
                nap[i]='1';
            }
            else
            {
                nap[i]='0';
            }
            x = x >> 1;
            i++;
        }
        wynik = 0;
        int potega = 1;
        for(j=i-1;j>=0;j--)
        {
            if(nap[j]=='1')wynik+=potega;
            potega*=2;
        }
        printf("%llu\n",wynik);
    }
    return 0;
}

Wykryłem jeszcze jeden błąd, nie "sprzątałeś" tablicy nap.

0

Hmm, kolejności cyfr w zapisie dwójkowym nie zamieniam, ponieważ program od razu podaje odwróconą formę. Co oznacza ' x = x >> 1;'? Bo ja piszę w C jakby co :)
na razie mam takie coś:

 #include <stdio.h>

int potega(int j);

int main(void){
    char nap[64];
    int i,j,potega1;
     unsigned long long x,wynik;
    while(scanf("%llu",&x)!=EOF){
    for(i=0;i<64;i++)
            nap[i]='0';
        i = 0;
        for(i=0;i<64;i++){
            if(x==0){
                nap[i]='0';
                break;
            }
            if(x%2==1)nap[i]='1';
            else nap[i]='0';
            x=x/2;
        }
    wynik=0;
    potega1=potega(i-1);
    for(j=0;i>=0;j++){
        if(nap[j]=='1')wynik+=potega1;
        potega1=potega1/2;
        i--;
    }
printf("%llu\n",wynik);
    }
    return 0;
}

int potega(int j){
    if(j==0)return 1;
    return 2*potega(j-1);
}

Poprawiłem funkcję z potęgami, wprowadziłem czyszczenie tablicy, jednak limit czasu dalej przekroczony :(

1

Na takie przetworzenie z jednej liczby na drugą wystarczy jeden for z if'em:

#include <stdio.h>
 
int main(void)
  {
   unsigned long long x,m,R;
   while(scanf("%llu",&x)==1)
     {
      for(R=0,m=1<<63;m,x>>=1,m>>=1) if(x&1) R|=m;
      printf("%llu\n",R);
     }
   return 0;
  }
0

Ty nie masz poprawiać funkcji potega, Ty masz ja usunąć.
x >> 1 to przesunięcie bitowe w prawo o jeden bit (dostępne w C) arytmetycznie równoważne jest z dzieleniem przez 2. Użycie przesunięcia może nie mieć znaczenie, jeśli kompilator sam zamieni dzielenie na przesunięcie.

 #include <stdio.h>

int main(void){
    char nap[64];
    int i,j;
    unsigned long long wynik, x, potega;
    while(scanf("%llu",&x)!=EOF){
    for(i=0;i<64;i++)
            nap[i]='0';
        i = 0;
        potega = 1;
        for(i=0;i<64;i++){
            if(x==0)
            {
                break;
            }
            if(x%2==1)nap[i]='1';
            else nap[i]='0';
            x/=2;
        }
        wynik = 0;
        for(j=i-1;j>=0;j--){
            if(nap[j]=='1')wynik+=potega;
            potega=potega*=2;
        }
        printf("%llu\n",wynik);
    }
    return 0;
}
0

Faktycznie teraz poszło :) Dziękuję, dzięki wam program po programie dowiaduję się czegoś nowego (przesunięcia bitowe) i uczę się jak pisać szybsze i wydajniejsze programy ;]
Pozdrawiam!

0

Dla @_13th_Dragon'a. Jeśli x = 13, to kod

while(x>0)
{
     x/=2;
     printf("%llu\n",x);
}

produkcode>produkuje
6
3
1
0
0
2147483648
1073741824
2684354560
3489660928
3892314112
4093640704
2046820352
3170893824
1585446912
792723456
396361728
198180864
99090432
49545216
24772608
12386304
6193152
2150580224
1075290112
537645056
268822528
134411264
67205632
33602816
16801408
8400704
4200352
2100176
1050088
525044
262522
131261
65630
32815
16407
8203
4101
2050
1025
512
256
128
64
32
16
8
4
2
1
0

0
    char nap[64];
    int i,j;
    unsigned long long wynik,x;
    //int x;
    while(scanf("%llu",&x)!=EOF)
    {
        for(i=0;i<64;i++)
            nap[i]='0';
        i = 0;
        while(x>0)
        {
            /*if(x%2==1)
            {
                nap[i]='1';
            }
            else
            {
                nap[i]='0';
            }*/
            x = x >> 1;
            printf("%llu\n",x);
            //i++;
        }
        //przeliczenia
    }

Korzystam z Code::Blocks, on pokazuje, że korzysta z GNU GCC Compiler.

0

A jak skrócisz do:

#include <stdio.h>

int main()
  {
   unsigned long long x=13;
   while(x>0)
     {
      x=x>>1;
      printf("%llu\n",x);
     }
   return 0;
  }

lub do:

#include <stdio.h>

int main()
  {
   unsigned long long x=13;
   while(x>0) printf("%llu\n",x>>=1);
   return 0;
  }
0

Oba działają dobrze, pierwotny kod też działa dobrze po takiej modyfikacji

    unsigned long long wynik,x=13;
    //while(scanf("%llu",&x)!=EOF)
    {
        while(x>0)
        {
            x = x >> 1;
            printf("%llu\n",x);
        }
        //obliczenia
    }
0

Sądzę że tamto też działało dobrze z tym że miałeś jakieś mazanko po pamięci którego nie ujawniłeś ;P

1 użytkowników online, w tym zalogowanych: 0, gości: 1