Por que o mod (%) é um operador matemático fundamental em muitas linguagens de programação?


17

Existe uma razão, histórica ou não, para que o operador de módulo faça parte de um pequeno conjunto de operadores padrão no que parece ser muitos idiomas? ( +, -, *, /e %, para Java e C, com **em Ruby e Python).

Parece estranho incluir mod como um "fundamental" (para não bater, eu uso bastante, mas também uso exponenciação, valor absoluto, piso / teto ou outros - eles parecem tão úteis e necessários). Foi uma decisão antiga tomada em alguma especificação que Java, C, Ruby e Python seguem ou uma linguagem da qual todos descendem? Até onde eu sei, a maioria dos dialetos Lisp inclui apenas +, -, /e *.

No começo, eu me perguntava se o mod era particularmente fácil de implementar no nível binário (isso faria alguma diferença, em relação às decisões sobre o que deveria ser um operador "fundamental" e o que não deveria?), Mas parece não ser. É muito mais comumente usado em programação do que eu acho?

Respostas:


20

Tenho certeza de que isso é comum porque muitas arquiteturas de CPU são implementadas moduluscomo uma segunda saída da instrução de divisão de número inteiro.

Não me lembro de estar presente nas CPUs dos anos 70 (6800, 8080, Z80, 1604 etc.), mas nos anos 80, os Intel 8086 e 8088, assim como o Motorola 6809, possuíam.

A arquitetura de instruções do PDP-11 especificou a DIVprodução de um quociente e um restante desde o início (1970), embora as instruções MUL e DIV não estivessem presentes nos projetos anteriores, mas pudessem ser emuladas de forma transparente por uma "armadilha de instrução não implementada" e implementada com um manipulador que fez um pouco de mexer. Provavelmente, o recurso PDP-11 incentivou a primeira edição da linguagem C que o forneceu %. (Você já reparou como um sinal de porcentagem tem uma barra nele? Isso o torna uma escolha inteligente para um operador relacionado à divisão.)

A presença do módulo por Csi só provavelmente pode explicar sua presença em todas as línguas modernas. Ctem uma família muito grande de descendentes e foi bastante influente.


3
A influência de +1 C em praticamente todas as línguas não-LISP desde o início dos anos 70 não pode ser exagerada.
Ross Patterson

8

Muitas linguagens de programação possuem um operador "restante" que pode ser usado como um operador de módulo quando ambos os operandos são positivos; o referido operador é freqüentemente chamado de operador "módulo", porque esse é seu uso principal. Os idiomas geralmente têm esse operador, porque o hardware de divisão de muitas plataformas de hardware fornece automaticamente um restante ao executar uma divisão, e computar um restante ou módulo por qualquer outro meio seria muito mais difícil.

Não conheço o histórico de suporte de hardware para divisão assinada; muitos processadores fornecem há anos hardware que pode executar automaticamente uma divisão assinada, sujeito à regra de que, se a / b produzir (q, r), -a / b ou a / -b produzirá (-q, -r), mas Não tenho certeza dos casos de uso em que a divisão usando essa regra é particularmente útil. Em quase todos os casos em que usei operações de divisão inteira ou "módulo" em valores negativos, eu queria infinito arredondado em direção ao infinito negativo na divisão e uma verdadeira operação de módulo (de modo que (a + b) / b sempre igual (a / b) +1 e (a + b)% b sempre seria igual a% b.). Como os operadores não funcionam dessa maneira, é necessário testar o sinal do dividendo e usar código diferente quando ele ' s negativo - negando essencialmente qualquer benefício de ter uma instrução de divisão assinada em primeiro lugar. Estou curioso para saber quais propósitos o suporte à divisão de assinaturas no hardware é realmente útil.

Retornando à pergunta original, o operador do módulo é frequentemente útil em situações em que certas coisas devem acontecer periodicamente, no espaço (por exemplo, coordenadas gráficas) ou no tempo. Por exemplo, se alguém deseja que um evento ocorra a cada 15 segundos, o tempo até o próximo evento será 15 - ((time_now - time_of_an_occurrence)% 15), supondo que time_of_an_occurrencenão seja maior quetime_now . Se time_of_an_occurrencefosse maior que time_now, um operador de módulo poderia continuar usando a mesma fórmula, desde que a subtração não transbordasse, mas o operador restante exigirá uma fórmula diferente.


3
Por esse motivo, Haskell possui dois operadores: rempara o restante e modpara o módulo com as propriedades que você descreve.
Ingo

@Complicatedseebio: O que é particularmente engraçado é que muitas vezes é chamado de operador de módulo, porque geralmente é usado para calcular o módulo, mesmo quando isso requer código semelhante m = number % base; if (m < 0) m+=base;. Não sei se já vi algum código que se beneficiou do operador restante ficar negativo, exceto talvez q = n/d; if (n%d < 0) q+=1;, que poderia, em qualquer caso, ser melhor escrito de outras maneiras.
Supercat

3

O módulo está intimamente relacionado à teoria de grupos e anéis, que são teorias matemáticas muito fundamentais.

A exponenciação é apenas a terceira operação na adição, multiplicação, exponenciação, tetragem da sequência (e essa é uma sequência infinita). Torna-se importante principalmente com números complexos, que são mais raros na aritmética computacional. Uma exponenciação específica é suportada explicitamente: 2 n é normalmente escrita como 1<<n, uma vez que os computadores são bastante binários.

O piso e o teto são realmente raros em comparação: eles só se aplicam ao converter de ℝ para ℤ. (ponto flutuante para inteiro). Da mesma forma, absestá associado a um mapeamento de ℤ para ℕ


ℤ são números inteiros (e ℕ é um subconjunto de números inteiros), você deve significar de ℝ a ℤ.
Joni

@ Joni: Misturados dois exemplos, corrigidos.
MSalters

0

Desculpe, mas com o risco de transformar isso em um jogo de "Call My Bluff", acho que a resposta real a esta pergunta é bastante simples:

O Mod permite cálculos precisos em quantidades "não-decimais" e unidades como datas, hora, jardas, polegadas, onças etc. Nos cálculos decimais, ele também fornece um método para o programador trabalhar com uma precisão numérica além da fornecida pelo hardware da máquina. Isso tem um grande número de aplicações, desde as muito pequenas (por exemplo, cálculos quânticos) às muito grandes (por exemplo, descobrindo novos números primos).

É importante entender que chamamos essas coisas de computadores por um motivo. Às vezes, precisamos deles para nos dar a resposta correta!


Esta resposta não faz sentido ... Qual é a conexão entre usar "mod" e usar unidades diferentes ???
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.