关于numpy.where的三类技术问题咨询:警告定位、精度设置与溢出处理
解决numpy中np.where计算溢出的三个问题
针对你使用np.where计算空间指标时遇到的RuntimeWarning: overflow encountered in exp警告,以及提出的三个问题,下面是具体的解决方案:
1. 无需手动遍历,快速获取引发溢出的x、y坐标
溢出主要来自np.exp的两个调用:当251.0 - mo ≤ 0时,-100.0/(251.0-mo)会变成很大的正数,导致np.exp溢出到inf;另外当self.p - 0.5趋近于0时,-6.93/(self.p - 0.5)的绝对值极大,也会引发溢出。我们可以直接通过掩码定位这些位置:
# 定位两个可能引发exp溢出的掩码 mask_mo_overflow = (251.0 - mo) <= 0 # mo >=251时触发第一个exp溢出 mask_p_overflow = np.abs(self.p - 0.5) < 1e-10 # p接近0.5时触发第二个exp溢出 # 合并所有溢出位置的掩码 total_overflow_mask = mask_mo_overflow | mask_p_overflow # 获取对应的y、x坐标(numpy的where返回(行索引, 列索引),对应空间数据的y、x) y_coords, x_coords = np.where(total_overflow_mask)
这样用numpy的向量化操作就能直接拿到所有溢出点的坐标,完全不需要手动遍历数组。
2. 强制np.where使用float128类型
np.where本身确实没有dtype参数,但它的输出类型由输入数组的公共 dtype 决定。所以你只需要把所有参与计算的数组先转换成float128,再传入np.where即可:
# 将所有参与计算的数组转换为float128 mo_float128 = mo.astype(np.float128) p_float128 = self.p.astype(np.float128) # 使用转换后的数组执行计算,输出自然就是float128类型 mo_arr = np.where( p_float128 > 0.5, mo_float128 + 42.5*(p_float128 - 0.5)*np.exp(-100.0/(251.0-mo_float128))*(1.0 - np.exp(-6.93/(p_float128 - 0.5))), mo_float128 ) # 如果后续需要转回原数组的类型,只需最后加一步astype # mo_arr = mo_arr.astype(mo.dtype)
3. 自定义溢出时的替换规则
要实现“正向溢出用指定值,负向溢出用其相反数”,可以先单独计算np.where中条件为True的表达式,再手动替换溢出产生的inf和-inf:
# 先计算条件成立时的表达式部分 cond_true_val = mo + 42.5*(self.p - 0.5)*np.exp(-100.0/(251.0-mo))*(1.0 - np.exp(-6.93/(self.p - 0.5))) # 定义你想要的正向溢出替换值 custom_pos_overflow_val = 1e10 # 示例值,可根据你的业务需求调整 # 替换正向溢出(正inf)为指定值,负向溢出(负inf)为其相反数 cond_true_val = np.where( np.isinf(cond_true_val) & (cond_true_val > 0), custom_pos_overflow_val, cond_true_val ) cond_true_val = np.where( np.isinf(cond_true_val) & (cond_true_val < 0), -custom_pos_overflow_val, cond_true_val ) # 最后执行np.where合并结果 mo_arr = np.where(self.p > 0.5, cond_true_val, mo)
另外,如果你想全局临时屏蔽溢出警告,可以在计算前加上:
import numpy as np with np.errstate(over='ignore'): # 这里执行你的计算代码 pass
不过更推荐上面的显式处理方式,能精准控制溢出后的数值。
内容的提问来源于stack exchange,提问作者Flash Thunder
相关产品推荐
相关产品推荐

