2011-09-10 10 views
48

¿Por qué X % 0 es una expresión no válida?Can not Mod Zero?

Siempre pensé que X % 0 debería ser igual a X. Dado que no se puede dividir por cero, ¿no debería la respuesta naturalmente ser el resto, X (todo sobrante)?

+0

@xanatos Me too. Di el otro +1 para equilibrar el otro -1 ... Sospecho que está muy duplicado, pero debería haber sido votado para ser cerrado. –

+0

@pst: posible duplicado de [¿Por qué es esta una excepción de punto flotante?] (Http://stackoverflow.com/questions/1081250/why-is-this-a-floating-point-exception) pero no era exactamente fácil de encontrar. –

+1

@Mu la respuesta es bastante diferente. Aquí Petar explica cómo '%' está matemáticamente definido, allí explican por qué el error es eso, en lugar de algo más claro. – xanatos

Respuesta

33

El estándar de C++ (2003) dice en §5.6/4,

[...] Si el segundo operando de/o% es cero el comportamiento es indefinido ; [...]

Es decir, las expresiones siguientes invocan indefinido en el comportamiento (UB):

X/0; //UB 
X % 0; //UB 

Nótese también que -5 % 2 no es igual a -(5 % 2) (Petar parece sugerir en su comentario a su respuesta). Está definido por la implementación. La especificación dice (§5.6/4),

[...] Si ambos operandos son no negativos, el resto no es negativo; si no, el signo del resto está definido por la implementación.

+0

Probablemente me inclinaría hacia la implementación "* en parte * definida", el letrero es la implementación definida pero ¿no se corregirá el valor una vez que se elija el signo? Pero eso es solo recoger cosas. –

+0

¿Es posible bloquear el programa usando mod cero o solo se desconoce el resultado? – Zaffy

+0

@Zaffy: Dado que el mod cero invoca un comportamiento indefinido (UB), entonces sí, es * posible * bloquear su programa usando mod cero, pero ** no ** * garantizado * bloquea su programa. El colapso del programa es solo una de las posibilidades de un millón de UB. – Nawaz

1

X% Y arroja un resultado en el rango entero [0, Y). X% 0 debería dar un resultado mayor o igual a cero y menor que cero.

+2

Eso no es cierto, AFAIK el signo de 'x% y' es implementación definida si' x <0'. '-5% 2' pasa a ser -1 en mi sistema. –

+0

Cierto, las peculiaridades de mod. Pero, por desgracia, es suficiente para ilustrar por qué uno no puede modificar por cero. –

4

X % D es por definición un número 0 <= R < D, tal que existe Q modo que

X = D*Q + R 

Así que si D = 0, dicho número no puede existe (porque 0 <= R < 0)

+2

Eso no es verdad, AFAIK el signo de 'x% y' es implementación definida si' x <0'. '-5% 2' pasa a ser -1 en mi sistema. –

+0

'X = D * Q + R' funciona para _any_' Q' cuando 'D = 0', con' X = R' como OP deseado. Es el '0 <= R <0' que es imposible de satisfacer. Tu respuesta parece implicar que es al revés, aunque podría estar leyéndolo mal. – hammar

+0

-5% 2 = - (5% 2) de hecho. –

8

mayo quiere ver this.

Como división por 0 es undefined, mod, que se basa en la división, también es undefined.


Esto representa la división; se compone de la parte integral y residuo:

(X/D) = floor(X/D) + (X % D)/D 

reordenado, se obtiene:

(X % D)/D = (X/D) - floor(X/D) 
(X % D) = D * ((X/D) - floor(X/D)) 

Sustituyendo 0 para D:

(X % D) = D * ((X/0) - floor(X/0)) 

Puesto que la división por 0 es undefined:

(X % D) = D * (undefined - floor(undefined)) 
(X % D) = D * (undefined) 
(X % D) = undefined 
+0

¿Por qué? t usted simplemente sustituye 0 por el D externo en la segunda ecuación haciéndolo '(X% 0) = 0 * (w/e)' y simplemente lo llama cero? –

2

creo porque para obtener el resto de X % 0 es necesario calcular primero X/0 que produce el infinito, y tratando de calcular el resto del infinito no es realmente posible.

Sin embargo, la mejor solución de acuerdo con su forma de pensar sería hacer algo como esto

REMAIN = Y ? X % Y : X 
2

Otra forma en que podría ser conceptualmente fácil de entender el problema:

Ignorando por el momento la cuestión del signo de argumento, a % b podría volver a escribirse fácilmente como a - ((a/b) * b). La expresión a/b no está definida si b es cero, por lo que en ese caso la expresión general debe ser también.

Al final, el módulo es efectivamente una operación divisiva, por lo que si a/b no está definido, no es irrazonable esperar que a % b también lo esté.

0

puede evadir el caso "divivion by 0" de (A% B) para su tipo float identity mod (a, b) para float (B) = b = 0.0, que no está definido o definido de forma diferente entre 2 implementaciones, para evitar errores de lógica (se bloquea duros) en favor de errores aritméticos ...

por computación mod([a*b],[b])==b*(a-floor(a))
instread dE
computación mod([a],[b])

donde [a * b] == su eje x , con el tiempo [b] == el máximo de la curva de balancín (que nunca se alcanzará) == la primera derivada del balancín función

https://www.shadertoy.com/view/MslfW8