c++ - menos - complemento a la base binario
¿Cómo imprime std:: cout el cero negativo en un sistema de complemento a uno? (4)
De hecho, agregar n
a -n
debería darte un cero negativo. Pero la generación de -0 no sucede en la práctica, ya que la adición de complemento de 1 utiliza una técnica llamada restador complementario (el segundo argumento se complementa y se resta del primero).
(La forma idiomática de obtener un punto flotante cero firmado no se aplica aquí porque no se puede dividir un número entero entre cero).
En una plataforma complementaria, ¿qué imprimiría el siguiente código?
#include <iostream>
int main() {
int i = 1, j = -1;
std::cout << i+j << std::endl;
return 0;
}
Sospecho que imprimiría "0" en lugar de "-0", pero parece que no puedo encontrar nada autoritario.
Edit: para aclarar, estoy interesado en cómo se imprimiría -0, varias personas han sugerido que, en la práctica, la implementación de complementos podría no generar un cero negativo con el código anterior.
En esos casos, se ha sugerido lo siguiente para generar realmente un -0:
#include <iostream>
int main() {
std::cout << ~0 << std::endl;
return 0;
}
La pregunta sigue siendo: ¿qué imprimirá esto?
En primer lugar, solo para aclarar las cosas, crear un cero negativo utilizando operaciones a nivel de bits y luego usar el valor resultante no es portátil. Dicho esto, nada se especifica en la documentación de fprintf
(por lo tanto, de std::basic_ostream::operator<<(int)
) si el bit de signo en la representación de int corresponde a un bit de relleno en la representación de unsigned
o un valor real poco.
Como conclusión, este es un comportamiento no especificado.
#include <iostream>
int main() {
std::cout << ~0 << std::endl;
return 0;
}
Mirando a través del código fuente de glibc, encontré estas líneas en vfprintf.c:
532 is_negative = signed_number < 0; /
533 number.word = is_negative ? (- signed_number) : signed_number; /
534 /
535 goto LABEL (number); /
...
683 if (is_negative) /
684 outchar (L_(''-'')); /
Por lo tanto, parece que la condición es signed_number < 0
, lo que devolvería false para un -0
.
como se mencionó en @Ysc, nada en la documentación da ninguna especificación para la impresión -0
, por lo que una implementación diferente de la plataforma libc (en un complemento) puede producir un resultado diferente.
Si vemos el punto teórico del complemento de uno. Dado que el cero se define como (+/-) 0, habrá dos valores binarios para 0 si tenemos 4 valores de Bit, el cero será 0000 (+0) y 1111 (-0). Como resultado de esto, siempre tiene que hacer una corrección si una operación, adición o resta, tiene una operación de cruce por cero en ella.
Entonces, por ejemplo, si hacemos la siguiente operación -2+6=4
el resultado se calculará de la siguiente manera:
1101 (-2)
+ 0110 (6)
------
1100 (add carry)
======
0011 (+3)
Como puede ver en la operación Bit, el resultado es incorrecto y es solo el resultado incompleto. En este caso, debemos agregar un +1 al valor para obtener el resultado correcto. Para identificar si se debe agregar el +1, tenemos que echar un vistazo al resultado del add carry. Si el número más a la izquierda 1 100 es un UNO, debemos agregar +1 al resultado para obtener el resultado correcto.
Si echamos un vistazo a tu ejemplo:
0001 (+1)
+ 1110 (-1)
------
0000 (add carry)
======
1111 (-0)
Vemos que el resultado será -0 y este será el resultado final porque el bit de arrastre de adición izquierdo es 0.