c++ - decimales - division entera ejercicios
¿Por qué la división de módulo(%) solo funciona con enteros? (8)
Recientemente me encontré con un problema que podría resolverse fácilmente usando la división de módulo, pero la entrada era flotante:
Dada una función periódica (por ejemplo,
sin
) y una función de computadora que solo puede calcularla dentro del rango de período (por ejemplo, [-π, π]), realice una función que pueda manejar cualquier entrada.
La solución "obvia" es algo así como:
#include <cmath>
float sin(float x){
return limited_sin((x + M_PI) % (2 *M_PI) - M_PI);
}
¿Por qué esto no funciona? Me sale este error:
error: invalid operands of types double and double to binary operator %
Curiosamente, funciona en Python:
def sin(x):
return limited_sin((x + math.pi) % (2 * math.pi) - math.pi)
El operador %
no funciona en C ++, cuando está tratando de encontrar el resto de dos números que son del tipo Float
o Double
.
Por lo tanto, podría intentar usar la función fmod
desde math.h
/ cmath.h
o podría usar estas líneas de código para evitar el uso de ese archivo de encabezado:
float sin(float x) {
float temp;
temp = (x + M_PI) / ((2 *M_PI) - M_PI);
return limited_sin((x + M_PI) - ((2 *M_PI) - M_PI) * temp ));
}
El operador de módulo %
en C y C ++ se define para dos enteros, sin embargo, hay una función fmod()
disponible para su uso con dobles.
El operador% te da un RESTO (otro nombre para el módulo) de un número. Para C / C ++, esto solo está definido para operaciones enteras. Python es un poco más amplio y le permite obtener el resto de un número de coma flotante por el resto de cuántas veces se puede dividir el número:
>>> 4 % math.pi
0.85840734641020688
>>> 4 - math.pi
0.85840734641020688
>>>
Está buscando fmod() .
Supongo que para responder más específicamente a su pregunta, en los idiomas más antiguos, el operador %
se definió como una división modular entera y en los idiomas más nuevos decidieron ampliar la definición del operador.
EDITAR: si tuviera que apostar por qué, diría que es porque la idea de la aritmética modular se origina en la teoría de números y trata específicamente con los enteros.
Las restricciones están en los estándares:
C11 (ISO / IEC 9899: 201x) §6.5.5 Operadores multiplicativos
Cada uno de los operandos debe tener un tipo aritmético. Los operandos del operador% tendrán un tipo de entero.
C ++ 11 (ISO / IEC 14882: 2011) §5.6 Operadores multiplicativos
Los operandos de * y / tendrán un tipo de enumeración o aritmética; los operandos de% tendrán un tipo de enumeración o integral. Las conversiones aritméticas habituales se realizan en los operandos y determinan el tipo de resultado.
La solución es usar fmod
, que es exactamente la razón por la que los operandos de %
están limitados al tipo de entero en primer lugar, de acuerdo con C99 Justificación §6.5.5 Operadores multiplicativos :
El Comité C89 rechazó la extensión del operador% para trabajar en tipos flotantes, ya que dicho uso duplicaría la facilidad provista por fmod
Porque la noción matemática normal de "resto" solo se aplica a la división de enteros. es decir, la división que se requiere para generar un cociente entero.
Para extender el concepto de "resto" a números reales, debe introducir un nuevo tipo de operación "híbrida" que genere un cociente entero para operandos reales . El lenguaje Core C no es compatible con dicha operación, pero se proporciona como una función fmod
biblioteca estándar, así como la función de remainder
en C99. (Tenga en cuenta que estas funciones no son las mismas y tienen algunas peculiaridades. En particular, no siguen las reglas de redondeo de la división de enteros).
Realmente no puedo decirlo con certeza , pero supongo que es principalmente histórico. Bastantes pocos compiladores de C iniciales no soportaban el punto flotante en absoluto. Se agregó más adelante, e incluso entonces no del todo, principalmente se agregó el tipo de datos y las operaciones más primitivas soportadas en el lenguaje, pero todo lo demás quedó en la biblioteca estándar.
prueba fmod