Když vám někdo řekne, vyděl mi se zbytkem 46 / 5, asi každý řekne 9 zbytek 1. Pokud toto zadáme v libovolném jazyce, výsledek nás asi nepřekvapí. Pokud ale řekne -46 / 5? A zde se to zamotá, některé jazyky nám vypíší zbytek -1 některé 4.
Nápad na napsání tohoto článku mě přivedl jiný článek na JeČas.cz, kde se rozebíralo, jak procházet pole i za jeho hranice. Zde nám počítání modulu trochu komplikuje práci.
Mocná zbraň - modulo
Zbytek při dělení se v nejen v počítačové vědě využívá pořád. Součet číslic rodného čísla od roku 1953 je vždy dělitelný 11 beze zbytku. Distribuce klíčů v šifrování AES používá modulo, kontrolní součet CRC zmíněný u čárových kódů rovněž používá modulo. Nejznámější je však zjištění sudého či lichého čísla.
Pokud v programovacích jazycích a programech bude dělenec i dělitel kladný, výsledky se budou shodovat. Pokud je jeden z nich však záporný, nastávají rozdíly. Podívejme se na tabulku.
9 % 5 | -9 % 5 | 9 % -5 | -9 % -5 | |
---|---|---|---|---|
PHP | 4 | -4 | 4 | -4 |
JavaScript | 4 | -4 | 4 | -4 |
Java | 4 | -4 | 4 | -4 |
Python | 4 | 1 | -1 | -4 |
MySQL | 4 | -4 | 4 | -4 |
MS Excel | 4 | 1 | -1 | -4 |
WolframAlpha | 4 | 1 | -1 | -4 |
Cestování polem přes okraje
Jsme v poli o délce 5 na pozici 2 (číslujeme od 0) a chceme se posunout o 4 prvky zpět. Očekávaná pozice bude tedy 3, ovšem po výpočtu nám vyjde -2 % 5 = -2, i když chceme 3.
Řešení
Nemusíme ale zoufat, řešení je velmi jednoduché! V některých jazycích je pro nás funkce již připravená, pro jiné ji stačí si napsat. Z výše zmíněné tabulky v Pythonu, MS Excelu a WolframAplha má výsledek shodné znaménko jako dělitel, v ostatních jako dělenec.
Na anglické Wiki je seznam velkého množství jazyků a programů a styl počítání modulu.
Java
V Javě je pro nás připravena funkce Math.floorMod().
PHP, JavaScript, C#
Implementace vlastní funkce je jednoduchá, pro desetinná čísla však nefunguje. Pro celá ale funguje správně, což by mělo vyřešit náš problém.
//PHP function floorMod($divident,$divisor) { return $divident - floor($divident / $divisor) * $divisor; }
//JavaScript function floorMod(divident, divisor) { return divident - Math.floor(divident / divisor) * divisor; }
//C# static int floorMod(int divident, int divisor) { return divident - (int)Math.Floor(divident / (float)divisor) * divisor; }
K tomuto článku již není možné přidávat další komentáře