C#中保留二维数组指定半径圆形区域内的值,寻求更优实现方案
二维数组圆形区域值保留的优化方案
问题背景
原二维数组可视化如下:
1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 *5* 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
需要保留以第三行第五列的5为中心、半径为2的圆形范围内的值,处理后结果应为:
0 0 0 0 *5* 0 0 0 0 0 0 0 0 *4 5 6* 0 0 0 0 0 0 *3 4 5 6 7* 0 0 0 0 0 0 *4 5 6* 0 0 0 0 0 0 0 0 *5* 0 0 0 0 0
当前实现逻辑为遍历所有单元格,用勾股定理计算与中心的距离,距离≤2则保留原值,否则设为0。处理100×100数组耗时约0.1秒(4.2GHz CPU),希望找到更优实现方式。
优化方案
1. 向量化矩阵操作(推荐)
利用数值计算库(如NumPy)的向量化能力,避免Python层面的循环,直接对整个数组进行批量运算:
- 先创建坐标网格,一次性计算所有单元格到中心的距离平方(省去开根号的浮点运算,直接比较平方值等价于比较距离);
- 生成布尔掩码矩阵,标记需要保留的区域;
- 将原数组与掩码做元素级乘法,得到结果。
示例代码:
import numpy as np # 构造原数组 arr = np.array([[1,2,3,4,5,6,7,8,9,0] for _ in range(5)]) center_y, center_x = 2, 4 # 中心坐标(索引从0开始) radius = 2 # 生成坐标网格 y_grid, x_grid = np.ogrid[:arr.shape[0], :arr.shape[1]] # 计算距离平方 dist_squared = (y_grid - center_y) ** 2 + (x_grid - center_x) ** 2 # 创建掩码:距离平方 ≤ 半径平方的位置为True mask = dist_squared <= radius ** 2 # 应用掩码,保留目标区域值,其余设为0 result = arr * mask
这种方式的运算由底层C实现,速度远快于Python循环,100×100数组的处理时间可忽略不计。
2. 缩小遍历范围
无需遍历整个数组,仅针对中心周围的矩形区域(行范围:[center_y-radius, center_y+radius],列范围:[center_x-radius, center_x+radius])进行遍历计算。对于半径2的场景,只需遍历25个单元格,相比遍历整个100×100数组,运算量减少99.75%,即使不用数值库也能显著提速。
3. 省略开根号运算
比较距离平方与半径平方,替代计算实际距离。勾股定理中的开根号是冗余操作,平方后的比较结果与原距离比较完全一致,能减少浮点运算开销,提升单步计算速度。
内容的提问来源于stack exchange,提问作者Priyansh Yadav
相关产品推荐
相关产品推荐

