numpy.astype(np.uint8)如何转换一个浮点数组?-1.2997805变成255

3 人关注

这是在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)

how is -1.2997805 converted to 255?

ADD : 从下面的评论(谢谢),我是这样测试的。看起来浮点数被转换为int,然后做了modulo 255(把它读成无符号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,   0,   1], dtype=uint8)
    
5 个评论
这是否回答了你的问题? numpy数组中的整数溢出
qwr
@MykolaZotko没有回答这个与numpy如何进行不安全转换有关的具体案例
uint8 类型涵盖了从0到255的范围。超出这个范围的负值会变成255。
qwr
我的猜测是,它首先将有符号整数转换为-1,然后将无符号整数转换为255。
qwr
@MykolaZotko并没有解释为什么-2是254。
python
numpy
python-3.5
Chan Kim
Chan Kim
发布于 2020-10-12
3 个回答
pygri
pygri
发布于 2021-08-28
已采纳
0 人赞同

你转换为无符号int8,其中-1对应255,-2对应254等等。 如果你想得到-1,-2,你必须用np.int8将其转换为有符号的int8。

>>> np.float32(-2.0358603).astype(np.uint8)
>>> np.float32(-2.0358603).astype(np.int8) 
    
qwr
qwr
发布于 2021-08-28
0 人赞同

根据numpy的文档,这是一个 "不安全的投射"。 astype ,意思是 "可以进行任何数据转换"。他们没有说具体是如何进行转换的,我在快速搜索文档时也没有发现,所以这可能取决于实现。

我的猜测是:首先,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位无符号int不一样,至少在我测试的平台上(godbolt的x86-64 gcc)给出了0。

This kind of thing is very confusing甚至可能取决于平台(可能取决于什么操作系统、numpy版本、FP硬件决定做什么或者处理器是否使用2s补码等等),所以在不清楚你将在什么平台上运行代码的情况下,千万不要依赖这种行为,而且无论如何这都是很差的编码实践。令人惊讶的是,我找不到关于numpy的铸造规则到底是如何工作的参考资料。

Ameya Kulkarni
Ameya Kulkarni
发布于 2021-08-28
0 人赞同

其他答案已经解决并解释了这个问题。不过,我可以提出一个可能有实际意义的替代方案。

np.uint8(np.clip(x, 0, 255))

其中x是你的浮动型数组。

This method ensures negative numbers become 0, and huge positive numbers (> 255) become 255.