Modulový provoz - Modulo operation

v výpočetní, modulo provoz vrátí zbytek nebo podepsaný zbytek a divize, poté, co je jedno číslo rozděleno jiným (nazývá se modul operace).
Vzhledem k tomu, dvě kladná čísla A a n, A modulo n (ve zkratce A mod n) je zbývající část Euklidovské dělení z A podle n, kde A je dividenda a n je dělitel.[1] Modulární provoz je třeba odlišit od symbolu mod, který odkazuje na modul[2] (nebo dělitel) jeden operuje z.
Například výraz „5 mod 2“ by se vyhodnotil na 1, protože 5 dělený 2 má a kvocient 2 a zbytek 1, zatímco „9 mod 3“ by se vyhodnotil jako 0, protože dělení 9 na 3 má podíl 3 a zbytek 0; po trojnásobném vynásobení 3 není co odečíst od 9.
(Zde si všimněte, že dělení s kalkulačkou neukáže výsledek operace modulo a že podíl bude vyjádřen jako desetinný zlomek, pokud se jedná o nenulový zbytek.)
Ačkoli se obvykle provádí s A a n oba jsou celá čísla, mnoho výpočetních systémů nyní umožňuje jiné typy numerických operandů. Rozsah čísel pro celé číslo modulo z n je 0 až n − 1 včetně (A mod 1 je vždy 0; A mod 0 není definováno, což může mít za následek a dělení nulou chyba v některých programovacích jazycích). Vidět modulární aritmetika pro starší a související konvenci použitou v teorie čísel.
Když přesně jeden z A nebo n je negativní, naivní definice se rozpadá a programovací jazyky se liší v tom, jak jsou tyto hodnoty definovány.
Varianty definice
v matematika, výsledek modulo provoz je třída ekvivalence, a kterýkoli člen třídy může být vybrán jako reprezentativní; obvyklým zástupcem je však nejméně pozitivní rezidua, nejmenší nezáporné celé číslo, které patří do dané třídy (tj. zbytek Euklidovské dělení ).[3] Jsou však možné i jiné konvence. Počítače a kalkulačky mají různé způsoby ukládání a reprezentace čísel; tedy jejich definice činnosti modulo závisí na programovací jazyk nebo podkladový Hardware.
Téměř ve všech výpočetních systémech kvocient q a zbytek r z A děleno n splňují následující podmínky:
(1)
To však stále ponechává nejednoznačnost znaménka, pokud je zbytek nenulový: nastanou dvě možné volby pro zbytek, jedna negativní a druhá pozitivní a dvě možné volby pro kvocient. V teorii čísel je vždy kladný zbytek zvolen, ale ve výpočetní technice si programovací jazyky vybírají v závislosti na jazyku a znakech A nebo n.[1] Standard Pascal a ALGOL 68 například dejte kladný zbytek (nebo 0) i pro záporné dělitele a některé programovací jazyky, například C90, to nechají na implementaci, když některý z n nebo A je záporné (viz tabulka níže) § V programovacích jazycích pro detaily). A modulo 0 je ve většině systémů nedefinováno, i když některé jej definují jako A.
- Mnoho implementací používá zkrácené rozdělení, kde je kvocient definován zkrácení q = trunc (A/n) a tedy podle rovnice (1) zbytek by měl stejné znaménko jako dividenda. Kvocient je zaokrouhlen směrem k nule: roven prvnímu celému číslu ve směru nula od přesného racionálního kvocientu.
- Donald Knuth[4] popsáno podlahové dělení kde je kvocient definován funkce podlahy q = ⌊A/n⌋ a tedy podle rovnice (1) zbytek by měl stejné znamení jako dělitel. Kvůli funkci podlahy je kvocient vždy zaokrouhlený dolů, i když je již záporný.
- Raymond T. Boute[5] popisuje euklidovskou definici, ve které je zbytek vždy nezáporný, 0 ≤ r, a je tedy v souladu s Euklidovské dělení algoritmus. V tomto případě,
nebo ekvivalentně
kde sgn je znaková funkce, a tudíž
- Common Lisp také definuje kruhové dělení a stropní dělení, kde je kvocient dán q = kulatý (A/n) a q = ⌈A/n⌉ resp.
- IEEE 754 definuje funkci zbytku, kde je kvocient A/n zaokrouhleno podle zaokrouhlit na nejbližší konvenci. Znamení zbytku je tedy vyvoleno nejblíže nule.
Jak popsal Leijen,
Boute tvrdí, že euklidovské dělení je lepší než ostatní, pokud jde o pravidelnost a užitečné matematické vlastnosti, ačkoli podlahové dělení podporované Knuthem je také dobrou definicí. Přes jeho široké použití se ukázalo, že zkrácené rozdělení je horší než ostatní definice.
— Daan Leijen, Divize a modul pro počítačové vědce[6]
Běžné úskalí
Pokud má výsledek operace modulo známky dividendy, může to vést k překvapivým chybám.
Chcete-li například otestovat, zda je celé číslo liché, můžete chtít otestovat, zda se zbytek o 2 rovná 1:
bool is_odd(int n) { vrátit se n % 2 == 1;}
Ale v jazyce, kde má modulo znak dividendy, je to nesprávné, protože kdy n (dividenda) je záporná a lichá, n mod 2 vrátí -1 a funkce vrátí false.
Jedna správná alternativa je otestovat, že zbytek není 0 (protože zbytek 0 je stejný bez ohledu na znaky):
bool is_odd(int n) { vrátit se n % 2 != 0;}
Jinou alternativou je použití skutečnosti, že u libovolného lichého čísla může být zbytek buď 1 nebo -1:
bool is_odd(int n) { vrátit se n % 2 == 1 || n % 2 == -1;}
Zápis
Některé kalkulačky mají a mod () funkční tlačítko a mnoho programovacích jazyků má podobnou funkci vyjádřenou jako mod (A, n), například. Některé také podporují výrazy, které používají "%", "mod" nebo "Mod" jako modulo nebo zbytek operátor, jako
a% n
nebo
mod n
nebo ekvivalent, pro prostředí bez a mod () function ('int' inherentně produkuje zkrácenou hodnotu A/n)
a - (n * int (a / n))
Problémy s výkonem
Modulové operace mohou být implementovány tak, že se pokaždé vypočítá rozdělení se zbytkem. Ve zvláštních případech existují na určitém hardwaru rychlejší alternativy. Například modulo mocnin 2 lze alternativně vyjádřit jako a bitový Provoz AND:
x% 2n == x & (2n - 1)
Příklady (za předpokladu X je kladné celé číslo):
x% 2 == x & 1
x% 4 == x & 3
x% 8 == x & 7
V zařízeních a softwaru, které implementují bitové operace efektivněji než modulo, mohou tyto alternativní formy vést k rychlejším výpočtům.[7]
Optimalizace překladače může rozpoznat výrazy formuláře výraz% konstanta
kde konstantní
je síla dvou a automaticky je implementuje jako výraz & (konstanta-1)
, což umožňuje programátorovi psát jasnější kód bez snížení výkonu. Tato jednoduchá optimalizace není možná pro jazyky, ve kterých má výsledek operace modulo znak dividendy (včetně C), pokud není dividenda nepodepsaný celočíselný typ. Je to proto, že pokud je dividenda záporná, modulo bude záporné, zatímco výraz & (konstanta-1)
bude vždy pozitivní. U těchto jazyků rovnocennost x% 2n == x <0? x | ~ (2n - 1): x & (2n - 1)
místo toho musí být použito, vyjádřeno bitovými operacemi OR, NOT a AND.
Vlastnosti (identity)
Některé modulo operace lze započítat nebo rozšířit podobně jako jiné matematické operace. To může být užitečné v kryptografie důkazy, například Výměna klíčů Diffie – Hellman.
- Identita:
- (A mod n) mod n = A mod n.
- nX mod n = 0 pro všechny kladné celočíselné hodnoty X.
- Li str je prvočíslo což není a dělitel z b, pak abstr−1 mod str = A mod str, kvůli Fermatova malá věta.
- Inverzní:
- [(−A mod n) + (A mod n)] mod n = 0.
- b−1 mod n označuje modulární multiplikativní inverzní, který je definován právě tehdy b a n jsou relativně prime, což je případ, kdy je definována levá strana: [(b−1 mod n)(b mod n)] mod n = 1.
- Distribuční:
- (A + b) mod n = [(A mod n) + (b mod n)] mod n.
- ab mod n = [(A mod n)(b mod n)] mod n.
- Rozdělení (definice): A/b mod n = [(A mod n)(b−1 mod n)] mod n, když je definována pravá strana (tj b a n jsou coprime ). Nedefinováno jinak.
- Inverzní násobení: [(ab mod n)(b−1 mod n)] mod n = A mod n.
V programovacích jazycích
Jazyk | Operátor | Výsledek má stejné znaménko jako |
---|---|---|
ABAP | MOD | Nezáporné vždy |
ActionScript | % | Dividenda |
Ada | mod | Dělitel |
rem | Dividenda | |
ALGOL 68 | ÷× , mod | Nezáporné vždy |
AMPL | mod | Dividenda |
APL | | [2] | Dělitel |
AppleScript | mod | Dividenda |
AutoLISP | (rem d n) | Dividenda |
AWK | % | Dividenda |
ZÁKLADNÍ | Mod | Nedefinováno |
bash | % | Dividenda |
před naším letopočtem | % | Dividenda |
C (ISO 1990) | % | Definováno implementací |
div | Dividenda | |
C ++ (ISO 1998) | % | Definováno implementací[8] |
div | Dividenda | |
C (ISO 1999) | % , div | Dividenda[9] |
C ++ (ISO 2011) | % , div | Dividenda |
C# | % | Dividenda |
Clarione | % | Dividenda |
Čistý | rem | Dividenda |
Clojure | mod | Dělitel |
rem | Dividenda | |
COBOL[3] | FUNKČNÍ MOD | Dělitel |
CoffeeScript | % | Dividenda |
%% | Dělitel[10] | |
Studená fúze | % , MOD | Dividenda |
Společný Lisp | mod | Dělitel |
rem | Dividenda | |
Krystal | % | Dividenda |
D | % | Dividenda[11] |
Šipka | % | Nezáporné vždy |
zbytek() | Dividenda | |
Eiffelova | \\ | Dividenda |
Elixír | rem | Dividenda |
Jilm | modBy | Dělitel |
zbytekBy | Dividenda | |
Erlang | rem | Dividenda |
Euforie | mod | Dělitel |
zbytek | Dividenda | |
F# | % | Dividenda |
Faktor | mod | Dividenda |
FileMaker | Mod | Dělitel |
Forth | mod | implementace definována |
fm / mod | Dělitel | |
sm / rem | Dividenda | |
Fortran | mod | Dividenda |
modulo | Dělitel | |
Frink | mod | Dělitel |
Studio GameMaker (GML) | mod , % | Dividenda |
GDScript | % | Dividenda |
Jít | % | Dividenda |
Báječný | % | Dividenda |
Haskell | mod | Dělitel |
rem | Dividenda | |
Haxe | % | Dividenda |
J | | [4] | Dělitel |
Jáva | % | Dividenda |
Math.floorMod | Dělitel | |
JavaScript | % | Dividenda |
Julie | mod | Dělitel |
% , rem | Dividenda | |
Kotlin | % , rem | Dividenda |
ksh | % | Dividenda |
LabVIEW | mod | Dividenda |
LibreOffice | = MOD () | Dělitel |
Logo | MODULO | Dělitel |
ZBYTEK | Dividenda | |
Lua 5 | % | Dělitel |
Lua 4 | mod (x, y) | Dělitel |
Liberty BASIC | MOD | Dividenda |
Mathcad | mod (x, y) | Dělitel |
Javor | e mod m | Nezáporné vždy |
Mathematica | Mod [a, b] | Dělitel |
MATLAB | mod | Dělitel |
rem | Dividenda | |
Maxima | mod | Dělitel |
zbytek | Dividenda | |
Vložený jazyk Maya | % | Dividenda |
Microsoft Excel | = MOD () | Dělitel |
Minitab | MOD | Dělitel |
mksh | % | Dividenda |
Modula-2 | MOD | Dělitel |
REM | Dividenda | |
PŘÍUŠNICE | # | Dělitel |
Netwide Assembler (NASM, NASMX ) | % , div | Operátor Modulo nepodepsaný |
%% | Podepsán operátor Modulo | |
Nim | mod | Dividenda |
Oberon | MOD | Dělitel[5] |
Cíl-C | % | Dividenda |
Objekt Pascal, Delphi | mod | Dividenda |
OCaml | mod | Dividenda |
Occam | \ | Dividenda |
Pascal (ISO-7185 a -10206) | mod | Nezáporné vždy[6] |
Programovací kód Advanced (PCA ) | \ | Nedefinováno |
Perl | % | Dělitel[7] |
Phix | mod | Dělitel |
zbytek | Dividenda | |
PHP | % | Dividenda |
OBR ZÁKLADNÍ Pro | \\ | Dividenda |
PL / I. | mod | Dělitel (ANSI PL / I) |
PowerShell | % | Dividenda |
Programovací kód (PRC ) | MATH.OP - 'MOD; () ' | Nedefinováno |
Pokrok | modulo | Dividenda |
Prolog (Já SO 1995 ) | mod | Dělitel |
rem | Dividenda | |
PureBasic | % , Mod (x, y) | Dividenda |
PureScript | `mod` | Dělitel |
Krajta | % | Dělitel |
Q # | % | Dividenda[12] |
R | %% | Dělitel |
RealBasic | MOD | Dividenda |
Důvod | mod | Dividenda |
Raketa | modulo | Dělitel |
zbytek | Dividenda | |
Rexx | // | Dividenda |
RPG | % REM | Dividenda |
Rubín | % , modulo () | Dělitel |
zbytek() | Dividenda | |
Rez | % | Dividenda |
rem_euclid () | Dělitel | |
SAS | MOD | Dividenda |
Scala | % | Dividenda |
Systém | modulo | Dělitel |
zbytek | Dividenda | |
Systém R6RS | mod | Nezáporné vždy[13] |
mod0 | Nejbližší k nule[13] | |
Poškrábat | mod | Dělitel |
7. semeno | mod | Dělitel |
rem | Dividenda | |
SenseTalk | modulo | Dělitel |
rem | Dividenda | |
Shell | % | Dividenda |
Pokec | \\ | Dělitel |
rem: | Dividenda | |
Snap! | mod | Dělitel |
Roztočit | // | Dělitel |
Pevnost | % | Dělitel |
SQL (SQL: 1999 ) | mod (x, y) | Dividenda |
SQL (SQL: 2011 ) | % | Dividenda |
Standardní ML | mod | Dělitel |
Int.rem | Dividenda | |
Stata | mod (x, y) | Nezáporné vždy |
Rychlý | % | Dividenda |
Tcl | % | Dělitel |
Strojopis | % | Dividenda |
Točivý moment | % | Dividenda |
Turing | mod | Dělitel |
Verilog (2001) | % | Dividenda |
VHDL | mod | Dělitel |
rem | Dividenda | |
VimL | % | Dividenda |
Visual Basic | Mod | Dividenda |
WebAssembly | i32.rem_s , i64.rem_s | Dividenda |
Sestava x86 | IDIV | Dividenda |
XBase ++ | % | Dividenda |
Mod () | Dělitel | |
Z3 věta prover | div , mod | Nezáporné vždy |
Jazyk | Operátor | Výsledek má stejné znaménko jako |
---|---|---|
ABAP | MOD | Nezáporné vždy |
C (ISO 1990) | fmod | Dividenda[14] |
C (ISO 1999) | fmod | Dividenda |
zbytek | Nejbližší k nule | |
C ++ (ISO 1998) | std :: fmod | Dividenda |
C ++ (ISO 2011) | std :: fmod | Dividenda |
std :: zbytek | Nejbližší k nule | |
C# | % | Dividenda |
Společný Lisp | mod | Dělitel |
rem | Dividenda | |
D | % | Dividenda |
Šipka | % | Nezáporné vždy |
zbytek() | Dividenda | |
F# | % | Dividenda |
Fortran | mod | Dividenda |
modulo | Dělitel | |
Jít | matematika. mod | Dividenda |
Haskell (GHC) | Data.Fixed.mod ' | Dělitel |
Jáva | % | Dividenda |
JavaScript | % | Dividenda |
ksh | fmod | Dividenda |
LabVIEW | mod | Dividenda |
Microsoft Excel | = MOD () | Dělitel |
OCaml | mod_float | Dividenda |
Perl | POSIX :: fmod | Dividenda |
Raku | % | Dělitel |
PHP | fmod | Dividenda |
Krajta | % | Dělitel |
math.fmod | Dividenda | |
Rexx | // | Dividenda |
Rubín | % , modulo () | Dělitel |
zbytek() | Dividenda | |
Rez | % | Dividenda |
rem_euclid () | Dělitel | |
Systém R6RS | flmod | Nezáporné vždy |
flmod0 | Nejbližší k nule | |
Poškrábat | mod | Dividenda |
Standardní ML | Real.rem | Dividenda |
Rychlý | truncatingRemainder (dividingBy :) | Dividenda |
XBase ++ | % | Dividenda |
Mod () | Dělitel |
Zobecnění
Modulo s offsetem
Někdy je to užitečné pro výsledek A modulo n ležet ne mezi 0 a n−1, ale mezi nějakým číslem d a d+n−1. V tom případě, d se nazývá offset. Nezdá se, že by pro tuto operaci existoval standardní notový zápis, takže pokusně použijeme A modd n. Máme tedy následující definici:[15] X = A modd n jen pro případ d ≤ X ≤ d+n−1 a X mod n = A mod n. Je zřejmé, že obvyklá modulo operace odpovídá nulovému offsetu: A mod n = A mod0 n. Provoz modulo s offsetem souvisí s funkce podlahy jak následuje:
- A modd n = .
(To je snadno vidět . Nejprve to ukážeme X mod n = A mod n. Obecně platí, že (A+bn) mod n = A mod n pro všechna celá čísla b; to tedy platí i v konkrétním případě, kdy b = ; ale to znamená, že , což jsme chtěli dokázat. Zbývá ukázat, že d ≤ X ≤ d+n−1. Nechat k a r být taková celá čísla A − d = kn + r s 0 ≤ r ≤ n-1 (vidět Euklidovské dělení ). Pak , tím pádem . Nyní vezměte 0 ≤ r ≤ n−1 a přidat d na obě strany, získání d ≤ d + r ≤ d+n−1. Ale viděli jsme to X = d + r, takže jsme hotovi. □)
Modulo s offsetem A modd n je implementováno v Mathematica tak jako[15] Mod [a, n, d]
.
Viz také
- Modulo (disambiguation) a modulo (žargon) - mnoho použití slova modulo, z nichž všechny vyrostly Carl F. Gauss Úvod do modulární aritmetika v roce 1801.
- Modulo (matematika), obecné použití termínu v matematice
- Modulární umocňování
- Turn (jednotka)
Poznámky
- ^ Perl obvykle používá aritmetický modulo operátor, který je nezávislý na stroji. Příklady a výjimky najdete v dokumentaci Perl o multiplikativních operátorech.[16]
- ^ Matematicky jsou tyto dvě možnosti pouze dvěma z nekonečného počtu možností, které jsou k dispozici nerovnost uspokojena zbytkem.
- ^ Dělitel musí být kladný, jinak nedefinovaný.
- ^ Jak je implementováno v ACUCOBOL, Micro Focus COBOL a dalších možných.
- ^ ^ Pořadí argumentů se obrací, tj.
α | ω
počítá , zbytek při děleníω
podleα
. - ^ Jak popisuje Boute, definice ISO Pascal
div
amod
neposlouchejte identitu divize, a jsou tedy zásadně rozbití.
Reference
- ^ „Definitivní glosář vyššího matematického žargonu: Modulo“. Matematický trezor. 2019-08-01. Citováno 2020-08-27.
- ^ Weisstein, Eric W. "Shoda". mathworld.wolfram.com. Citováno 2020-08-27.
- ^ Caldwell, Chris. "zbytek". Hlavní glosář. Citováno 27. srpna 2020.
- ^ Knuth, Donald. E. (1972). Umění počítačového programování. Addison-Wesley.
- ^ Boute, Raymond T. (duben 1992). „Euklidovská definice funkcí div a mod“. Transakce ACM v programovacích jazycích a systémech. ACM Press (New York, NY, USA). 14 (2): 127–144. doi:10.1145/128861.128862. hdl:1854 / LU-314490.
- ^ Leijen, Daan (3. prosince 2001). „Divize a modul pro počítačové vědce“ (PDF). Citováno 2014-12-25.
- ^ Horvath, Adam (5. července 2012). „Rychlejší dělení a modulo provoz - síla dvou“.
- ^ „ISO / IEC 14882: 2003: Programming languages - C ++“. Mezinárodní organizace pro normalizaci (ISO), Mezinárodní elektrotechnická komise (IEC). 2003. s 5.6.4.
binární% operátor získá zbytek z dělení prvního výrazu druhým. .... Pokud jsou oba operandy nezáporné, zbytek je nezáporný; pokud ne, znaménko zbytku je definováno implementací
Citovat deník vyžaduje| deník =
(Pomoc) - ^ „Specifikace C99 (ISO / IEC 9899: TC2)“ (PDF). 6. května 2005. sek. 6.5.5 Multiplikativní operátoři. Citováno 16. srpna 2018.
- ^ Operátoři CoffeeScript
- ^ „Výrazy“. D Programovací jazyk 2.0. Digitální Mars. Citováno 29. července 2010.
- ^ QuantumWriter. „Výrazy“. docs.microsoft.com. Citováno 2018-07-11.
- ^ A b r6rs.org
- ^ „ISO / IEC 9899: 1990: Programming languages - C“. ISO, IEC. 1990. sek. 7.5.6.4.
The
Citovat deník vyžadujefmod
funkce vrací hodnotux - i * y
, pro celé čísloi
takové, pokudy
je nenulová, výsledek jako stejné znaménko jakoX
a velikost menší než velikosty
.| deník =
(Pomoc) - ^ A b "Mod". Centrum jazykové a systémové dokumentace Wolfram. Wolfram Research. 2020. Citováno 8. dubna 2020.
- ^ Perl dokumentace
externí odkazy
- Modulorama, animace cyklické reprezentace multiplikačních tabulek (vysvětlení ve francouzštině)