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

Cha*_*Kim 5 python numpy python-3.5

这是 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)
Run Code Online (Sandbox Code Playgroud)

-1.2997805 如何转换为 255?

添加:从下面的评论(谢谢),我这样测试。看起来 float 已转换为 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,   0,   1], dtype=uint8)
Run Code Online (Sandbox Code Playgroud)

qwr*_*qwr 3

根据 numpy 文档,这是一个“不安全的转换” astype,意味着“可以完成任何数据转换”。他们没有说铸造是如何完成的,我在快速搜索文档时没有找到它,所以它可能依赖于实现。

我的猜测如下:首先将 32 位浮点数转换为 8 位有符号整数,默认情况下会截断为零,例如。-1.3 变为 -1。然后从无符号 8 位整数转换为 8 位无符号整数,给出值 255。类似于

float x = -1.2997805;  # Assume float is 32-bit
(uint8_t)(int8_t)x;
Run Code Online (Sandbox Code Playgroud)

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

这种事情非常令人困惑,甚至可能与平台相关(可能取决于操作系统、numpy 版本、FP 硬件决定做什么,或者处理器是否使用 2s 补码等),因此不要依赖这种行为,除非确切地知道您将在哪个平台上运行代码,无论如何,这都是糟糕的编码实践。令人惊讶的是,我找不到关于 numpy 的转换规则到底如何工作的参考。