Cómo convertir enteros firmados a sin firmar en python


Digamos que tengo este número i = -6884376. ¿Cómo me refiero a ella como a una variable sin signo? Algo así como {[1] } en C.

Author: Lior, 2013-12-25

4 answers

Suponiendo :

  1. Tienes representaciones de complemento de 2 en mente; y,
  2. Por (unsigned long) usted significa entero de 32 bits sin signo,

Entonces solo necesita agregar 2**32 (or 1 << 32) al valor negativo.

Por ejemplo, aplica esto a -1:

>>> -1
-1
>>> _ + 2**32
4294967295L
>>> bin(_)
'0b11111111111111111111111111111111'

La suposición #1 significa que desea que -1 se vea como una cadena sólida de 1 bits, y la suposición #2 significa que desea 32 de ellos.

Nadie más que usted puede decir cuáles son sus suposiciones ocultas, sin embargo. Si, por ejemplo, tiene representaciones de complemento de 1 en mente, entonces necesita aplicar el operador de prefijo ~ en su lugar. Los enteros de Python trabajan duro para dar la ilusión de usar una representación de complemento de 2 infinitamente ancha (como el complemento de 2 regular, pero con un número infinito de "bits de signo").

Y para duplicar lo que hace el compilador de plataforma C, puede usar el módulo ctypes:

>>> import ctypes
>>> ctypes.c_ulong(-1)  # stuff Python's -1 into a C unsigned long
c_ulong(4294967295L)
>>> _.value
4294967295L

C unsigned long pasa a ser 4 bytes en la caja que corrió esta muestra.

 63
Author: Tim Peters,
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
2013-12-25 02:47:06

Para obtener el valor equivalente a su cast de C, solo a nivel de bits y con la máscara adecuada. por ejemplo, si unsigned long es de 32 bits:

>>> i = -6884376
>>> i & 0xffffffff
4288082920

O si es de 64 bits:

>>> i & 0xffffffffffffffff
18446744073702667240

Tenga en cuenta que aunque eso le da el valor que tendría en C, sigue siendo un valor con signo, por lo que cualquier cálculo posterior puede dar un resultado negativo y tendrá que seguir aplicando la máscara para simular un cálculo de 32 o 64 bits.

Esto funciona porque aunque Python parece que almacena todos números como signo y magnitud, las operaciones bit a bit se definen como trabajando en los valores de complemento de dos. C almacena enteros en complemento de dos pero con un número fijo de bits. Los operadores bitwise de Python actúan sobre valores de complemento de dos, pero como si tuvieran un número infinito de bits: para números positivos se extienden hacia la izquierda hasta el infinito con ceros, pero los números negativos se extienden hacia la izquierda con unos. El operador & cambiará esa cadena de unos hacia la izquierda en ceros y te dejará solo con los bits eso habría encajado en el valor C.

Mostrar los valores en hexadecimal puede hacer esto más claro (y reescribí a la cadena de f como una expresión para mostrar que estamos interesados en 32 o 64 bits):

>>> hex(i)
'-0x690c18'
>>> hex (i & ((1 << 32) - 1))
'0xff96f3e8'
>>> hex (i & ((1 << 64) - 1)
'0xffffffffff96f3e8L'

Para un valor de 32 bits en C, los números positivos van hasta 2147483647 (0x7fffffff), y los números negativos tienen el bit superior establecido desde -1 (0xffffffff) hasta -2147483648 (0x80000000). Para los valores que encajan por completo en la máscara, podemos invertir el proceso en Python utilizando un máscara para eliminar el bit de signo y luego restar el bit de signo:

>>> u = i & ((1 << 32) - 1)
>>> (u & ((1 << 31) - 1)) - (u & (1 << 31))
-6884376

O para la versión de 64 bits:

>>> u = 18446744073702667240
>>> (u & ((1 << 63) - 1)) - (u & (1 << 63))
-6884376

Este proceso inverso dejará el valor sin cambios si el bit de signo es 0, pero obviamente no es un verdadero inverso porque si comenzaste con un valor que no encajaría dentro del tamaño de la máscara, esos bits desaparecerán.

 43
Author: Duncan,
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
2018-04-20 08:52:11

Python no tiene tipos sin signo incorporados. Puede usar operaciones matemáticas para calcular un nuevo int que representa el valor que obtendría en C, pero no hay un "valor sin signo" de un int de Python. Python int es una abstracción de un valor entero, no un acceso directo a un entero de tamaño de byte fijo.

 12
Author: BrenBarn,
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
2013-12-24 21:19:14

Simplemente use abs para convertir sin signo a firmado en python

 a=-12
b=abs(a)
print(b)

Salida: 12

 0
Author: Hari Prasath,
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
2018-08-17 16:40:43