OpenCV的cv::Mat矩阵SVD重构结果与手动计算值差异原因咨询
结论
你遇到的数值差异就是单精度浮点运算的舍入误差导致,属于OpenCV矩阵运算的正常现象,不是代码逻辑错误。
误差产生的具体环节
误差来自你手动计算的运算顺序、精度处理和OpenCV底层矩阵乘法逻辑的差异,主要有两点:
- 运算顺序不一致
你手动计算的逻辑是直接按SVD重构的数学公式,对每个项先算u[0][j] * w[j] * vt[j][0]再累加,中间只有一次乘加的舍入。
但你写的重构代码是u * cv::Mat::diag(w) * vt,OpenCV的*运算符是左结合的,实际执行顺序是:
- 第一步先算
u * cv::Mat::diag(w),得到临时矩阵,这个步骤每一个元素的计算都会做一次单精度舍入 - 第二步再用上述临时矩阵和
vt做乘法,第二次做单精度舍入
两次舍入叠加的结果就和你单次累加的计算结果有微小差异。
- 底层优化带来的精度差异
OpenCV的矩阵乘法底层默认开启SIMD向量化优化(比如x86平台的SSE/AVX指令集),部分场景还会调用FMA(融合乘加)指令:FMA指令可以在单个指令周期内完成a*b + c的运算,中间不会单独对a*b的结果做舍入,和你手动分步计算(每次乘法都先舍入到float精度再做加法)的舍入规则不一样,也会带来微小的数值偏差。
你给出的两个结果差值约为1e-9,远低于单精度float的正常相对误差上限(1e-7量级),完全符合浮点运算的误差预期。
内容的提问来源于stack exchange,提问作者Jerem
相关产品推荐
相关产品推荐

