Numpy cross()处理object类型数组时类型转换错误的解决问询
问题描述
执行以下代码时会抛出类型转换错误:
import numpy as np u = np.array([1, 2, -1], dtype=object) v = np.array([-1, 1, 0], dtype=object) np.cross(u, v)
错误信息:
numpy._core._exceptions._UFuncOutputCastingError: Cannot cast ufunc 'multiply' output from dtype('O') to dtype('int64') with casting rule 'same_kind'
但np.dot(u, v)可以正常运行。
由于实际数据是约15位有效数字(50位二进制)的整数,使用int64会无警告溢出,因此采用dtype=object存储。目前的解决方法是将所有值转为Decimal类型:
from decimal import Decimal u = np.array(list(map(Decimal, [1, 2, -1]))) v = np.array(list(map(Decimal, [-1, 1, 0]))) np.cross(u, v)
请问是否有更优的基于NumPy的解决方法?
优化方案
1. 手动实现object dtype向量的叉乘
np.cross对object dtype的支持存在局限,但可以直接基于Python原生int的任意精度特性手动实现叉乘逻辑,无需引入额外类型:
import numpy as np def cross_object(a, b): # 针对3D向量实现 return np.array([ a[1]*b[2] - a[2]*b[1], a[2]*b[0] - a[0]*b[2], a[0]*b[1] - a[1]*b[0] ], dtype=object) u = np.array([1, 2, -1], dtype=object) v = np.array([-1, 1, 0], dtype=object) print(cross_object(u, v)) # 输出 array([1, 1, 3], dtype=object)
这种方案完全基于NumPy的object数组,运算速度比Decimal方案更快,因为Python原生int的计算效率更高。
2. 使用np.int128 dtype(平台支持时优先选择)
如果你的运行平台支持np.int128(多数x86_64架构的Linux、macOS系统都支持),50位二进制整数完全可以被int128容纳(int128最多支持127位二进制),此时能直接使用原生np.cross:
import numpy as np u = np.array([1, 2, -1], dtype=np.int128) v = np.array([-1, 1, 0], dtype=np.int128) print(np.cross(u, v)) # 输出 array([1, 1, 3], dtype=int128)
这是效率最高的方案,NumPy对原生数值类型的运算做了深度优化,且不会出现溢出问题。
3. 自定义ufunc实现批量叉乘
如果需要频繁处理多组object dtype向量的叉乘,可以用np.frompyfunc封装自定义ufunc,提升代码复用性:
import numpy as np def cross_elem(a1, a2, a3, b1, b2, b3): return (a2*b3 - a3*b2, a3*b1 - a1*b3, a1*b2 - a2*b1) cross_ufunc = np.frompyfunc(cross_elem, 6, 3) u = np.array([1, 2, -1], dtype=object) v = np.array([-1, 1, 0], dtype=object) result = cross_ufunc(u[0], u[1], u[2], v[0], v[1], v[2]) print(np.array(result, dtype=object)) # 输出 array([1, 1, 3], dtype=object)
内容的提问来源于stack exchange,提问作者Grant Robinson
相关产品推荐
相关产品推荐

