Číselná soustava je způsob zápisu numerických hodnot. V běžném životě se setkáme především s desítkovou soustavou, ale tato soustava není vhodná pro všeobecné použití. Jako příklad poslouží elektrické vedení, ve kterém je výrazně snazší detekovat jestli teče/neteče proud, než 10 hodnot napětí na vodiči.
Při zápisu čísel se využívá termínu základ pro počet hodnot, kterých může nabývat cifra v dané soustavě.
Základ 2 – dvojková (binární) soustava – 0, 1
Základ 8 – osmičková (oktalová) soustava – 0, 1, 2, 3, 4, 5, 6, 7
Základ 16 – šestnáctková (hexadecimální) - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F
Číselných soustav (základů) je samozřejmě nekonečně mnoho, ale toto jsou soustavy, které asi potkáte nejčastěji. Za připomínku možná ještě stojí, že základ soustavy je první číslo, které se už v soustavě nevyskytuje (v desítkové není 10, ve dvojkové 2...), protože se počítá od nuly. Pokud má soustava základ vyšší než 10, tak je zvykem nahrazovat číslice, které jsou větší nebo rovno 10, písmeny (viz šestnáctková soustava).
Zápis do soustavy
Nyní k samotnému zápisu do soustavy. Pro ten se využívá následujícího rozkladu:
kde je základ a jsou čísla menší než základ.
Sice to vypadá na první pohled poněkud děsivě, ale ve skutečnosti je to poměrně jednoduché. Demonstrujme si tento vzorec na příkladu v desítkové soustavě.
Pokud by nás zajímalo číslo 73 ve dvojkové soustavě.
Podíváme-li se podrobněji například na číslo 4567, tak vidíme, že 7 je zbytek po dělení čísla 4567 deseti, 60 je zbytek po dělení čísla 4567 stem (po zarovnání čísla na jednotkovém místě na 0), 500 tisícem, 4000 desetitisícem...a takto to funguje v každém čísle v každé soustavě. Této vlastnosti se využívá při převodu čísla ze soustavy s vyšším základem do soustavy se základem nižším.
Převod ze soustavy s vyšším základem
Převádíme-li ze soustavy s vyšším základem do soustavy se základem nižším, pak obvykle používáme algoritmus zapisování zbytků po dělení.
Příklad:
73 v desítkové soustavě chceme převést do dvojkové soustavy.
// zbytek na 2. místě odzadu
// zbytek na 3. místě odzadu
// zbytek na 4. místě odzadu
// zbytek na 5. místě odzadu
// zbytek na 6. místě odzadu
// zbytek na 7. místě odzadu
Výsledek je (zdola nahoru) 10010012.
Trochu jiný zápis toho samého:
//zbytek 1 jsme již zahrnuli v předchozím kroku
//zbytek byl zahrnut v prvním kroku
//zbytek se zvýšil o 8, což je 23, na 4. místě od konce čísla (tomto místě) je 1
//zbytek se nemění
//zbytek se nemění
//zbytek se zvýšil 0 64, což je 26, na 7. místě od konce čísla (tomto místě) je 1
Celé číslo již bylo zahrnuto do zbytků po dělení je převedeno. Výsledek je (čteno zdola nahoru) .
Převod ze soustavy s nižším základem
Převod ze soustavy s nižším základem do soustavy s vyšším základem je snazší. Víme totiž, že číslice na n-tém místě (počítáno od 0) reprezentuje číslo vzniklé umocněním základu na n-tou. Tyto čísla posčítáme a máme převedeno.
Příklad:
10010012 do desítkové soustavy
Převod mezi příbuznými soustavami
Přechozí postupy mají tu nevýhodu, že je s nimi velmi nepohodlné počítat převody například z dvojkové do šestnáctkové soustavy (nejsme zvyklí počítat ani v jedné ze soustav, proto se často počítá převod z dvojkové do desítkové a z desítkové do šestnáctkové). Mezi soustavami, kde je základ jedné soustavy mocninou základu jiné soustavy, se dá převádět jednodušeji.
Pokud máme soustavu X, jejíž základ je n-tou mocninou základu soustavy Y, pak každá číslice soustavy X je reprezentována právě n číslicemi v soustavě Y. Máme-li například šestnáctkovou a dvojkovou soustavu, pak každá číslice šestnáctkové soustavy je ve dvojkové soustavě reprezentována čtyřmi číslicemi (a naopak). Převod pak provádíme po daném počtu číslic. Tento postup je obzvláště užitečný v informatice, kde se setkáváme hlavně s dvojkovou, osmičkovou a šestnáctkovou soustavou (vše mocniny čísla 2).
Příklad
Převeďte číslo do šestnáctkové soustavy.
Nyní provedeme samotný převod:
Výsledek:
Kód
/** * Prevede cislo mezi dvemi soustavami * @param baseFrom soustava, ve ktere je cislo uvedene * @param baseTo soustava, do ktere cislo prevadime * @param number cislo k prevodu 0-9, A-Z * @return cislo prevedene do zadane soustavy * @throws java.lang.IllegalArgumentException pokud ma kterakoliv ze soustav * bazi nizsi nez 2 nebo vyssi nez 36 */ public static String convert(int baseFrom, int baseTo, String number) throws IllegalArgumentException{ return convertFromDecimal(baseTo, convertToDecimal(baseFrom, number)); } /** * Provede prevod ze zadane soustavy do desitkove, zadana soustava je * reprezentovana pomoci cisel 0-9, a pismen A-Z, soustavy se zakladem * vyssim nez 36 nejsou podporovany * @param base zaklad soustavy * @param number cislo k prevedeni * @return cislo v desitkove soustave * @throws java.lang.IllegalArgumentException v pripade soustavy nizsi 2 a vyssi 36 */ public static int convertToDecimal(int base, String number) throws IllegalArgumentException{ if(base < 2 || base > 36) throw new IllegalArgumentException("Neplatna soustava: " + base); int result = 0; //vysledek int position = 0; //kolikate misto odzadu pocitame for(int i = number.length() - 1; i >= 0; i--){ int numeral = convertToInt(number.charAt(i)); if(numeral >= base) throw new IllegalArgumentException("Neplatna soustava"); result += numeral * Math.pow(base, position); //prevod cislice na odpovidajici pozici position++;// posun pozice } return result; } /** * Prevede cislo z desitkove soustavy do nejake jine * @param base zaklad soustavy do ktere prevadime * @param number desitkove cislo k prevodu * @return prevede cislo jako retezec 0-9 A-Z * @throws java.lang.IllegalArgumentException pokud je zaklad soustavy * mensi 2 nebo vyssi nez 36 */ public static String convertFromDecimal(int base, int number) throws IllegalArgumentException{ if(base < 2 || base > 36) throw new IllegalArgumentException("Neplatna soustava: " + base); String result = ""; while(number != 0){ int remainder = number % base; //zjisteni zbytku (hodnoty na odpovidajici pozici) number = number / base; //posun o pozici dal result = convertToNumeral(remainder) + result; } return result; } /** * Prevede ASCII znak reprezentujici cislici soustavy na integer * @param charAt 0-9 A-Z * @return cislo v desitkove soustave odpovidajici hodnote cislice */ private static int convertToInt(char charAt) { if(charAt >= 48 && charAt <= 57) return charAt - 48; else if(charAt >= 65 && charAt <= 90) return charAt - 65 + 10;//0-9 jsou cisla throw new IllegalArgumentException("Cislice neni 0-9 A-Z"); } /** * Prevede cislici na odpovidajici znak * @param remainder cislice 0-35 * @return cislice prevedena na 0-9 A-Z */ private static char convertToNumeral(int numeral) { if(numeral >= 0 && numeral < 10) return (char)(48 + numeral); else if(numeral >= 10 && numeral <= 35) return (char)(65 + numeral - 10); throw new IllegalArgumentException("Neni cislice 0-35"); }