numpy.astypenp.uint8如何转换浮点数组? -1.2997805变为255

问题描述

这是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,254,255],dtype=uint8)

-1.2997805如何转换为255?

ADD:从下面的评论(谢谢)中,我进行了这样的测试。看起来浮点数已转换为int,并且完成了255模(将其读取为unsigned int8)。

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,1],dtype=uint8)

解决方法

您已转换为unsigned int 8,其中-1对应于255,-2对应于254等。 如果要获得-1,则必须使用np.int8将其转换为-2,将其转换为带符号的int8:

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

根据astype上的numpy文档,这是“不安全的转换”,表示“可能会进行任何数据转换”。他们没有说明转换是如何完成的,我也没有在文档的快速搜索中找到它,因此它可能取决于实现。

我的猜测如下:首先将32位浮点强制转换为8位有符号整数,默认情况下默认为向零截断,例如。 -1.3变为-1。然后将无符号的8位整数转换为8位的无符号整数,得到255的值。

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

这与使用(uint8_t)x直接转换为8位无符号整数不同,后者至少在我测试的平台(godbolt的x86-64 gcc)上为0。

这种事情是very confusing,甚至可能取决于平台(可能取决于操作系统,numpy版本,FP硬件决定做什么或处理器是否使用2s补码等),因此不要在没有确切知道要在哪个平台上运行代码的情况下,总是依赖于此行为,并且这仍然是不良的编码实践。令人惊讶的是,我找不到有关numpy的强制转换规则如何工作的参考。