Me pregunto si estoy causando problemas porque estoy asignando y convirtiendo tipos de datos incorrectamente hacia y desde matrices numpy en Python2.7.

¡Lo que estoy haciendo es leer un valor entero hdf5 de 64 bits en una matriz numpy.zeros () del tipo numpy.float64! ¡Luego escriba estos valores en otro hdf5 asignando un entero sin signo de 64 bits!

Dos ejemplos de algunos valores originales que en realidad son números de identificación (por lo que es crucial que no cambien debido a la conversión del tipo de datos):

12028545243
12004994169

Pregunta 1: ¿Será ese entero sin signo en el segundo archivo hdf5 el mismo que en el original?

¡Verifiqué esto con una pequeña submuestra pero no puedo controlar si eso es cierto para todos ellos (hay millones)!

Pregunta 2: si estoy leyendo el valor de 64 bits del archivo original en la matriz numpy con tipo de datos = float64 y luego hago algo como:

value=int(value)
value.astype(int64)

¿será ese exactamente el valor original o cambiará debido a la transformación?

Pregunta 3: ¿Python interpretará los valores como supuse como (a), (b), (c) y (d)? ¿Habrá un problema con el formato de los valores también, como el uso de anotaciones científicas 'e + 10'? ¿O Python los reconoce como el mismo valor (ya que es solo una forma diferente de mostrarlos ...)?

 1.20285452e+10 == 12028545243.0 == 12028545243 == 12028545243
 1.20049942e+10 == 12004994169.0 == 12004994169 == 12004994169
 (a)             (b)              (c)            (d)   

(a) valor listado que imprime una columna de datos con nombre de matriz:

print data[:,0] <type 'numpy.ndarray'>

(b) imprimir un solo elemento en los datos

print data[0,0] <type 'numpy.float64'>

(c) después de hacer la conversión

print int(data[0,0]) <type int>

(d) igual que (a) pero usando astype () para convertir!

print data[:,0].astype(numpy.int64) <type 'numpy.ndarray'>

Puede preguntar por qué no estoy asignando un tipo int64 a la matriz numpy para que sea seguro. Sí, lo haré, pero hay datos que ya están almacenados incorrectamente y necesito saber si aún puedo confiar en estos datos ...

Estoy usando: Python2.7, Pythonbrew, Ubuntu 14.04 LTS de 64 bits en Lenovo T410

0
firefly2517 7 mar. 2017 a las 17:46

2 respuestas

La mejor respuesta

En general, NO se guarda guardar un número entero de 64 bits en un flotante de 64 bits. Puede ver eso fácilmente, por ejemplo, mirando:

import numpy as np
print(np.int64(2**63-1))
print(np.int64(np.float64(2**63-1))

Mientras que el primero le dará el resultado correcto (9223372036854775807), el segundo tiene un error de redondeo que resulta en un desbordamiento de enteros (-9223372036854775808).

Para comprender esto, debe observar cómo se almacenan estos números. Mientras que un número entero básicamente solo almacena su valor absoluto en binario (más un bit utilizado para el signo del número), esto no se cumple para un número de coma flotante.

Un punto flotante almacena un número en tres partes. Uno es el bit de signo, el siguiente es el significativo / mantisa y el último es el exponente. El número se da como signo multiplicado por mantisa multiplicado por 2 ^ exponente. Estos tres tienen que compartir los bits disponibles (en su caso 64). Como se especifica en documentación de numpy para un np.float64 Se usan 52 bits para el significativo y 11 bits para el exponente. Por lo tanto, solo para enteros de hasta 52 bits definitivamente obtendrá el resultado correcto si los convierte a np.float64 y viceversa.

Entonces, para responder a su primera y segunda pregunta : No, no puede estar seguro de que los números sean los mismos si hay números mayores que 2**52-1 en su conjunto de datos.

Con respecto a su tercera pregunta : el formateo se realiza solo al imprimir los valores. Al comparar números internamente, los números no tienen ningún formato, de modo que todos esos valores se considerarán iguales siempre que tengan exactamente el mismo valor.

Por cierto, si desea obtener más información sobre la aritmética de coma flotante, una muy buena lectura es el artículo "Lo que todo informático debería saber sobre la aritmética de coma flotante" de David Goldberg.

0
jotasi 7 mar. 2017 a las 15:18

Depende de si Numpy convierte sus valores int64 en float64 y luego de nuevo en ints o simplemente almacena los datos int en la memoria reservada para float64. Supongo que la primera opción es verdadera. Incluso sin inspeccionar float64 interna (la bruja es algo que se debe hacer de todos modos). Está claro que float64 no puede tener una representación única para todos los 2**64 enteros diferentes, si tiene solo 2**64 códigos diferentes y necesita algunos para 0.1 y así sucesivamente. Float64 usa 52 bits para almacenar una mantisa normalizada de 53 bits de largo (el bit más significativo es un 1 implícito), por lo que si su int tiene bits distintos de cero, más de 52 bits después del primero, como con:

     5764607523034234887
   = 0x5000000000000007
   = 0b0101000000000000000000000000000000000000000000000000000000000111

(la bruja es un entero de 64 bits perfectamente fino)

La parte 0b111 al final simplemente se redondeará y se perderá después de convertirla al doble para ajustar el número en la mantisa. Esta información se perderá para siempre. Es probable que esto suceda con algunos de sus ID, ya que generalmente son números bastante grandes. Intente ajustar su matriz a int64 en su lugar.

0
sannaj 17 oct. 2017 a las 00:18