Sean a, byc números enteros positivos no grandes. ¿A / b / c siempre es igual a a / (b * c) con aritmética de números enteros de C #? Para mí, en C # se ve así:
int a = 5126, b = 76, c = 14;
int x1 = a / b / c;
int x2 = a / (b * c);
Entonces mi pregunta es: ¿ x1 == x2para todo a, by c?
c#
math
integer
integer-arithmetic
Jason Crease
fuente
fuente

Respuestas:
Dejar que
\denotan división entera (C #/operador entre dosints) y dejar que/denotan división matemática habitual. Entonces, six,y,zson enteros positivos y estamos ignorando el desbordamiento ,(x \ y) \ z = floor(floor(x / y) / z) [1] = floor((x / y) / z) [2] = floor(x / (y * z)) = x \ (y * z)dónde
El salto de una línea
[1]a otra[2]se explica a continuación. Suponga que tiene dos números enterosayby un número fraccionariofen el rango[0, 1). Es sencillo ver quefloor(a / b) = floor((a + f) / b) [3]Si de acuerdo
[1]a identificara = floor(x / y),f = (x / y) - floor(x / y)yb = z, a continuación,[3]implica que[1]y[2]son iguales.Puede generalizar esta prueba a enteros negativos (aún ignorando el desbordamiento ), pero se lo dejo al lector para que sea sencillo.
Sobre el tema del desbordamiento , consulte la respuesta de Eric Lippert para obtener una buena explicación. También adopta un enfoque mucho más riguroso en la publicación y la respuesta de su blog , algo que deberías considerar si sientes que estoy siendo demasiado ondulante.
fuente
floor(x / y) - (x / y)es pequeña,z >= 1por lo que tomando el valorfloorde eso es 0 y podemos ignorarlo. Eso en realidad no sigue, ya que en realidad es un sumando dentro de unfloor()(es decir, considerarfloor(1/2)vsfloor(1/2 + 1/2)).Me gustó tanto esta pregunta que la convertí en el tema de mi blog el 4 de junio de 2013 . ¡Gracias por la gran pregunta!
Los estuches grandes son fáciles de conseguir. Por ejemplo:
a = 1073741823; b = 134217727; c = 134217727;porque se
b * cdesborda a un número negativo.Yo agregaría a eso el hecho de que en aritmética comprobada , la diferencia entre
a / (b * c)y(a / b) / cpuede ser la diferencia entre un programa que funciona y un programa que falla. Si el producto debycdesborda los límites de un entero, el primero se bloqueará en un contexto verificado.Para pequeños enteros positivos, digamos, lo suficientemente pequeños como para caber en un corto, se debe mantener la identidad.
Timothy Shields acaba de publicar una prueba; Presento aquí una prueba alternativa. Suponga que todos los números aquí son enteros no negativos y que ninguna de las operaciones se desborda.
La división
x / yentera de encuentra el valorqtal queq * y + r == x, donde0 <= r < y.Entonces la división
a / (b * c)encuentra el valorq1tal quedónde
0 <= r1 < b * cla división
( a / b ) / cprimero encuentra el valorqttal quey luego encuentra el valor
q2tal queAsí que sustituye eso por
qty obtenemos:donde
0 <= r2 < cy0 <= r3 < b.Dos cosas iguales son iguales entre sí, así que tenemos
Supongamos
q1 == q2 + xpor algún número enterox. Sustituye eso y resuelve parax:dónde
0 <= r1 < b * c 0 <= r2 < c 0 <= r3 < b¿Puede
xser mayor que cero? No. Tenemos las desigualdades:b * r2 + r3 - r1 <= b * r2 + r3 <= b * (c - 1) + r3 < b * (c - 1) + b == b * cEntonces, el numerador de esa fracción es siempre menor que
b * c, porxlo que no puede ser mayor que cero.¿Puede
xser menor que cero? No, por argumento similar, se deja al lector.Por lo tanto, el entero
xes cero y, por lo tantoq1 == q2.fuente
x1como lax2operación fallarán de manera idéntica en ese casox1yx2fallarán sibocson cero. Para otros valores, lax1expresión es mejor, ya que evitará el posible desbordamiento de enteros( b * c)quex2tiene.Si los valores absolutos de
bycestán por debajo de aproximadamentesqrt(2^31)(aprox. 46 300), por lo queb * cnunca se desbordará, los valores siempre coincidirán. Si seb * cdesborda, se puede arrojar un error en uncheckedcontexto o se puede obtener un valor incorrecto en ununcheckedcontexto.fuente
Evitando los errores de desbordamiento notados por otros, siempre coinciden.
Supongamos eso
a/b=q1, lo que significa esoa=b*q1+r1, dónde0<=r1<b.Ahora suponga eso
a/b/c=q2, lo que significa esoq1=c*q2+r2, dónde0<=r2<c.Esto significa eso
a=b(c*q2+r2)+r1=b*c*q2+br2+r1.Para
a/(b*c)=a/b/c=q2, necesitamos tener0<=b*r2+r1<b*c.Pero
b*r2+r1<b*r2+b=b*(r2+1)<=b*c, según sea necesario, y las dos operaciones coinciden.Esto no funciona si
bocson negativos, pero tampoco sé cómo funciona la división de enteros en ese caso.fuente
Ofreceré mi propia prueba por diversión. Esto también ignora el desbordamiento y, lamentablemente, solo maneja los positivos, pero creo que la prueba es clara y clara.
El objetivo es demostrar que
floor(floor(x/y)/z) = floor(x/y/z)donde
/es la división normal (a lo largo de esta prueba).Representamos el cociente y el resto de
a/búnicamente comoa = kb + r(con eso queremos decir quek,rson únicos y también nota|r| < |b|). Entonces tenemos:(1) floor(x/y) = k => x = ky + r (2) floor(floor(x/y)/r) = k1 => floor(x/y) = k1*z + r1 (3) floor(x/y/z) = k2 => x/y = k2*z + r2Entonces, nuestro objetivo es simplemente mostrar eso
k1 == k2. Bueno, tenemos:k1*z + r1 = floor(x/y) = k = (x-r)/y (from lines 1 and 2) => x/y - r/y = k1*z + r1 => x/y = k1*z + r1 + r/yy por lo tanto:
(4) x/y = k1*z + r1 + r/y (from above) x/y = k2*z + r2 (from line 3)Ahora observe de (2) que
r1es un número entero (porquek1*zes un número entero por definición) yr1 < z(también por definición). Además de (1) sabemos esor < y => r/y < 1. Ahora considere la sumar1 + r/yde (4). La afirmación es quer1 + r/y < zy esto se desprende de las afirmaciones anteriores (porque0 <= r1 < zyr1es un número entero, por lo que tenemos0 <= r1 <= z-1. Por lo tanto0 <= r1 + r/y < z). Así,r1 + r/y = r2por definición der2(de lo contrario, habría dos residuos de losx/yque contradice la definición de residuo). Por tanto tenemos:y tenemos la conclusión deseada de eso
k1 = k2.La prueba anterior debería funcionar con negativos, excepto por un par de pasos que necesitaría para verificar un caso (s) adicional (s) ... pero no lo verifiqué.
fuente
ejemplo de contador: INT_MIN / -1 / 2
fuente