新闻中心
深入理解NumPy数据类型:避免数组赋值时的数据溢出问题

在使用numpy数组时,若为数组指定了不合适的`dtype`(数据类型),尤其是范围过小的整数类型如`np.uint8`,可能导致超出该类型表示范围的数值发生溢出,从而在数组赋值后出现意外的“数据改变”。本文将深入探讨numpy数据类型溢出的原理,并通过实例代码展示如何避免这一常见陷阱,确保数据完整性。
在Python的数据科学生态中,NumPy库以其高效的数值计算能力而广受欢迎。然而,初学者在使用NumPy数组时,有时会遇到一个令人困惑的问题:当将一个数组的值赋给另一个新创建的数组时,新数组中的数据却与预期不符,甚至出现完全不同的数值。这并非NumPy的“bug”,而是对数据类型(dtype)理解不足导致的数据溢出问题。
问题的根源:NumPy数据类型溢出
NumPy数组在创建时,会为其中存储的元素指定一个数据类型,例如np.int8、np.uint8、np.int32、np.float64等。每种数据类型都有其特定的取值范围。当试图将一个超出该类型表示范围的数值存储进去时,就会发生数据溢出(overflow),导致数值被截断或“环绕”(wrap around),从而得到一个看似错误的结果。
以np.uint8为例,它代表无符号8位整数(unsigned 8-bit integer)。这意味着它只能存储0到255之间的整数值。任何小于0或大于255的数值在被强制转换为np.uint8时,都会发生溢出。例如:
- 573 转换为 np.uint8:573 % 256 = 61
- 1023 转换为 np.uint8:1023 % 256 = 255 (因为1023 = 3*256 + 255)
我们可以使用np.iinfo函数来查看整数数据类型的详细信息,包括其最小值和最大值:
import numpy as np # 查看 np.uint8 的信息 print(np.iinfo(np.uint8)) # 输出: iinfo(min=0, max=255, dtype=uint8) # 查看 np.int32 的信息 print(np.iinfo(np.int32)) # 输出: iinfo(min=-2147483648, max=2147483647, dtype=int32)
案例分析:不正确的dtype导致的数据改变
考虑以下场景,一个函数旨在对三维NumPy数组进行重新排序:
import numpy as np
def reorder_problematic(points):
# 将输入数组重塑为 (4, 2)
points = points.reshape((4, 2))
# 创建空的输出数组,指定 dtype 为 np.uint8
# 这里的 dtype 是问题的关键
points_new = np.zeros((4, 1, 2), np.uint8)
# 根据和与差进行排序逻辑
add = points.sum(1)
diff = np.diff(points, axis=1)
points_new[0] = points[np.argmin(add)]
points_new[3] = points[np.argmax(add)]
points_new[1] = points[np.argmin(diff)]
points_new[2] = points[np.argmax(diff)]
return points_new
# 示例输入数据
input_data = np.array([[[ 573, 148]], [[ 25, 223]], [[ 153, 1023]], [[ 730, 863]]])
output_data = reorder_problematic(input_data)
print("原始输入数据:\n", input_data)
print("使用 problematic 函数的输出数据:\n", output_data)运行上述代码,会得到如下输出:
原始输入数据: [[[ 573 148]] [[ 25 223]] [[ 153 1023]] [[ 730 863]]] 使用 problematic 函数的输出数据: [[[ 25 223]] [[ 61 148]] [[153 255]] [[218 95]]]
可以看到,output_data中的数值与input_data完全不同。例如,573变成了61,1023变成了255。这正是由于points_new数组被声明为np.uint8类型,而input_data中的许多数值(如573, 1023, 730, 863)都超出了np.uint8的取值范围(0-255),导致在赋值时发生了溢出。
为了进一步验证,我们可以尝试将原始输入数据直接转换为np.uint8类型:
# 显式将输入数据转换为 np.uint8
test_cast = np.array([[[573, 148]],
[[25, 223]],
[[153, 1023]],
[[730, 863]]],
dtype=np.uint8)
print("输入数据强制转换为 np.uint8 后的结果:\n", test_cast)输出结果与reorder_problematic函数的输出高度吻合:
输入数据强制转换为 np.uint8 后的结果: [[[ 61 148]] [[ 25 223]] [[153 255]] [[218 95]]]
为什么基于列表的方法“有效”?
在原问题中,作者还提供了一个基于Python列表的重写版本,它似乎“修复”了这个问题:
def reorder_by_lst(points):
points = points.reshape((4, 2))
add = points.sum(1)
diff = np.diff(points, axis=1)
a = points[np.argmin(add)]
d = points[np.argmax(add)]
b = points[np.argmin(diff)]
c = points[np.argmax(diff)]
lst = [a, b, c, d]
# 这里将列表转换为 NumPy 数组,但没有指定 dtype
return np.array(lst)
output_data_lst = reorder_by_lst(input_data)
print("使用 list 函数的输出数据:\n", output_data_lst)输出结果:
Delphi 7应用编程150例 全书内容 CHM版
Delphi 7应用编程150例 CHM全书内容下载,全书主要通过150个实例,全面、深入地介绍了用Delphi 7开发应用程序的常用方法和技巧,主要讲解了用Delphi 7进行界面效果处理、图像处理、图形与多媒体开发、系统功能控制、文件处理、网络与数据库开发,以及组件应用等内容。这些实例简单实用、典型性强、功能突出,很多实例使用的技术稍加扩展可以解决同类问题。使用本书最好的方法是通过学习掌握实例中的技术或技巧,然后使用这些技术尝试实现更复杂的功能并应用到更多方面。本书主要针对具有一定Delphi基础知识
1
查看详情
使用 list 函数的输出数据: [[ 25 223] [ 730 863] [ 573 148] [ 153 1023]]
这个版本之所以“有效”,是因为在np.array(lst)这一行,我们并没有显式地指定数据类型。NumPy在将Python列表转换为数组时,会根据列表中的元素自动推断出一个最合适的数据类型。由于input_data中的值最大为1023,NumPy通常会推断出np.int32(或在某些系统上是np.int64)这样的数据类型,其取值范围远大于0-255,因此能够容纳所有原始数值,避免了溢出。
虽然这种隐式推断在某些情况下很方便,但它并不总是最佳实践,因为它可能导致:
- 不必要的内存消耗: 如果实际数据范围很小(例如都在0-100之间),但NumPy推断为np.int32,则会浪费内存。
- 不确定性: 在不同环境或NumPy版本中,推断结果可能略有不同,导致代码行为不一致。
解决方案与最佳实践
要彻底解决NumPy数组赋值时的数据溢出问题,核心在于显式地为数组指定正确且足够大的数据类型。
-
选择合适的数据类型: 根据你预期存储的数据范围,选择一个能够完全容纳这些值的数据类型。
- 整数: 如果数据是整数,并且可能包含负数,使用np.int16、np.int32或np.int64。如果只包含非负整数,可以使用np.uint16、np.uint32或np.uint64。
- 浮点数: 如果数据是浮点数,使用np.float32或np.float64。
对于本例中的坐标数据,最大值是1023,最小值是25,且都是正整数。np.int16(范围通常为-32768到32767)或np.uint16(范围0到65535)都足以容纳这些值,并且比np.int32更节省内存。
修改代码以指定正确的dtype:
import numpy as np
def reorder_fixed(points):
points = points.reshape((4, 2))
# 修正:将 dtype 从 np.uint8 改为 np.int16 或 np.uint16
# 考虑到数据最大值1023,np.uint16 是一个合适的选择
points_new = np.zeros((4, 1, 2), np.uint16)
add = points.sum(1)
diff = np.diff(points, axis=1)
points_new[0] = points[np.argmin(add)]
points_new[3] = points[np.argmax(add)]
points_new[1] = points[np.argmin(diff)]
points_new[2] = points[np.argmax(diff)]
return points_new
input_data = np.array([[[ 573, 148]], [[ 25, 223]], [[ 153, 1023]], [[ 730, 863]]])
output_data_fixed = reorder_fixed(input_data)
print("使用 fixed 函数的输出数据:\n", output_data_fixed)
print("输出数据的数据类型:", output_data_fixed.dtype)运行修正后的代码,将得到期望的输出:
使用 fixed 函数的输出数据: [[[ 25 223]] [[ 730 863]] [[ 573 148]] [[ 153 1023]]] 输出数据的数据类型: uint16
现在,output_data_fixed中的数值与原始输入数据完全一致,且数据类型为uint16。
总结
NumPy数组的数据类型(dtype)是其强大功能的核心,但也是新手常遇到的陷阱。理解每种数据类型的取值范围至关重要,特别是在创建新数组或进行类型转换时。为了避免数据溢出和意外的数值改变,请始终遵循以下最佳实践:
- 显式指定dtype: 在创建NumPy数组时,尽可能明确指定其dtype,而不是依赖NumPy的隐式推断。
-
选择合适的dtype: 根据数据可能的最大值、最小值以
及是否包含小数,选择一个既能容纳所有数据又不至于过度浪费内存的数据类型。 - 检查数据类型信息: 使用np.iinfo()(针对整数)和np.finfo()(针对浮点数)来查询数据类型的详细信息,确保所选类型能够满足需求。
通过深入理解和正确应用NumPy的数据类型,可以有效避免常见的数值处理错误,确保数据操作的准确性和可靠性。
以上就是深入理解NumPy数据类型:避免数组赋值时的数据溢出问题的详细内容,更多请关注其它相关文章!
# 都是
# 西餐厅营销推广途径
# 关键词排名优化公司排名
# 中山网站推广联盟
# 河南网站建设案例
# seo工作的不足
# 甘肃关键词优化seo
# 乌海餐饮网站建设
# 网站一般都是怎么推广的
# 哪些企业需要建设网站
# 苏州代码关键词排名
# 是一个
# python
# 如何用
# 多线程
# 重启
# 浮点数
# 可以使用
# 最小值
# 本书
# 转换为
# 为什么
# overflow
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
TikTok搜索结果不显示如何解决 TikTok搜索刷新优化方法
J*a TimerTask文件监控:HashMap状态管理与常见陷阱规避指南
ACG动漫视频网入口 ACG动漫*免费正版观看地址
b站如何看历史记录_b站观看历史找回方法
QQ邮箱网页版邮箱入口 QQ邮箱官方登录平台
mcjs网页版流畅运行 mcjs低配电脑畅玩入口
电脑IP地址怎么查 查看本机IP地址的几种方法
Python vgamepad库按键模拟:正确使用XUSB_BUTTON常量
Win11怎么开启卓越性能模式 Win11电源选项启用高性能释放硬件潜力【方法】
写好的html代码怎么运行出来_运行写好的html代码方法【教程】
cad怎么合并重叠的线段_cad清理重复重叠线条的操作方法
谷歌浏览器一键优化方案_谷歌浏览器直达主页极速不卡版
解决macOS Tkinter应用双击启动崩溃:PyInstaller打包指南
Golang如何通过reflect获取匿名字段方法_Golang reflect匿名字段方法访问技巧
AO3最新可访问网址 Archive of Our Own官方在线入口
深入理解Go语言中Map值与方法接收器的交互:为什么需要临时变量
汽水音乐在线版入口_汽水音乐网页播放手册
天猫2025双十一0点秒杀攻略 天猫爆款抢购时间
Win10文件资源管理器“此电脑”分组怎么关 Win10恢复经典视图【技巧】
小红书怎么解除第三方平台绑定_小红书多平台登录解绑方法介绍
Descript怎样用AI剪辑自动去噪_Descript用AI剪辑自动去噪【自动降噪】
如何在低配置电脑上搭建轻量级J*a环境_占用更小的环境选择技巧
学习通网页版官方登录 超星学习通电脑端入口指南
解决 Express.js 中 PUT 请求密码修改失败的路由配置指南
极速漫画官方主页网址 极速漫画漫画在线浏览官网链接
在Pyomo中实现基于变量的条件约束:Big-M方法详解
快速CSGO开箱网站指南 CSGO开箱平台推荐
QQ邮箱在线使用入口 QQ邮箱个人账号网页版登录
React/Next.js中实现列表项的动态移动与状态管理:兼论唯一键的重要性
理解Python模块与全局变量的作用域管理
c++项目目录结构应该如何组织_c++工程化项目结构规范
PrimeNG Sidebar背景色自定义指南:CSS覆盖与主题化实践
word中如何让数字纵向排列_Word数字纵向排列方法
C++如何使用AddressSanitizer(ASan)_C++调试工具中检测内存访问错误的利器
漫画星球免费下拉式入口 漫画星球免费漫画在线阅读网站
css卡片内容溢出如何处理_使用overflow隐藏或scroll显示内容
零跑汽车11月交付量达70327台 实现连续9个月正增长
Lar*el的路由模型绑定怎么用_Lar*el Route Model Binding简化控制器逻辑
AO3最新入口2025公告_AO3中文官网合集
美团外卖商家服务中心入口 美团商家版官网入口
深入理解J*aScript中的B样条曲线与节点向量生成
在Qt QML中通过Python字典动态更新TextEdit内容的教程
c++中的const_cast和reinterpret_cast怎么用_c++四种类型转换
《GTA6》开发画面疑似泄露!这次可不是AI了
自定义Bag-of-Words实现:处理带负号的词汇权重
Win10怎么制作U盘启动盘 Win10系统安装U盘制作教程【详解】
Lar*el 8 多关键词数据库搜索优化实践
外媒分析《GTA6》定价:卖100美元可以但真没必要!
如何在复杂的电商平台中优雅地管理共享资源并确保正确重定向,使用spryker-shop/resource-share-page模块助你一臂之力
Win10快速启动功能利弊分析 Win10开启或关闭快速启动教程【技巧】


2025-12-08
浏览次数:次
返回列表
及是否包含小数,选择一个既能容纳所有数据又不至于过度浪费内存的数据类型。