¿Cuál es el comportamiento de la división de enteros?

8 minutos de lectura

avatar de usuario
TTT

Por ejemplo,

int result;

result = 125/100;

o

result = 43/100;

¿El resultado será siempre el piso de la división? ¿Cuál es el comportamiento definido?

  • Resumen: firmado la división entera se trunca hacia cero. Para resultados no negativos, esto es lo mismo que el piso (redondeado hacia -Infinito). (Tenga en cuenta que C89 no garantiza esto, vea las respuestas).

    – Peter Cordes

    7 de noviembre de 2017 a las 4:19


  • Todos siguen diciendo “truncar hacia cero” o “techo” o “piso” como si el código estuviera tomando una decisión deliberada sobre qué técnica usar. Si el código pudiera hablar diría "I just throw the dam fraction part in the trash and move on with life"

    – Timothy LJ Stewart

    8 de octubre de 2018 a las 3:09


  • @TimothyL.J.Stewart El “código” está tomando una decisión deliberada. Según la especificación, la división de enteros está destinada a ser una división T (runcation). Debido a esto, el operador módulo/resto se implementa de manera diferente que si estuviera en otro idioma, por ejemplo, Python o Ruby. Ver este para obtener una lista de las diferentes formas en que los idiomas hacen el operador de módulo y este documento que enumera al menos cinco de las formas comunes en que los lenguajes de programación deciden hacer div/modulo.

    – 13steinj

    23 oct 2018 a las 21:22

  • @ 13steinj Hablo coloquialmente por los comentarios que se estaba convirtiendo en “está truncado hacia cero… no, es el piso… no, si es negativo, es el techo…” a veces los tecnicismos no se propagan en el futuro con la memoria humana como deseamos, pero sabiendo intuitivamente que “la parte de la fracción se tira”, puede derivar los puntos técnicos. Los tecnicismos son una carga pesada, pero la intuición es ligera y refrescante como el viento, los llevaré lejos y cuando sea necesario sabré por dónde empezar. Como ese documento que vinculaste, gracias.

    – Timothy LJ Stewart

    24 oct 2018 a las 0:50

  • Respondí aquí con énfasis en la división euclidiana (interacción entre la división de enteros y el operador de módulo).

    – Picaud Vicente

    18 mayo 2019 a las 17:25

avatar de usuario
tiro

Dirkgently ofrece una excelente descripción de la división de enteros en C99, pero también debe saber que en C89 la división de enteros con un operando negativo tiene una dirección definida por la implementación.

Del borrador ANSI C (3.3.5):

Si alguno de los operandos es negativo, la implementación define si el resultado del operador / es el entero más grande menor que el cociente algebraico o el entero más pequeño mayor que el cociente algebraico, al igual que el signo del resultado del operador %. Si el cociente a/b es representable, la expresión (a/b)*b + a%b será igual a a.

Así que tenga cuidado con los números negativos cuando esté atascado con un compilador C89.

Es un hecho divertido que C99 eligió el truncamiento hacia cero porque así fue como lo hizo FORTRAN. Ver este mensaje en comp.std.c.

  • Y C99 borrador N1256 prólogo párrafo 5 menciona reliable integer division como una nueva característica del lenguaje. Increíble *-*.

    – Ciro Santilli Путлер Капут 六四事

    11 de septiembre de 2016 a las 8:24

  • El truncamiento es la forma en que se comporta el hardware de CPU más común (por ejemplo, x86), por lo que sería una locura hacer una elección diferente. IDK, que fue primero, la semántica de Fortran o el comportamiento del hardware, pero no es una coincidencia que también sean lo mismo.

    – Peter Cordes

    7 de noviembre de 2017 a las 4:23

  • @PeterCordes: el hardware de CPU más común podría hacer una división piso por la mayoría de las constantes más rápido de lo que podría hacer una división truncada. En mi humilde opinión, hubiera sido mejor para el estándar decir que expr1 / expr2 y expr1 % expr2 deben ser consistentes entre sí cuando ambas instancias de expr1 combinan los mismos objetos de la misma manera, y lo mismo para expr2, pero la elección de división truncada versus dividida por pisos no está especificada. Eso habría permitido una generación de código más eficiente sin romper mucha compatibilidad (y las implementaciones podrían documentar un comportamiento específico si estuviera inclinado)

    – Super gato

    30 de junio de 2018 a las 20:05

  • @ dan04: sí, el piso sería válido solo para números enteros positivos 🙂

    – Leónidas

    30 de agosto de 2010 a las 17:46

Cuando el resultado es negativo, C se trunca hacia 0 en lugar de suelo. Aprendí esta lectura sobre por qué la división de enteros de Python siempre suelo aquí: Por qué los pisos de división de enteros de Python

  • Estoy de acuerdo con el comentario y me pregunto si tener (% pos negativo) negativo es alguna vez útil. En una nota relacionada, me pregunto si el comportamiento aritméticamente incorrecto requerido en algunos casos de “unsignedvar > signedvar” es alguna vez útil. Puedo entender la razón por la que no se requiere un comportamiento siempre correcto; No veo ninguna razón para exigir un comportamiento incorrecto.

    – Super gato

    30 de agosto de 2010 a las 18:34

  • +1 para obtener una excelente referencia sobre por qué el piso es el comportamiento correcto para la división de enteros (al contrario de la definición de C, que está rota y casi nunca es útil).

    – R.. GitHub DEJA DE AYUDAR A ICE

    30 de agosto de 2010 a las 19:19

  • @supercat Considere: filtered = (k - 1) * filtered + value + carry; carry = filtered % factor; filtered /= factoriterado con valores cambiantes de value. Hace una buena aproximación de enteros a un filtro de paso bajo de primer orden con constante de tiempo k… pero solo es simétrico si la división se trunca y carry obtiene valores negativos. Ambos comportamientos para la división son útiles de vez en cuando.

    – Hobbs

    21 de diciembre de 2017 a las 15:01

  • @hobbs: no creo que el código anterior se comporte limpiamente cuando las señales cruzan cero. Si div es un operador de división piso y factor es raro entonces filtered += (filter+(factor div 2)) div factor produciría un comportamiento limpio y simétrico para todos los valores hasta INT_MAX-(factor div 2).

    – Super gato

    21 de diciembre de 2017 a las 18:35

  • Sin embargo, @supercat funciona; ese código solo se destila ligeramente de algo que he estado ejecutando en el controlador de un reloj atómico durante un tiempo.

    – Hobbs

    16 de enero de 2018 a las 22:11

avatar de usuario
adi1ya

Sé que la gente ha respondido a su pregunta, pero en términos sencillos:

5 / 2 = 2 //ya que tanto 5 como 2 son números enteros y la división de números enteros siempre trunca los decimales

5.0 / 2 or 5 / 2.0 or 5.0 /2.0 = 2.5 //aquí 5 o 2 o ambos tienen decimales, por lo tanto, el cociente que obtendrá estará en decimal.

  • Estoy de acuerdo con el comentario y me pregunto si tener (% pos negativo) negativo es alguna vez útil. En una nota relacionada, me pregunto si el comportamiento aritméticamente incorrecto requerido en algunos casos de “unsignedvar > signedvar” es alguna vez útil. Puedo entender la razón por la que no se requiere un comportamiento siempre correcto; No veo ninguna razón para exigir un comportamiento incorrecto.

    – Super gato

    30 de agosto de 2010 a las 18:34

  • +1 para obtener una excelente referencia sobre por qué el piso es el comportamiento correcto para la división de enteros (al contrario de la definición de C, que está rota y casi nunca es útil).

    – R.. GitHub DEJA DE AYUDAR A ICE

    30 de agosto de 2010 a las 19:19

  • @supercat Considere: filtered = (k - 1) * filtered + value + carry; carry = filtered % factor; filtered /= factoriterado con valores cambiantes de value. Hace una buena aproximación de enteros a un filtro de paso bajo de primer orden con constante de tiempo k… pero solo es simétrico si la división se trunca y carry obtiene valores negativos. Ambos comportamientos para la división son útiles de vez en cuando.

    – Hobbs

    21 de diciembre de 2017 a las 15:01

  • @hobbs: no creo que el código anterior se comporte limpiamente cuando las señales cruzan cero. Si div es un operador de división piso y factor es raro entonces filtered += (filter+(factor div 2)) div factor produciría un comportamiento limpio y simétrico para todos los valores hasta INT_MAX-(factor div 2).

    – Super gato

    21 de diciembre de 2017 a las 18:35

  • Sin embargo, @supercat funciona; ese código solo se destila ligeramente de algo que he estado ejecutando en el controlador de un reloj atómico durante un tiempo.

    – Hobbs

    16 de enero de 2018 a las 22:11

¿El resultado será siempre el piso de la división?

No. El resultado varía, pero la variación ocurre solo para valores negativos.

¿Cuál es el comportamiento definido?

Para que quede claro, el piso redondea hacia el infinito negativo, mientras que la división entera redondea hacia cero (trunca)

Para valores positivos son iguales

int integerDivisionResultPositive= 125/100;//= 1
double flooringResultPositive= floor(125.0/100.0);//=1.0

Para valor negativo esto es diferente

int integerDivisionResultNegative= -125/100;//=-1
double flooringResultNegative= floor(-125.0/100.0);//=-2.0

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad