Es posible diferenciar entre 0 y -0?


Sé que los valores enteros 0 y -0 son esencialmente los mismos. Pero, me pregunto si es posible diferenciar entre ellos.

Por ejemplo, ¿cómo sé si se asignó una variable -0?

bool IsNegative(int num)
{
    // How ?
}

int num = -0;
int additinon = 5;

num += (IsNegative(num)) ? -addition : addition;

¿Se guarda el valor -0 en la memoria exactamente de la misma manera que 0?

Author: Marco A., 2015-04-30

7 answers

Depende de la máquina a la que estés apuntando.

En una máquina que usa una representación de complemento 2 para enteros no hay ninguna diferencia a nivel de bits entre 0 y -0 (tienen la misma representación)

Si su máquina utiliza el complemento de uno , definitivamente podría

0000 0000   -> signed   0 
1111 1111   -> signed   −0

Obviamente estamos hablando de usar soporte nativo , los procesadores de la serie x86 tienen soporte nativo para la representación del complemento de los dos numero. El uso de otras representaciones es definitivamente posible, pero probablemente sería menos eficiente y requeriría más instrucciones.

(Como JerryCoffin también señaló: incluso si el complemento de uno se ha considerado principalmente por razones históricas, las representaciones de magnitud con signo siguen siendo bastante comunes y tienen una representación separada para cero negativo y positivo)

 110
Author: Marco A.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-07 11:28:51

Para un int (en la representación casi universal del complemento de 2) las representaciones de 0 y -0 son las mismas. (Pueden ser diferentes para otras representaciones numéricas, por ejemplo. IEEE 754 coma flotante.)

 14
Author: RichieHindle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-30 08:28:52

Comencemos con representar 0 en el complemento de 2 (por supuesto existen muchos otros sistemas y representaciones, aquí me refiero a este específico), asumiendo que 8 bits, cero es:

0000 0000

Ahora volteemos todos los bits y agreguemos 1 para obtener el complemento de 2:

1111 1111 (flip)
0000 0001 (add one)
---------
0000 0000

Tenemos 0000 0000, y esa es la representación de -0 también.

Pero tenga en cuenta que en el complemento de 1, 0 firmado es 0000 0000, pero -0 es 1111 1111.

 12
Author: Maroun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-03 07:41:15

He decidido dejar esta respuesta ya que las implementaciones de C y C++ generalmente están estrechamente relacionadas, pero de hecho no se altera al estándar de C como pensé que lo hizo. El punto sigue siendo que el estándar de C++ no especifica lo que sucede para casos como estos. También es relevante que las representaciones sin complemento de dos son extremadamente raras en el mundo real, y que incluso donde existen a menudo ocultan la diferencia en muchos casos en lugar de exponerla como algo que alguien podría espere descubrir fácilmente.


El comportamiento de ceros negativos en las representaciones de enteros en las que existen no está tan rigurosamente definido en el estándar C++ como en el estándar C. Sin embargo, cita la norma C (ISO/IEC 9899:1999) como referencia normativa en el nivel superior [1.2].

En el estándar C [6.2.6.2], un cero negativo solo puede ser el resultado de operaciones a bit, u operaciones donde un cero negativo ya está presente (por ejemplo, multiplicando o dividir cero negativo por un valor, o agregar un cero negativo a cero) - aplicar el operador unario menos a un valor de un cero normal, como en su ejemplo, por lo tanto, está garantizado para dar lugar a un cero normal.

Incluso en los casos en que puede generar un cero negativo, no hay garantía de que lo harán, incluso en un sistema que soporta cero negativo:

No se especifica si estos casos realmente generan un cero negativo o un cero normal, y si un cero negativo se convierte en un cero normal cuando se almacena en un objeto.

Por lo tanto, podemos concluir: no, no hay una manera confiable de detectar este caso. Incluso si no fuera por el hecho de que las representaciones no-doses-complemento son muy poco comunes en los sistemas informáticos modernos.

El estándar de C++, por su parte, no menciona el término "cero negativo", y tiene muy poca discusión de los detalles de la magnitud con signo y las representaciones de complemento de uno, excepto para tener en cuenta [3.9.1 párrafo 7] que están permitidos.

 9
Author: Random832,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-01 14:44:48

Si su máquina tiene representaciones distintas para -0 y +0, entonces memcmp podrá distinguirlas.

Si los bits de relleno están presentes, en realidad podría haber varias representaciones para valores que no sean cero también.

 7
Author: Ben Voigt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-30 15:45:41

En la especificación del lenguaje C++, no hay tal int como cero negativo.

El único significado que tienen esas dos palabras es el operador unario - aplicado a 0, al igual que tres más cinco es solo el operador binario + aplicado a 3 y 5.

Si hubiera un negativo cero distinto, el complemento two (la representación más común de tipos enteros) sería una representación insuficiente para las implementaciones de C++, ya que no hay manera para representar dos formas de cero.


En contraste, los puntos flotantes (después de IEEE) tienen ceros positivos y negativos separados. Se pueden distinguir, por ejemplo, al dividir 1 por ellos. Cero positivo produce infinito positivo; cero negativo produce infinito negativo.


Sin embargo, si sucede que hay diferentes representaciones de memoria del int 0 (o cualquier int, o cualquier otro valor de cualquier otro tipo), puede usar memcmp para descubrir que:

#include <string>

int main() {
    int a = ...
    int b = ...
    if (memcmp(&a, &b, sizeof(int))) {
        // a and b have different representations in memory
    }
}

De por supuesto, si esto sucediera, fuera de las operaciones de memoria directa, los dos valores seguirían funcionando exactamente de la misma manera.

 5
Author: Paul Draper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-01 13:18:36

Para simplificar me pareció más fácil de visualizar.

Type int (_32) se almacena con 32 bits . 32 bits significa 2^32 = 4294967296 valores únicos . Así:

Unsigned int rango de datos es 0 a 4.294.967.295

En caso de valores negativos depende de cómo se almacenen. En caso

En el caso de Existe el valor -0 del complemento.

 2
Author: Margus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-30 08:39:55