2 votes

Comment numpy.astype(np.uint8) convertit-il un tableau de flottants ? -1.2997805 est devenu 255

Voici une exécution en ipython3

In [81]: r2
Out[81]: 
array([-1.2997805, -1.4251276, -1.3047135, ..., -2.0358603, -1.9741256,
       -1.6412157], dtype=float32)

In [82]: r2.astype(np.uint8)
Out[82]: array([255, 255, 255, ..., 254, 255, 255], dtype=uint8)

Comment -1,2997805 est-il converti en 255 ?

ADD : d'après les commentaires ci-dessous (merci), j'ai testé comme ceci. il semble que le float soit converti en int, et que le modulo 255 (pour le lire en unsigned int8) soit fait.

is first convereted to int. and the it is cut using modulo(%).  
In [98]: b
Out[98]: array([-1.,  0.,  1.])

In [99]: b.astype(np.uint8)
Out[99]: array([255,   0,   1], dtype=uint8)

2voto

pygri Points 533

Vous avez converti en unsigned int 8, où -1 correspond à 255, -2 à 254 etc. Si vous voulez obtenir -1, -2, vous devez le convertir en int8 signé en utilisant np.int8 :

>>> np.float32(-2.0358603).astype(np.uint8)
254                                        
>>> np.float32(-2.0358603).astype(np.int8) 
-2

1voto

qwr Points 840

Il s'agit d'un "unsafe cast" selon la documentation de numpy sur astype ce qui signifie que "toutes les conversions de données peuvent être effectuées". Ils n'ont pas dit comment le casting est effectué exactement et je ne l'ai pas trouvé dans une recherche rapide de la documentation, donc cela peut dépendre de l'implémentation.

Mon hypothèse est la suivante : d'abord, le flottant 32 bits est converti en entier signé 8 bits, qui par défaut est tronqué vers zéro, par exemple, -1.3 devient -1. Ensuite, un entier non signé de 8 bits est converti en entier non signé de 8 bits, ce qui donne une valeur de 255. Quelque chose comme

float x = -1.2997805;  # Assume float is 32-bit
(uint8_t)(int8_t)x;

Ce n'est pas la même chose que de convertir directement en int non signé 8 bits avec (uint8_t)x qui donne 0, du moins sur la plateforme que j'ai testée (godbolt's x86-64 gcc).

Ce genre de choses est très déroutant et peut même dépendre de la plate-forme (éventuellement en fonction du système d'exploitation, de la version de numpy, de ce que le matériel FP décide de faire ou si le processeur utilise même le complément à 2, etc), donc ne vous fiez jamais à ce comportement sans savoir exactement sur quelle plate-forme vous exécuterez le code, et c'est de toute façon une mauvaise pratique de codage. Étonnamment, je n'ai pas pu trouver de référence sur le fonctionnement exact des règles de casting de numpy.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X