Čí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.
Výsledek je (zdola nahoru) 10010012.
Trochu jiný zápis toho samého:
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
01.
/**
02.
* Prevede cislo mezi dvemi soustavami
03.
* @param baseFrom soustava, ve ktere je cislo uvedene
04.
* @param baseTo soustava, do ktere cislo prevadime
05.
* @param number cislo k prevodu 0-9, A-Z
06.
* @return cislo prevedene do zadane soustavy
07.
* @throws java.lang.IllegalArgumentException pokud ma kterakoliv ze soustav
08.
* bazi nizsi nez 2 nebo vyssi nez 36
09.
*/
10.
public
static
String convert(
int
baseFrom,
int
baseTo, String number)
throws
IllegalArgumentException{
11.
return
convertFromDecimal(baseTo, convertToDecimal(baseFrom, number));
12.
}
13.
/**
14.
* Provede prevod ze zadane soustavy do desitkove, zadana soustava je
15.
* reprezentovana pomoci cisel 0-9, a pismen A-Z, soustavy se zakladem
16.
* vyssim nez 36 nejsou podporovany
17.
* @param base zaklad soustavy
18.
* @param number cislo k prevedeni
19.
* @return cislo v desitkove soustave
20.
* @throws java.lang.IllegalArgumentException v pripade soustavy nizsi 2 a vyssi 36
21.
*/
22.
public
static
int
convertToDecimal(
int
base, String number)
throws
IllegalArgumentException{
23.
if
(base <
2
|| base >
36
)
throw
new
IllegalArgumentException(
"Neplatna soustava: "
+ base);
24.
int
result =
0
;
//vysledek
25.
int
position =
0
;
//kolikate misto odzadu pocitame
26.
for
(
int
i = number.length() -
1
; i >=
0
; i--){
27.
int
numeral = convertToInt(number.charAt(i));
28.
if
(numeral >= base)
throw
new
IllegalArgumentException(
"Neplatna soustava"
);
29.
result += numeral * Math.pow(base, position);
//prevod cislice na odpovidajici pozici
30.
position++;
// posun pozice
31.
}
32.
return
result;
33.
}
34.
/**
35.
* Prevede cislo z desitkove soustavy do nejake jine
36.
* @param base zaklad soustavy do ktere prevadime
37.
* @param number desitkove cislo k prevodu
38.
* @return prevede cislo jako retezec 0-9 A-Z
39.
* @throws java.lang.IllegalArgumentException pokud je zaklad soustavy
40.
* mensi 2 nebo vyssi nez 36
41.
*/
42.
public
static
String convertFromDecimal(
int
base,
int
number)
throws
IllegalArgumentException{
43.
if
(base <
2
|| base >
36
)
throw
new
IllegalArgumentException(
"Neplatna soustava: "
+ base);
44.
String result =
""
;
45.
while
(number !=
0
){
46.
int
remainder = number % base;
//zjisteni zbytku (hodnoty na odpovidajici pozici)
47.
number = number / base;
//posun o pozici dal
48.
result = convertToNumeral(remainder) + result;
49.
}
50.
return
result;
51.
}
52.
/**
53.
* Prevede ASCII znak reprezentujici cislici soustavy na integer
54.
* @param charAt 0-9 A-Z
55.
* @return cislo v desitkove soustave odpovidajici hodnote cislice
56.
*/
57.
private
static
int
convertToInt(
char
charAt) {
58.
if
(charAt >=
48
&& charAt <=
57
)
return
charAt -
48
;
59.
else
if
(charAt >=
65
&& charAt <=
90
)
return
charAt -
65
+
10
;
//0-9 jsou cisla
60.
throw
new
IllegalArgumentException(
"Cislice neni 0-9 A-Z"
);
61.
62.
}
63.
/**
64.
* Prevede cislici na odpovidajici znak
65.
* @param remainder cislice 0-35
66.
* @return cislice prevedena na 0-9 A-Z
67.
*/
68.
private
static
char
convertToNumeral(
int
numeral) {
69.
if
(numeral >=
0
&& numeral <
10
)
return
(
char
)(
48
+ numeral);
70.
else
if
(numeral >=
10
&& numeral <=
35
)
return
(
char
)(
65
+ numeral -
10
);
71.
throw
new
IllegalArgumentException(
"Neni cislice 0-35"
);
72.
}