Potřeboval bych poradit jak udělat následující. Mám číslici 75 v desítkové soustavě (uint32_t). Binárně je to
01 00 10 11 a potřeboval bych převést jednotlivé dvojce na char ale v desítkové soustavě.
Tedy 01 => '1', 00 => '0', 10 => '2', 11 => '3'
jednak nevím jak se převádí za 75 na binární (ale to snad ani nebude třeba?)
Napadá mě smyčka a posun do leva, ale to mi příjde neefektivní, protože bych k tomu potřeboval pomocné proměnné a provádět přiřazování což samo o sobě je časově náročnější operace než čtení. Jedná se jen o 4 číslice.
A druhak nevím jak převést tu binární dvojci na char v desítkové soustavě.
#1oxidián
Najdi si na googlu převod z desítkové do binární soustavy v C, pak výsledný řetězec charů rozděl po dvou a na každou dvojici použij třeba atoi.
#5oxidián
No dobře, až mi ukážeš, jak třeba do integeru nacpeš 110010101100001011011011, tak uznám, že převádět číslo v desítkové soustavě na řetězec charů je zbytečné :-).
#7oxidián
Bitový posun ale můžeš provádět na číslech, na nichž to jde. Vem si například 32bitový signed integer, ten má rozmezí -2 147 483 648 až 2 147 483 647. Tedy horní hranice je 2 miliardy 147 milionů 483 tisíc 647. A vyšší číslo do integeru prostě nedáš kvůli OverflowException.
Když horní hranici vyjádříš v dvojkové soustavě, dostaneš 1 111 111 111 111 111 111 111 111 111 111. Takové číslo je v desítkové soustavě 1 kvintilion 111 kvadriliard 111 kvadrilionů 111 triliard 111 trilionů 111 biliard 111 bilionů 111 miliard 111 milionů 111 tisíc 111. Jestli se ti povede do běžného integeru narvat 1 kvintilion, budeš asi první na světě.
BTW: Kvintilion nenacpeš ani do 64bitového unsigned integeru, jediná možnost pro vyjadřování čísel ve dvojkové soustavě je prostě přes pole znaků.
#9oxidián
I tak se to jinak nedělá. Prostě pole charů. (Udělal ti to tak i ingiraxo, akorát namísto pole charů používá string z C++.)
ingiraxo na převáděí používá bitset, ale převést číslo z dekadické do binární soustavy můžeš udělat normálně modulem a následným podělením dvěma. Výsledky narvat do toho pole charů, jak jsem psal, pak to projet for cyklem a prvky i a i+1 znovu převést nazpátek do dekadické soustavy.
Jinak toto nejsou žádné složité operace, fakt ne. Je to pár cyklů dohromady s tím, že si musíš ohlídat pár indexů. To je úplně celé.
haha zrovna ho studuju, tos nemusel posílat. Ale nevím jak zapsat binární jedničku (bit) do čísla? Protože musím tu detekovanou hodnotu někam zapsat. Tak já mám proměnnou uint16_t ch=0; a do toho chci zapsat tu zjištěnou hodnotu. Ta hodnota má jeden bit, ale jak zapsat bit na první místo a pak bit na druhé místo zprava?
Proc se tu resi binarka, kdyz mi to pripada, ze chce ctyrkovou soustavu.. Samozrejme pan "bit shift je pomalej" predpoklada, ze bude potreba dalsich promennych (coz ani moc neni)
Tak jsem to dokázal, jen se chci ještě zeptat jestli se to dá nějak udělat aby se k neměnilo. Protože se k mění, tak jsem musel udělat 3 kopie k a do každého příkazu dát samostatnou kopii, abych pokaždé pracoval s tím původním číslem 75.
uint16_t k,kk,kkk,kkkk;
// unsigned char a,b,c,d;
uint32_t n;
k=kk=kkk=kkkk = 75;
int c_ = 15; n = (uint32_t) k; printf("%d\n",n); for (; c_ >= 0; c_--) { k = n >> c_; if (k & 1) printf("1"); else printf("0"); }
n = k & ~(0b11111100); // delete pair of bits
printf("\n%d\n",k);
c_ = 15; printf("\n%d\n",n); for (; c_ >= 0; c_--) { k = n >> c_; if (k & 1) printf("1"); else printf("0"); }
n = (kk & ~(0b11110011)) >> 2 ; // delete pair of bits
printf("\n%d\n",kk);
c_ = 15; printf("\n%d\n",n); for (; c_ >= 0; c_--) { k = n >> c_; if (k & 1) printf("1"); else printf("0"); }
n = (kkk & ~(0b11001111)) >> 4; // delete pair of bits
printf("\n%d\n",kkk);
c_ = 15; printf("\n%d\n",n); for (; c_ >= 0; c_--) { k = n >> c_; if (k & 1) printf("1"); else printf("0"); }
n = (kkkk & ~(0b00111111)) >> 6; // delete pair of bits
printf("\n%d\n",kkkk);
c_ = 15; printf("\n%d\n",n); for (; c_ >= 0; c_--) { k = n >> c_; if (k & 1) printf("1"); else printf("0"); }
#15oxidián
ok, verze č.2, pokusil jsem se nepoužít žádný dělěno, modulo apod.. :-D i když to vypadá neefektivně tak tomu tak není, je to poměrně rychlý
void homework(int n, char* r)
{
int i,j,k,x;
char t[3] = { 0 };
for (i = 7, j = 1, k = 4; i >= 0; --i, n >>= 1, --j) {
*(t + j) = (n & 1) + '0';
if (j == 0) {
if (*(t + 1) == '1' && *t == '1') x = '3';
else if (*(t + 1) == '1') x = '1';
else if (*t == '1') x = '2';
else x = '0';
*(r + --k) = x;
j = 2;
}
}
}
int main()
{
char r[5] = { 0 };
homework(75, r); // 1023
puts(r);
return EXIT_SUCCESS;
}
díky. Tak to asi pracuje neomezeně na libovolný počet cifer, viď? Mě konkrétně stačili 4 cifry, takže viz před tebou moje řešení, ještě se to dá udělat tak, že to nejdříve posunu doleva o dvě cifry a pak použuju masku zprava kratší o dvě cifry.
#17oxidián
ne, též to pracuje na 4 cifry, číslo int to vždy převede do binaru o 8 bitech, takže velikost vstupního čísla nijak nemění rychlost převodu (cyklus se vždy vykoná 8x pro celý vypočet)
Tak jsem se to jal otestovat a změřit. Vytvořil jsem smyčku 4000x4000 cyklů aby byl vidět rozdíl. Časovač resetován těsně před cyklem a po cyklu ukončen.
PRVNÍ TESTY OBSAHUJÍ CHYBU:
Toto je můj kód
uint32_t n,m;
n=0; m=4000*4000;
uint16_t k,kk,kkk,kkkk;
unsigned char a,b,c,d;
k=kk=kkk=kkkk = 75;
for (;n<m;n++){
a = k & ~(0b11111100);
b = (kk & ~(0b11110011)) >> 2 ;
c = (kkk & ~(0b11001111)) >> 4;
d = (kkkk & ~(0b00111111)) >> 6;
}
jen nezapomen, ze ti to optimalizace muze uplne vyhodit, kdyz to pak nepouzijes (ci si to rekne, ze je to furt stejny, tak to spocita v jednom kole a necha ti to vysledek)
Nahlásit jako SPAM
IP: 94.113.95.–
Program vždy dělá to co naprogramujete, ne to co chcete...
já mám dojem, že to zbytečně moc řešíš. proč prostě nepoužiješ to co napsal kiiv? Pro tvůj případ, kdy to nepřevádíš přímo do binaru jako celý číslo, ale jen vypočitáváš dvojice, tak stačí ty 4 řádky s bitovým posunem.
Jestli milion iterací trva 0.04 nebo 0.2 je úplně jedno, nepoznáš v praxi při dnešním HW. A jestli je to natolik špatně optimalizovany, tak se vytvářej cache, dá se pryč kurvítko (sleep) nebo se to optimalizuje, ale někdy to úplně dobře nejde a používají se cache, tudíš i vyšší nároky na pamět.
A jestli se chceš dostat po 0.01s, tak to prostě pust na výkonějším stroji ;)
Ještě potřebuju poradit jestli správně převádím do 16ctkové soustavy:
decimal: 75
binary: 1001011
rozděleno: 0100 1011
base 16: 4 11
Edit - zkouška: (int) 75/16 = 4 a zbytek je 11. ... 4*16^1 + 11*16^0 = 411?
No to teda není jedno. Kdybych něco podobného používal na zpracování grafických operací u obrazu tak tam hrajou milisekundy velkou roli. Protože když těch operací budou desítky (různé operace, kopírování bitů, porovnávání masek, převody masek a já nevím co vše používá třeba Photoshop) tak je rozdíl jestli se ten obraz zpracuje za 0.5s nebo 2s. Když to děláš hromadně (několik desítek nebo stovek souborů) tak rozdíl může být v desítkách minut. Rozdíl jestli něco trvá 2 minuty nebo deset, 10 minut nebo 40 je dost velký. A nepotřebuju k tomu kupovat stroj za 40-90 tisíc.
"Pro tvůj případ, kdy to nepřevádíš přímo do binaru jako celý číslo, ale jen vypočitáváš dvojice, tak stačí ty 4 řádky s bitovým posunem."
Nechápu proč to píšeš? Děláš ze mě blba? Vždyť s tím bitovým posunem jsem přišel já že to tak bude nejrychlejší a vy ste pořád oponovali že to je zbytečné a že rychlejší to je přes řetězce...
#27oxidián
Najprv si to implementuj jednoducho, ked budes mat funkcny program spust ho a zisti ktore casti kodu trvaju najdlhsie a tie casti optimalizuj. Predcasne optimalizovat je vecisinou strata casu lebo vo finalnom programe bude uzke hrdlo uplne ina cast pripadne niektore casti nakoniec ani nepouzies, cize je zbytocne ich optimaliovat.
Nahlásit jako SPAM
IP: 46.165.251.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
A budu ztrácet čas přepisováním? Díky, ale ne. Tys to ale asi vůbec nepochopil. Já chtěl jen 4 číslice a toho jsem dosáhl. Na tom se taky učím ty převody. Je to jednoduché a přehledné.
Časy jsem poměřoval proto, že až to budu potřebovat někde jinde vím jak dlouho to trvá a mám představu o tom co je rychlejší. Samozřejmě tu dynamickou metodu od KIIVa nezavrhuju, jen ji momentálně nepotřebuju.
#27oxidián
bral jsem to tak, že ti přijde nějaký číslo a ty ho v prvním kroku potřebuješ převést do binaru a až v druhém ty dvojice projít...
nevim proč sem motáš grafický operace, tam se většinou používaj matice
souhlasim s tím co napsal vitamín.. optimalizace bývá až mezi posledními kroky, ted tomu dáš hodiny/dny a ve výsledku zjistíš, že zpomalení nastane úplně jinde a třeba ani nepůde z optimalizovat... proto jsem i psal, že to ted nemáš tolik řešit... i v praxi se optimalizace dělá až ve chvíli, kdy je potřeba, dnes se dává přednost přehlednému kódu, protože nikdy nevíš, kdo ten kód po tobě bude spravovat a taky máme vykonější stroje :)
Jenže já vám to opakuju už po sté, že toto není součást žádné složité aplikace. Je to samostatné řešení, které nemá se zbytkem jakékoliv aplikace nic společného. Chtěl jsem prostě nejjednodušší a nejefektivnější cestu. Tudíž bavit se o nějaké optimalizaci je úplně mimo mísu. Celá má aplikace tvoří asi 10 řádků kódu na kterém si testuju převod z desítkové soustavy do čtyřkové a z desítkové do šestnáctkové. Toto řešení pak mohu kdykoliv použít ve složitějším programu. Nejdůležitější ale je, že toto řešení je nejjednodušší na pochopení, a ne nějaké složité cykly které začátečníkovi třeba nic neřeknou. Je tam maska a z té masky lze odečíst jednoduše a přehledně výsledek. Celé řešení je postaveno na tom jak nejjednodušeji vysvětlit či spočítat ten převod. Že vezmeš binární ekvivalent desítkového čísla třeba 000110101011 a rozdělíš to po třech 000 110 101 011 nebo po čtyřech 0001 1010 1011. Nic víc v tom není. Není třeba dělat složité funkce, přinejmenším ne na vysvětlení základů. Nechápu co na tom nechápete.