Modulo v programovacích jazycích

PHP, JavaScript

Modulo, neboli zbytek po dělení, známe ne ZŠ všichni. V programovacích jazycích nás ale může překvapit jeho chování při záporných číslech. Podíváme se, které jazyky jak modulo počítají, a jak to využít, či nevyužít ve svůj prospěch.

Modulo v programovacích jazycích

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