为何numpy.uint系列函数转换负数会得到异常大数值?
NumPy uint系列类型处理负数的行为解释
实验复现
import numpy as np matrix = np.matrix([-32, -32.0, -3.91886975727153e-15]) matrix # matrix([[-3.20000000e+01, -3.20000000e+01, -3.91886976e-15]]) np.uint(matrix) # matrix([[4294967264, 4294967264, 0]], dtype=uint32) np.around(matrix) # matrix([[-32., -32., -0.]]) np.uint(np.around(matrix)) # matrix([[4294967264, 4294967264, 0]], dtype=uint32)
使用不同uint类型的结果:
np.uint8(np.around(matrix)) # matrix([[224, 224, 0]], dtype=uint8) np.uint16(np.around(matrix)) # matrix([[65504, 65504, 0]], dtype=uint16)
行为原因解释
- 无符号整数的本质限制:NumPy的
uint系列类型(uint8/16/32等)是无符号整数类型,取值范围仅包含非负数(uint8:0255,uint16:065535,uint32:0~4294967295),不支持负数存储。 - 负数的模运算转换:当将负数转换为uint类型时,NumPy会按照模2^n的规则将负数映射到合法取值区间,其中n是该uint类型的位数:
- uint32:2^32 = 4294967296,-32转换后为
4294967296 - 32 = 4294967264 - uint8:2^8 = 256,-32转换后为
256 - 32 = 224 - uint16:2^16 = 65536,-32转换后为
65536 - 32 = 65504
- uint32:2^32 = 4294967296,-32转换后为
- 负零的处理:
np.around()输出的-0.是浮点数的特殊表示,其数值与正零等价,转换为uint类型时会被直接当作0处理,所以第三个元素结果为0。
不管是否先经过np.around()处理,只要输入是负数,转换为uint类型时都会触发上述模运算规则——因为无符号整数无法直接表示负数,只能通过循环映射的方式将负数转换到合法范围。
内容的提问来源于stack exchange,提问作者Qwerth
相关产品推荐
相关产品推荐

