2008-11-26 14 views
29

Supongamos que a y b son del tipo int, y b es distinto de cero. Considere el resultado de realizar a/b en los siguientes casos:Redondeo de división entera con negativos en C++

  1. a y b son tanto no negativo.
  2. a y b son negativos.
  3. Exactamente uno de ellos es negativo.

En el Caso 1, el resultado se redondea al entero más cercano. Pero, ¿qué dice la norma sobre los casos 2 y 3? Un viejo borrador que encontré flotando en Internet indica que depende de la implementación (sí, incluso del caso 2), pero el comité se inclina a hacerlo siempre 'redondo hacia cero'. ¿Alguien sabe lo que dice el (último) estándar? Responda solo en función del estándar, no de lo que tenga sentido o de lo que hagan los compiladores en particular.

+1

Increíble oportunidad de investigación dada la naturaleza de 1200 páginas del estándar. Voy a darle un grep rápido y renunciar :) –

Respuesta

22

De acuerdo con la revisión de mayo de 2008,

Tienes razón:

El binario/operador obtiene el cociente y el operador binario% devuelve el resto de la división de la primera expresión de el segundo. Si el segundo operando de/o% es cero, el comportamiento no está definido; de lo contrario (a/b) * b + a% b es igual a a. Si ambos operandos son no negativos, el resto no es negativo; si no, el signo del resto está definido por la implementación75).

Nota 75 dice:

según la obra en curso hacia la revisión de ISO C, el algoritmo preferido para la división de enteros sigue las reglas definidas en la norma ISO Fortran, ISO/IEC 1539: 1991, en el que el cociente siempre se redondea hacia cero.

Lo más probable es que C++ tenga un retraso de C en este aspecto. Tal como está, no está definido pero tienen un ojo para cambiarlo.

Trabajo en el mismo departamento que Stroustrup y con un miembro del comité. Las cosas toman AGES para ser completadas, y son interminablemente políticas. Si parece tonto, probablemente lo sea.

+7

La declaración citada es antigua. Se remonta al estándar C++ 98 y se refiere a la revisión C99. C99 especifica el redondeo hacia cero y C++ 11 sigue su ejemplo. – Jed

7

Apenas un comentario. El borrador de trabajo actual para el estándar C++ corrige de hecho el problema "definido por la implementación" y solicita el truncamiento hacia cero. Here es la página web del comité, y here es el borrador. La cuestión está en la página 112.

17

Como una actualización de las otras respuestas:

El último proyecto de C++ 11, n3242 que es, a efectos prácticos idéntica a la norma real de C++ 11, dice esto en 5.6 punto 4 (página 118):

Para operandos integrales la/operador produce el cociente algebraica con cualquier parte fraccionaria desechado; (Ver nota 80)

Nota 80 estados (tenga en cuenta que los billetes son no normativo):

80) Esto es a menudo llamado truncamiento hacia cero.

Point 4 pasa a estado:

si el cociente a/b es representable en el tipo del resultado, (a/b) * b + a% b es igual a una .

que se puede mostrar para requerir el signo de a%b a ser el mismo que el signo de a (cuando no cero).

-1

veces tenemos que dar un paso atrás y mirar justo en la matemática de que:

Dada int x, int y

si int i1 = X/Y y int i2 = x% Y

entonces y * I1 + I2 debe ser x

así que esto no se trata tanto de la norma, pero sólo hay una forma en que esto pueda ser. Si cualquier estándar permite que sea de otra manera, entonces el estándar es incorrecto, y eso significa que el idioma está roto.