overload - operator c++
¿Por qué se hace referencia al operador% como el operador de "módulo" en lugar del operador "resto"? (3)
Me parece un nombre inapropiado llamarlo "módulo" y no "resto" (en matemáticas, la respuesta debería ser 9).
C lo llama el operador%, y llama a su resultado el resto. C ++ copia esto de C. Ningún lenguaje lo llama el operador de módulo. Esto también explica por qué el resto es negativo: porque el operador / trunca hacia 0, y (a / b) * b + (a % b)
debe ser igual a
.
Edición : David Rodríguez señala acertadamente que C ++ define una plantilla de clase std::modulus
, que llama al operator%
. En mi opinión, esa clase tiene un mal nombre. Excavando un poco, se hereda de STL donde ya estaba nombrado como lo es ahora. La descarga para STL dice "El STL se desarrolló en SGI MIPSproTM C ++ 7.0, 7.1, 7.2 y 7.2.1.", Y por lo que puedo decir sin tener el compilador y el hardware, MIPSpro pasa la división a la CPU y El hardware MIPS se trunca a 0, lo que significaría que std::modulus
siempre ha sido mal llamado.
Hoy en el trabajo tuve una discusión interesante con uno de mis compañeros de trabajo. Se sorprendió cuando le sucedió lo siguiente:
assert(-1 % 10 == -1) //Expecting 9
Así que cuando vino a preguntarme al respecto, le dije "bueno, eso tiene sentido. Cuando divides -1 por 10, obtienes 0 con -1 restante. Sin embargo, su argumento es que se supone que el operador de módulo debe ser fiel a el modelo "siempre positivo". Hice una pequeña investigación y descubrí que el módulo al que se refería se ve así:
Sea q el cociente entero de a y n. Sea r el resto. Entonces:
a = n * q + r
La definición que estaba usando, sin embargo, parece ser la versión de Knuth del módulo, que es:
Sea q el piso de un dividido por n. Sea r el resto. Entonces:
r = a - n * q
Entonces, mi pregunta es ¿por qué terminó en el estándar FORTRAN (y posteriormente en el estándar C) para que el operador de módulo truncara hacia 0? Me parece un nombre inapropiado llamarlo "módulo" y no "resto" (en matemáticas, la respuesta debería ser 9). ¿Está esto relacionado con cómo el hardware está haciendo la división?
Para referencia:
- Wikipedia en Módulo
- Entrada de MSDN en el operador "módulo"
(Sí, me doy cuenta de que es para VS2003 ... Actualmente estoy atascado. Sadface) - Cambios de operador de módulo
- No asuma el resto positivo ...
TLDR; ¿Es el hardware la razón por la que el operador de módulo trunca hacia 0?
Me temo que el problema surge de un malentendido de las matemáticas. El módulo de congruencia n es una relación de equivalencia , por lo que solo define las clases de equivalencia . Por lo tanto, no es correcto decir que '' en matemáticas, la respuesta realmente debería ser 9 '' porque podría ser también 19, 29, etc. Y por supuesto puede ser -1 o -11. Hay infinitos elementos de la clase de los números n que son n ≡ -1 mod (10).
http://en.wikipedia.org/wiki/Modular_arithmetic
http://en.wikipedia.org/wiki/Congruence_relation
Entonces, la pregunta correcta podría ser: ¿qué elemento de la clase de los números que son ≡ -1 mod (10) será el resultado de -1% 10 en C ++? Y la respuesta es: el resto de la división de -1 por 10. No hay misterio.
PS Su definición de módulo y Knuth son, ehm, equivalente ... :)
%
es el operador restante en C y C ++.
En el estándar de C ++, se llama el operador %
y produce el resto de la división . En la Norma C se llama el operador %
y desde C99 es en realidad un operador restante. Los operadores de módulo y resto difieren con respecto a los valores negativos.
El operador %
se define en C y C ++ con a == (a / b * b) + a % b
.
El truncamiento de la división entera hacia 0 en C se realiza desde C99. En C89 se definió la implementación (y %
puede ser un operador de módulo en C89). C ++ también realiza un truncamiento hacia cero para la división entera.
Cuando el truncamiento se realiza hacia cero, %
es un operador restante y el signo del resultado es el signo del dividendo. Cuando el truncamiento se realiza hacia menos infinito, %
es un operador de módulo y el signo del resultado es el signo del divisor.
Sobre las razones por las que C cambió el comportamiento definido por la implementación de la división de enteros con respecto al truncamiento, Doug Gwyn del comité C dijo:
C99 impuso un requisito compatible con Fortran en un intento de atraer a más programadores de Fortran y ayudar a convertir el código de Fortran a C.
La justificación de C99 dice con respecto al truncamiento hacia la división entera cero:
Sin embargo, en Fortran, el resultado siempre se truncará hacia cero, y la sobrecarga parece ser aceptable para la comunidad de programación numérica. Por lo tanto, C99 ahora requiere un comportamiento similar, lo que debería facilitar la transferencia del código de Fortran a C.
En gcc
el comportamiento de implementación en C89 siempre ha sido el truncamiento hacia cero.
Entonces, %
es el operador restante en C99, C ++ y también en Java, pero no es el operador restante en todos los lenguajes de programación. En Ruby y Python, %
es de hecho el operador de módulo (la división entera se realiza hacia menos infinito en estos idiomas). Haskhell y Scheme tienen dos operadores separados: mod
y rem
para Haskell, y modulo
y remainder
para Scheme.