You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

np.sum()与原生sum结果异常:为何float64精度反而不如float16?

NumPy数组求和的精度异常问题

我遇到一个NumPy数组求和的异常情况:数组包含正负数值,用np.sum()、Python原生sum()、循环累加、math.fsum()计算float64类型数组时,返回的都是极小的异常值;但转为float16类型后,sum()和np.sum()却能得到看似"正常"的非零结果。为什么精度更高的float64反而出现这种问题?

测试数据与代码

import numpy as np
import math

data = np.array([-0.90569317, -1.46995447, -1.74996384, -1.8867866 , -1.87511954,
   -1.57071542, -1.28009964, -0.93220921, -0.51855901, -0.20460912,
   -0.44537475, -0.2321858 ,  0.22495071, -0.07839277, -0.19347238,
   -0.37325112, -0.19082078, -0.14362223,  0.17350959,  0.29018016,
    0.67731432,  0.40419913,  0.16290318, -0.30590038, -0.97622584,
   -1.19896056, -1.76534314, -1.90852975, -1.84276997, -1.59776178,
   -1.40631598, -1.03456112, -0.05293738,  0.15388772, -0.36582663,
   -0.30218814,  0.71072453,  0.13691746, -0.16483506, -0.15157704,
   -0.14892544,  0.20161659,  0.27904342,  0.99126422,  1.30786572,
    0.55003734,  0.78496944,  0.1353265 , -0.47825463, -0.91682991,
   -1.62692942, -1.77435859, -1.76799475, -1.68844663, -1.37343609,
   -1.03562176, -0.11074234,  0.27798278, -0.12877325, -0.03172455,
    0.77754495,  0.47685307, -0.012633  , -0.01952717, -0.02376973,
    0.06108159,  0.37980437,  1.32324502,  1.50355408,  1.24634851,
    1.48021997,  1.12914762, -0.04869481, -0.74023309, -1.32464658,
   -1.56541221, -1.5574574 , -1.54632066, -1.43866555, -0.95448269,
   -0.12612164,  0.28593759,  0.07911249,  0.00857983,  0.78762104,
    0.55693151,  0.09024923, -0.03596711,  0.41692683,  0.22017782,
    0.62110032,  1.18111905,  1.67378705,  1.31369925,  1.48817478,
    1.61280016,  2.02963229,  0.41586618, -0.54454473, -1.28116028,
   -1.41055855, -1.45881774, -1.40896758, -0.74341502, -0.42097999,
    0.02714106, -0.17915372,  0.56912889,  1.50726633,  1.13922371,
    0.59670557,  0.62216096,  0.67360208,  0.83428927,  0.94353535,
    2.18554659,  2.3032778 ,  1.39748993,  0.95149016,  0.63223706,
    1.51522114,  1.68757539,  1.113238  ,  0.13691746, -0.50477067,
   -0.72591443, -1.1411556 , -1.19789992, -0.90675382, -0.41514646,
   -0.16218346,  0.06479383,  0.69057234,  0.40366881,  0.15123612,
    0.08494602,  0.23555712,  0.5770837 ,  0.79345457,  1.31475989,
    1.56188937,  1.00929512,  1.11376832,  0.9679301 ,  2.25183669,
    2.21577488,  1.60802727,  0.38775918, -0.2067304 , -0.54242345,
   -1.15547426, -1.19153607, -1.1284279 , -0.9751652 , -0.55037826,
   -0.33824995,  0.21169269, -0.00308722, -0.2629444 ,  0.03297459,
   -0.10543913, -0.12028811,  0.30237754,  0.67148079,  1.29195609,
    0.64920732,  0.48427756,  0.14752387])

不同方式的求和结果

  • 循环累加结果:1.2878587085651816e-14
  • math.fsum()结果:-9.367506770274758e-17

float16类型求和

print(sum(data.astype(np.float16)))
print(np.sum(data, dtype=np.float16))

输出:

0.0011463165283203125
0.001146

float64类型求和

print(sum(data.astype(np.float64)))
print(np.sum(data, dtype=np.float64))

输出:

1.2878587085651816e-14
0.0

问题原因解析

这不是float64的精度"失效",反而恰恰是它高精度的体现:

  1. 真实求和值接近0:数组中正负数值的总和本身就非常接近0,float64能保留这些极小的误差值,而float16因为精度有限,累加时会丢失大量小数位信息,把原本接近0的结果"凑"成了看似非零的小数值。
  2. 浮点数累加的误差特性:浮点数累加时,大数会吞噬小数的精度,但你的数组正负值相互抵消后,剩余值本身极小,float64能准确反映这个结果;float16因位数不足,无法区分极小值和真实非零值,返回的非零数实际是不准确的近似值。
  3. 累加算法差异:np.sum处理float64时可能使用成对累加等优化算法,进一步减少误差,所以直接返回0.0;原生sum和循环累加的误差稍大,返回极小非零值;math.fsum是专门优化浮点数累加误差的算法,返回的误差值更小。

简言之:float64返回的极小值才是更接近真实总和的结果,float16的非零结果是精度不足导致的虚假"正常值"。


内容的提问来源于stack exchange,提问作者LordNR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 13:09:50