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?
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?
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 /= factor
iterado 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
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 /= factor
iterado 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
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