Pourquoi le mod (%) est-il un opérateur mathématique fondamental dans de nombreux langages de programmation?


17

Y a-t-il une raison, historique ou autre, pour laquelle l'opérateur de module fait partie d'un petit ensemble d'opérateurs standard dans ce qui semble être de nombreuses langues? ( +, -, *, /et %, pour Java et C, avec **en Ruby et Python).

Il semble étrange d'inclure le mod comme "fondamental" (pour ne pas le frapper, je l'utilise beaucoup, mais j'utilise aussi l'exponentiation, la valeur absolue, le plancher / plafond ou autres - ils semblent tout aussi utiles et nécessaires). Était-ce une vieille décision prise dans une spécification que Java, C, Ruby et Python suivent tous ou un langage dont ils descendent tous? Pour autant que je sache, la plupart des dialectes lisp ne comprennent que +, -, /et *.

Au début, je me demandais si le mod était particulièrement facile à implémenter au niveau binaire (cela ferait-il même une différence en ce qui concerne les décisions sur ce qui devrait être un opérateur "fondamental" et ce qui ne devrait pas?), Mais il ne semble pas l'être. Est-il simplement beaucoup plus couramment utilisé en programmation que je ne le pense?

Réponses:


20

Je suis sûr que c'est courant car de nombreuses architectures CPU implémentent en modulustant que deuxième sortie de l'instruction de division entière.

Je ne me souviens pas qu'il soit présent dans les processeurs des années 1970 (6800, 8080, Z80, 1604, etc.), mais dans les années 1980, les Intel 8086 et 8088, ainsi que le Motorola 6809 l'avaient.

L'architecture d'instructions PDP-11 spécifiait la DIVproduction d'un quotient et d'un reste depuis le début (1970), bien que les instructions MUL et DIV n'étaient pas présentes sur les premières conceptions, mais pouvaient être émulées de manière transparente par une "instruction non implémentée" et implémentée avec un gestionnaire qui a fait un peu de twiddling. La fonctionnalité PDP-11 a probablement encouragé la toute première édition du langage C fournissant la %fonctionnalité. (Avez-vous déjà remarqué comment un signe de pourcentage comporte une barre oblique? Cela en fait un choix intelligent pour un opérateur lié à une division.)

La présence de module à lui Cseul peut probablement expliquer sa présence dans toutes les langues modernes. Ca une très grande famille de descendants et était par ailleurs assez influent.


3
L'influence de +1 C sur à peu près tous les langages non LISP depuis le début des années 1970 ne peut pas être surestimée.
Ross Patterson

8

De nombreux langages de programmation ont un opérateur "restant" qui peut être utilisé comme opérateur de module lorsque les deux opérandes sont positifs; cet opérateur est souvent appelé opérateur "module", car il s'agit de son utilisation principale. Les langages ont généralement un tel opérateur parce que le matériel de division de nombreuses plates-formes matérielles fournit automatiquement un reste lors de l'exécution d'une division, et le calcul d'un reste ou d'un module par tout autre moyen serait beaucoup plus difficile.

Je ne connais pas l'historique du support matériel pour la division signée; de nombreux processeurs fournissent depuis des années du matériel capable d'effectuer automatiquement une division signée, sous réserve que si a / b donne (q, r), alors -a / b ou a / -b produira (-q, -r), mais Je ne suis pas sûr des cas d'utilisation où la division utilisant cette règle est particulièrement utile. Dans presque tous les cas où j'ai utilisé une division entière ou des opérations de "module" sur des valeurs négatives, j'ai voulu arrondir vers l'infini négatif sur la division et une véritable opération de module (telle que (a + b) / b serait toujours égal (a / b) +1 et (a + b)% b serait toujours égal à a% b.). Parce que les opérateurs ne fonctionnent pas de cette façon, il est nécessaire de tester le signe du dividende et d'utiliser un code différent quand il ' s négatif - annulant essentiellement tout avantage d'avoir une instruction de division signée en premier lieu. Je suis curieux de savoir à quelles fins le support de division signée dans le matériel est réellement utile.

Pour revenir à la question d'origine, l'opérateur de module est souvent utile dans des situations où certaines choses sont censées se produire sur une base périodique, soit dans l'espace (par exemple des coordonnées graphiques) ou dans le temps. Par exemple, si l'on veut qu'un événement se produise toutes les 15 secondes, le temps jusqu'au prochain événement sera de 15 - ((time_now - time_of_an_occurrence)% 15), en supposant qu'il time_of_an_occurrencen'est pas supérieur àtime_now . S'il time_of_an_occurrenceétait supérieur à time_now, un opérateur de module pourrait continuer à utiliser la même formule à condition que la soustraction ne déborde pas, mais l'opérateur restant nécessitera une formule différente.


3
Pour cette raison, Haskell a deux opérateurs: rempour le reste et modpour le module avec les propriétés que vous décrivez.
Ingo

@Complicatedseebio: Ce qui est particulièrement drôle, c'est qu'il est souvent appelé l'opérateur de module, car il est généralement utilisé pour calculer le module, même lorsque cela nécessite du code comme m = number % base; if (m < 0) m+=base; . Je ne sais pas si j'ai jamais vu un code qui a bénéficié de l'opérateur restant devenir négatif, sauf peut q = n/d; if (n%d < 0) q+=1;- être , qui pourrait en tout cas être mieux écrit autrement.
supercat

3

Le module est étroitement lié à la théorie des groupes et des anneaux, qui sont des théories mathématiques très fondamentales.

L'exponentiation n'est que la troisième opération dans l'addition de séquence, la multiplication, l'exponentiation, la tétration (et c'est une séquence infinie). Il devient important principalement avec les nombres complexes, qui sont plus rares en arithmétique informatique. Une exponentiation particulière est prise en charge explicitement, cependant: 2 n est couramment écrit comme 1<<n, car les ordinateurs sont assez binaires.

Le sol et le plafond sont vraiment rares en comparaison: ils ne s'appliquent que lors de la conversion de ℝ en ℤ. (virgule flottante en entier). De même, absest associé à un mappage de ℤ à ℕ


ℤ sont les entiers (et ℕ est un sous-ensemble d'entiers), vous devez signifier de ℝ à ℤ.
Joni

@Joni: Mélange de deux exemples, corrigé.
MSalters

0

Désolé, mais au risque de transformer cela en un jeu de "Call My Bluff", je pense que la vraie réponse à cette question est assez simple:

Le mod permet des calculs précis en quantités et unités "non décimales" telles que les dates, l'heure, les verges, les pouces, les onces, etc. Dans les calculs décimaux, il fournit également une méthode permettant au programmeur de travailler avec une précision numérique au-delà de celle fournie par le matériel. de la machine. Cela a un grand nombre d'applications, du très petit (par exemple les calculs quantiques) au très grand (par exemple, la découverte de nouveaux nombres premiers).

Il est important de comprendre que nous avons appelé ces choses ordinateurs pour une raison. Parfois, nous en avons besoin pour nous donner la bonne réponse!


Cette réponse n'a aucun sens ... Quel est le lien entre l'utilisation de "mod" et l'utilisation de différentes unités ???
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.