Zamiana z dziesiętnego na dwójkowy!

Zamiana z dziesiętnego na dwójkowy!
JA
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 2 lata
  • Postów:25
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

Kopiuj
 #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);
}
bogdans
Moderator
  • Rejestracja:prawie 17 lat
  • Ostatnio:prawie 5 lat
0

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

Kopiuj
    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.


To smutne, że głupcy są tak pewni siebie, a ludzie mądrzy - tak pełni wątpliwości. Bertrand Russell
edytowany 1x, ostatnio: bogdans
bogdans
Moderator
  • Rejestracja:prawie 17 lat
  • Ostatnio:prawie 5 lat
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.

Kopiuj
 #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.


To smutne, że głupcy są tak pewni siebie, a ludzie mądrzy - tak pełni wątpliwości. Bertrand Russell
JA
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 2 lata
  • Postów:25
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ś:

Kopiuj
 #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 :(

Zobacz pozostały 1 komentarz
bogdans
Nie wiedziałeś czy napisać potengi, czy też potęgi? I stąd hybryda 'potęngi'? A przy okazji, u mnie powyższy program działa błędnie jeśli x jest typu unsigned long long, umieszczony na ideone działa dobrze. Wiesz dlaczego?
_13th_Dragon
Pewnie masz ustawienia kompilatora Ansi-C, w którym nie ma long long
bogdans
Program się kompiluje i wykonuje. Na produkowane wyniki spójrz w poście.
_13th_Dragon
Nie rozumiem o jakie wyniki chodzi?
bogdans
No, o te trzy posty niżej.
_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:2 miesiące
1

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

Kopiuj
#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;
  }

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
edytowany 1x, ostatnio: _13th_Dragon
_13th_Dragon
Uprzedzam że nie jest to najszybsza możliwa wersja.
bogdans
Moderator
  • Rejestracja:prawie 17 lat
  • Ostatnio:prawie 5 lat
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.

Kopiuj
 #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;
}

To smutne, że głupcy są tak pewni siebie, a ludzie mądrzy - tak pełni wątpliwości. Bertrand Russell
JA
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 2 lata
  • Postów:25
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!

_13th_Dragon
Jeżeli uważasz że nauczyłeś się czegoś z tego przykładu to teraz bez problemu przyspieszysz go 8-krotnie.
bogdans
Moderator
  • Rejestracja:prawie 17 lat
  • Ostatnio:prawie 5 lat
0

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

Kopiuj
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

Kopiuj

To smutne, że głupcy są tak pewni siebie, a ludzie mądrzy - tak pełni wątpliwości. Bertrand Russell
Zobacz pozostałe 3 komentarze
bogdans
Taki kod działa: #include &lt;stdio.h&gt; int main() { unsigned long long x=13; while(x&gt;0) printf(&quot;%llu\n&quot;,x&gt;&gt;=1); return 0; } a taki nie`#include <stdio.h> int main() { unsigned long long x; scanf("%llu",&x); //13 i ENTER while(x>0) printf("%llu\n",x>>=1); return 0; }Psuje wywołanie funkcji scanf, jeśli po jej wywołaniu dodam przypisanie x=13;` znów jest dobrze.
_13th_Dragon
Ok chyba jarzę. printf i scanf dal twojego kompilatora nie łapią "llu". Sprawdź może złapie "lu" oraz sprawdź "lld".
bogdans
Nie pomogło, ale wyniki są jeszcze ciekawsze: 6 3 1 0 0 0 0 0 0 0 0 0 -2147483648 ....
bogdans
Sprawdziłem obie możliwości, obie działają źle.
bogdans
Moderator
  • Rejestracja:prawie 17 lat
  • Ostatnio:prawie 5 lat
0
Kopiuj
    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.


To smutne, że głupcy są tak pewni siebie, a ludzie mądrzy - tak pełni wątpliwości. Bertrand Russell
_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:2 miesiące
0

A jak skrócisz do:

Kopiuj
#include <stdio.h>

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

lub do:

Kopiuj
#include <stdio.h>

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

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
bogdans
Moderator
  • Rejestracja:prawie 17 lat
  • Ostatnio:prawie 5 lat
0

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

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

To smutne, że głupcy są tak pewni siebie, a ludzie mądrzy - tak pełni wątpliwości. Bertrand Russell
_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:2 miesiące
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


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
bogdans
Źle sądzisz. Jak będziesz w Poznaniu zapraszam do mojego komputera (nie zaktualizuje kompilatora).
_13th_Dragon
No to podaj namiary tego kompilatora.
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)