Procitati prije programiranja s bazama (brojevnim sustavima)
Select messages from
# through # FAQ
[/[Print]\]

Forum@DeGiorgi -> Programiranje 1 i 2

#1: Procitati prije programiranja s bazama (brojevnim sustavima) Autor/ica: vsegoLokacija: /sbin/init PostPostano: 15:40 pon, 26. 11. 2012
    —
Ovaj post je nastao jer mi je konacno dosadilo svake godine pisati isto. Sad mogu samo dati link. Cool

Poanta: "Broj" i "zapis broja" su dva vrlo razlicita pojma.
Broj se moze zapisati u nekoj bazi, pri cemu se sam broj ne mijenja, nego samo njegov zapis.
Broj se ne moze pretvoriti iz jedne baze u drugu, jer promjena broja znaci da to vise nije isti broj.

Svi kojima ova poanta nije kristalno jasna i/ili ne razumiju zasto je vazna, nastavite citati. Ostali, svejedno procitajte. Razz

Ako napisete program koji sadrzi ovako nesto
Kod:
broj_n_u_bazi_b = 0;
potencija_baze = 1;
while (n > 0) {
  broj_n_u_bazi_b += potencija_baze * (n % b);
  potencija_baze *= 10;
  n /= b;
}

vjerojatno cete biti uvjereni da je rijec o "pretvaranju broja u bazu b" ili tako necemu.

No, broj se ne moze "pretvoriti u bazu", nego samo zapisati u njoj. Dakle, da ste ispisivali n % b u gornjoj petlji, zaista biste ispisali znamenke broja n kad ga se zapise u bazi b (redoslijed ispisa je s desna nalijevo, ali to sada nije bitno).

Ono sto vas program radi je da neki broj zamijeni s brojem koji zapisan dekadski izgleda kao ovaj prvi kad se zapise u bazi b. Na primjer, [tex]n = 6[/tex] ce zamijeniti sa [tex]110[/tex]. To mozda izgleda kao da ima smisla jer je [tex](6)_{10} = (110)_2[/tex], ali ne mijenja cinjenicu da je jedan broj sest, a drugi je sto i deset i oni nemaju veze jedan s drugim!

U nastavku programa cete sa znamenkama broja raditi tako da broj dijelite s 10, no postavlja se pitanje cemu ta gimnastika? Zasto jednostavno ne dijelite stalno s b i zaboravite "pretvaranje"?

Ne bi ovo bilo tako lose, da ne uzrokuje stvarno ozbiljne probleme.

Problem 1:

Recimo da zelimo nesto raditi s brojem [tex]4096 = 2^{12} = (1000000000000)_2[/tex], sto binarno zapisano ima jednu jedinicu i 12 nula. Pokusate li to "pretvoriti" kako je gore prikazano, dobit cete broj koji, zapisan dekadski, jednako izgleda kao 4096 zapisan binarno. Dakle, dobit cemo broj koji u dekadskom zapisu ima jednu jedinicu i nakon nje 12 nula.

Problem lezi u neprikazivosti tog broja u standardnoj aritmetici racunala. Naime,
[tex]1000000000000 = (1110100011010100101001010001000000000000)_2[/tex],
sto znaci da za prikaz tog broja treba 40 bitova, a u int stane samo 31 (u unsigned stanu 32 bita) i program se raspadne.

Naravno, mozemo koristiti long ili cak tipove mimo standarda, poput long long, ali to samo znaci da cemo uhvatiti sitno brojeva vise. Recimo, broj [tex]1048576 = 2^{20}[/tex] u binarnom zapisu ima jednu jedinicu i 20 nula. Gornjim "pretvaranjem" dobijemo broj koji za zapis trazi 67 bitova. Dakle, nas pocetni broj stane u obicni int, a "pretvoreni" ne stane niti u dvostruko vise memorije.

Koristenjem tipa double radimo jos vece zlo, jer se gube znamenke u algoritmu koji bi morao biti cisto cjelobrojni, sto znaci da bi morao imati pouzdano tocan rezultat i ne bi smio pogubiti niti jednu jedinu znamenku.

Problem 2:

Sto se dogadja u bazama vecim od 10?

Recimo, neka je baza b = 16. "Pretvorimo" li brojeve 11 i 17, dobit cemo identican rezultat: 11. To znaci da negdje dolazi do neke ozbiljne greske, jer ne mogu dva razlicita broja imati jednak zapis. Naravno, stvar je u tome da 11 treba postati B, no takva dekadska znamenka ne postoji, pa "pretvaranje" ispada potpuno pogresno.

Zakljucak

Nikad, ali stvarno NIKAD, nemojte "pretvarati" broj iz jedne baze u drugu. Ako se trazi nesto sa zapisom broja u bazi, dijelite broj s bazom i racunajte znamenke. Ako treba, i nekoliko puta u programu, ali nemojte "pretvarati" samo zato da bi u vecem dijelu programa imali dijeljenje s 10 umjesto s b, jer je to jednostavno pogresno.

Ako na nekom kolokviju/ispitu negdje napravite "pretvaranje", ispitivac ima puno pravo samo prekriziti rjesenje kao krivo, bez da uopce gleda sto pise iza tog "pretvaranja".



Forum@DeGiorgi -> Programiranje 1 i 2


output generated using printer-friendly topic mod. Vremenska zona: GMT + 01:00.

Stranica 1 / 1.

Powered by phpBB © 2001,2002 phpBB Group
Theme created by Vjacheslav Trushkin