Pourquoi X % 0
est-il une expression invalide?
J'ai toujours pensé que X % 0
devrait être égal à X. Puisque vous ne pouvez pas diviser par zéro, la réponse ne devrait-elle pas être naturellement le reste, X (tout ce qui reste)?
La norme C++ (2003) dit au §5.6/4:
[...] Si le second opérande de/ou% est zéro, le comportement est undefined ; [...]
C'est-à-dire que les expressions suivantes invoquent undefined-behavior (UB):
X / 0; //UB
X % 0; //UB
Notez également que -5 % 2
n'est PAS égal à -(5 % 2)
(comme Petar semble le suggérer dans son commentaire à sa réponse). C'est défini par l'implémentation. La spécification dit (§5.6/4),
[...] Si les deux opérandes ne sont pas négatifs, le reste est non négatif. sinon, le signe du reste est défini par la mise en oeuvre .
Cette réponse n'est pas pour le mathématicien. Cette réponse tente de motiver (au détriment de la précision mathématique).
Mathématiciens:Voir ici.
Programmeurs: N'oubliez pas que la division par 0
est undefined
. Par conséquent, mod
, qui repose sur la division, est également undefined
.
Cela représente une division pour X
et D
positifs; il est composé de la partie intégrale et de la partie fractionnaire:
(X / D) = integer + fraction
= floor(X / D) + (X % D) / D
En réarrangeant, vous obtenez:
(X % D) = D * (X / D) - D * floor(X / D)
En remplaçant 0
par D
:
(X % 0) = 0 * (X / 0) - 0 * floor(X / 0)
Puisque la division par 0
est undefined
:
(X % 0) = 0 * undefined - 0 * floor(undefined)
= undefined - undefined
= undefined
X % D
est par definition un nombre 0 <= R < D
, tel qu’il existe Q
de sorte que
X = D*Q + R
Donc, si D = 0
, un tel numéro ne peut pas exister (parce que 0 <= R < 0
)
Je pense que parce que pour obtenir le reste de X % 0
, vous devez d’abord calculer X / 0
qui donne l’infini, et essayer de calculer le reste de l’infini n’est pas vraiment possible.
Cependant, la meilleure solution en accord avec votre réflexion serait de faire quelque chose comme ceci
REMAIN = Y ? X % Y : X
Une autre façon, conceptuellement facile, de comprendre le problème:
Ignorer pour le moment la question du signe argument, a % b
pourrait facilement être ré-écrit en tant que a - ((a / b) * b)
. L'expression a / b
n'est pas définie si b
est égal à zéro. Dans ce cas, l'expression globale doit l'être également.
En fin de compte, le module est effectivement une opération de division, donc si a / b
n'est pas défini, il n'est pas déraisonnable de s'attendre à ce que a % b
le soit également.
X% Y donne un résultat dans l'intervalle entier [0, Y). X% 0 devrait donner un résultat supérieur ou égal à zéro et inférieur à zéro.
vous pouvez échapper au cas "divivion par 0" de (A% B) pour son identité de type float mod (a, b) pour float (B) = b = 0.0, défini de manière différente ou défini différemment entre éviter les erreurs de logique (crash brutal) au profit des erreurs arithmétiques ...
en calculant mod([a*b],[b])==b*(a-floor(a))
INSTREAD OF
informatique mod([a],[b])
où [a * b] == votre axe des x, dans le temps [b] == le maximum de la courbe de bascule (qui ne sera jamais atteint) == la première dérivée de la fonction de bascule