¿Por qué es mod (%) un operador matemático fundamental en muchos lenguajes de programación?

17

¿Hay alguna razón, histórica o de otro tipo, por la cual el operador de módulo es parte de un pequeño conjunto de operadores estándar en lo que parecen muchos idiomas? ( +, -, *, /y %, para Java y C, con **Ruby y Python).

Parece extraño incluir el mod como "fundamental" (para no tocarlo, lo uso mucho, pero también uso la exponenciación, el valor absoluto, el piso / techo u otros; parecen igual de útiles y necesarios). ¿Fue esta una vieja decisión tomada en alguna especificación que siguen Java, C, Ruby y Python o un lenguaje del que todos descienden? Por lo que puedo decir, la mayoría de los dialectos de Lisp solo incluyen +, -, /y *.

Al principio me preguntaba si el mod era particularmente fácil de implementar a nivel binario (¿eso incluso haría una diferencia, con respecto a las decisiones sobre lo que debería ser un operador "fundamental" y lo que no debería ser), pero parece que no lo es. ¿Se usa mucho más comúnmente en programación de lo que creo?

Eli Rose - REINSTATE MONICA
fuente

Respuestas:

20

Estoy seguro de que es común porque muchas arquitecturas de CPU se implementan moduluscomo una segunda salida de la instrucción de división de enteros.

No recuerdo que estuviera presente en las CPU de la década de 1970 (6800, 8080, Z80, 1604, etc.), pero en la década de 1980, Intel 8086 y 8088, así como el Motorola 6809 lo tenían.

La arquitectura de instrucción PDP-11 especificaba la DIVproducción de un cociente y un resto desde el principio (1970), aunque las instrucciones MUL y DIV no estaban presentes en los primeros diseños, pero podían ser emuladas de forma transparente por una "trampa de instrucciones no implementadas" e implementadas con un manejador que hizo un poco de tonterías. Probablemente, la función PDP-11 fomentó la primera edición del lenguaje C que proporciona la %función. (¿Alguna vez notó que un signo de porcentaje tiene una barra oblicua? Eso lo convierte en una opción inteligente para un operador relacionado con la división).

La presencia de módulo Csolo puede explicar su presencia en todos los idiomas modernos. Ctiene una familia muy grande de descendientes y, por lo demás, tuvo bastante influencia.

wallyk
fuente
3
La influencia de +1 C en casi todos los idiomas que no son LISP desde principios de la década de 1970 no puede ser exagerada.
Ross Patterson el
8

Muchos lenguajes de programación tienen un operador "restante" que puede usarse como operador de módulo cuando ambos operandos son positivos; dicho operador a menudo se llama el operador de "módulo", porque ese es su uso principal. Los idiomas generalmente tienen dicho operador porque el hardware de división de muchas plataformas de hardware suministra automáticamente un resto al realizar una división, y calcular un resto o módulo por cualquier otro medio sería mucho más difícil.

No conozco la historia del soporte de hardware para la división firmada; muchos procesadores han proporcionado durante años hardware que puede realizar automáticamente la división firmada sujeta a la regla de que si a / b produce (q, r), entonces -a / b o a / -b producirá (-q, -r), pero No estoy seguro de los casos de uso en los que la división que usa esa regla es particularmente útil. En casi todos los casos en los que he usado operaciones de división entera u "módulo" en valores negativos, he querido redondear hacia el infinito negativo en la división y una verdadera operación de módulo (tal que (a + b) / b siempre igual (a / b) +1 y (a + b)% b siempre sería igual a% b.). Debido a que los operadores no funcionan de esa manera, es necesario probar el signo del dividendo y usar un código diferente cuando ' s negativo: esencialmente negar cualquier beneficio de tener una instrucción de división firmada en primer lugar. Tengo curiosidad por saber para qué fines es realmente útil el soporte de división firmada en hardware.

Volviendo a la pregunta original, el operador de módulo a menudo es útil en situaciones donde se supone que suceden ciertas cosas de forma periódica, ya sea en el espacio (por ejemplo, coordenadas gráficas) o en el tiempo. Por ejemplo, si uno quiere que suceda un evento cada 15 segundos, el tiempo hasta el próximo evento será 15 - ((time_now - time_of_an_occurrence)% 15), suponiendo time_of_an_occurrenceque no sea mayor quetime_now . Si time_of_an_occurrencefuera mayor que time_now, un operador de módulo podría continuar usando la misma fórmula siempre que la resta no se desbordara, pero el operador restante requerirá una fórmula diferente.

Super gato
fuente
3
Por esa razón, Haskell tiene dos operadores: rempara el resto y modpara el módulo con las propiedades que usted describe.
Ingo
@Complicatedseebio: Lo que es particularmente divertido es que a menudo se llama operador de módulo porque generalmente se usa para calcular el módulo, incluso cuando eso requiere un código similar m = number % base; if (m < 0) m+=base;. No sé si alguna vez he visto algún código que se haya beneficiado de que el operador restante se haya vuelto negativo, excepto tal vez q = n/d; if (n%d < 0) q+=1;, que en cualquier caso podría escribirse mejor de otras maneras.
supercat
3

El módulo está estrechamente relacionado con la teoría de grupos y anillos, que son teorías matemáticas muy fundamentales.

La exponenciación es solo la tercera operación en la secuencia de suma, multiplicación, exponenciación, tetración (y esa es una secuencia infinita). Se vuelve importante principalmente con números complejos, que son más raros en aritmética informática. Sin embargo, una exponenciación particular se admite explícitamente: 2 n se escribe comúnmente como 1<<n, ya que las computadoras son bastante binarias.

El piso y el techo son realmente raros en comparación: solo se aplican cuando se convierte de ℝ a ℤ. (coma flotante a entero). Del mismo modo, absse asocia con un mapeo de ℤ a ℕ

MSalters
fuente
ℤ son los enteros (y ℕ es un subconjunto de enteros), debe significar de ℝ a ℤ.
Joni
@Joni: Mezclado dos ejemplos, arreglado.
MSalters
0

Lo siento, pero a riesgo de convertir esto en un juego de "Call My Bluff", creo que la respuesta real a esta pregunta es bastante simple:

Mod permite cálculos precisos en cantidades y unidades "no decimales" como fechas, hora, yardas, pulgadas, onzas, etc. En los cálculos decimales, también proporciona un método para que el programador trabaje con una precisión numérica más allá de la proporcionada por el hardware de la máquina. Esto tiene una gran cantidad de aplicaciones desde muy pequeñas (por ejemplo, cálculos cuánticos) hasta muy grandes (por ejemplo, descubriendo nuevos números primos).

Es importante entender que llamamos a estas cosas computadoras por una razón. ¡A veces necesitamos que nos den la respuesta correcta!


fuente
Esta respuesta no tiene sentido ... ¿Cuál es la conexión entre usar "mod" y usar diferentes unidades?