np.arange的浮点步长计算不稳定问题

By | 2020年7月24日

概述

项目中有生成步长为0.01的一列数的需求,使用了np.arange,结果却出现了不同的上下界数组不同的窘况,具体如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
np.arange(37,37.63,0.01)
array([37.  , 37.01, 37.02, 37.03, 37.04, 37.05, 37.06, 37.07, 37.08,
       37.09, 37.1 , 37.11, 37.12, 37.13, 37.14, 37.15, 37.16, 37.17,
       37.18, 37.19, 37.2 , 37.21, 37.22, 37.23, 37.24, 37.25, 37.26,
       37.27, 37.28, 37.29, 37.3 , 37.31, 37.32, 37.33, 37.34, 37.35,
       37.36, 37.37, 37.38, 37.39, 37.4 , 37.41, 37.42, 37.43, 37.44,
       37.45, 37.46, 37.47, 37.48, 37.49, 37.5 , 37.51, 37.52, 37.53,
       37.54, 37.55, 37.56, 37.57, 37.58, 37.59, 37.6 , 37.61, 37.62,
       37.63])

np.arange(1,2,0.01)
array([1.  , 1.01, 1.02, 1.03, 1.04, 1.05, 1.06, 1.07, 1.08, 1.09, 1.1 ,
       1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17, 1.18, 1.19, 1.2 , 1.21,
       1.22, 1.23, 1.24, 1.25, 1.26, 1.27, 1.28, 1.29, 1.3 , 1.31, 1.32,
       1.33, 1.34, 1.35, 1.36, 1.37, 1.38, 1.39, 1.4 , 1.41, 1.42, 1.43,
       1.44, 1.45, 1.46, 1.47, 1.48, 1.49, 1.5 , 1.51, 1.52, 1.53, 1.54,
       1.55, 1.56, 1.57, 1.58, 1.59, 1.6 , 1.61, 1.62, 1.63, 1.64, 1.65,
       1.66, 1.67, 1.68, 1.69, 1.7 , 1.71, 1.72, 1.73, 1.74, 1.75, 1.76,
       1.77, 1.78, 1.79, 1.8 , 1.81, 1.82, 1.83, 1.84, 1.85, 1.86, 1.87,
       1.88, 1.89, 1.9 , 1.91, 1.92, 1.93, 1.94, 1.95, 1.96, 1.97, 1.98,
       1.99])

解决

上述前者包含下界37.63,后者却不包含2。对已这个问题,应该是由于浮点数精度造成的,目前没有找到更好的办法,仅仅用取整不用浮点数的方式解决。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
np.arange(int(37*100),int(37.63*100))/100
array([37.  , 37.01, 37.02, 37.03, 37.04, 37.05, 37.06, 37.07, 37.08,
       37.09, 37.1 , 37.11, 37.12, 37.13, 37.14, 37.15, 37.16, 37.17,
       37.18, 37.19, 37.2 , 37.21, 37.22, 37.23, 37.24, 37.25, 37.26,
       37.27, 37.28, 37.29, 37.3 , 37.31, 37.32, 37.33, 37.34, 37.35,
       37.36, 37.37, 37.38, 37.39, 37.4 , 37.41, 37.42, 37.43, 37.44,
       37.45, 37.46, 37.47, 37.48, 37.49, 37.5 , 37.51, 37.52, 37.53,
       37.54, 37.55, 37.56, 37.57, 37.58, 37.59, 37.6 , 37.61, 37.62])

np.arange(int(1*100),int(2*100))/100
array([1.  , 1.01, 1.02, 1.03, 1.04, 1.05, 1.06, 1.07, 1.08, 1.09, 1.1 ,
       1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17, 1.18, 1.19, 1.2 , 1.21,
       1.22, 1.23, 1.24, 1.25, 1.26, 1.27, 1.28, 1.29, 1.3 , 1.31, 1.32,
       1.33, 1.34, 1.35, 1.36, 1.37, 1.38, 1.39, 1.4 , 1.41, 1.42, 1.43,
       1.44, 1.45, 1.46, 1.47, 1.48, 1.49, 1.5 , 1.51, 1.52, 1.53, 1.54,
       1.55, 1.56, 1.57, 1.58, 1.59, 1.6 , 1.61, 1.62, 1.63, 1.64, 1.65,
       1.66, 1.67, 1.68, 1.69, 1.7 , 1.71, 1.72, 1.73, 1.74, 1.75, 1.76,
       1.77, 1.78, 1.79, 1.8 , 1.81, 1.82, 1.83, 1.84, 1.85, 1.86, 1.87,
       1.88, 1.89, 1.9 , 1.91, 1.92, 1.93, 1.94, 1.95, 1.96, 1.97, 1.98,
       1.99])

另外参考文献1中说可以用np.linspace,目前的测试也是正常工作的。但印象中以前好像有生成序列不连续的情况(不等间距)。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
np.linspace(1,2,(2-1)*(1/0.01)+1)
array([1.  , 1.01, 1.02, 1.03, 1.04, 1.05, 1.06, 1.07, 1.08, 1.09, 1.1 ,
       1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17, 1.18, 1.19, 1.2 , 1.21,
       1.22, 1.23, 1.24, 1.25, 1.26, 1.27, 1.28, 1.29, 1.3 , 1.31, 1.32,
       1.33, 1.34, 1.35, 1.36, 1.37, 1.38, 1.39, 1.4 , 1.41, 1.42, 1.43,
       1.44, 1.45, 1.46, 1.47, 1.48, 1.49, 1.5 , 1.51, 1.52, 1.53, 1.54,
       1.55, 1.56, 1.57, 1.58, 1.59, 1.6 , 1.61, 1.62, 1.63, 1.64, 1.65,
       1.66, 1.67, 1.68, 1.69, 1.7 , 1.71, 1.72, 1.73, 1.74, 1.75, 1.76,
       1.77, 1.78, 1.79, 1.8 , 1.81, 1.82, 1.83, 1.84, 1.85, 1.86, 1.87,
       1.88, 1.89, 1.9 , 1.91, 1.92, 1.93, 1.94, 1.95, 1.96, 1.97, 1.98,
       1.99, 2.  ])

np.linspace(37,37.63,(37.63-37)*(1/0.01)+1)
array([37.  , 37.01, 37.02, 37.03, 37.04, 37.05, 37.06, 37.07, 37.08,
       37.09, 37.1 , 37.11, 37.12, 37.13, 37.14, 37.15, 37.16, 37.17,
       37.18, 37.19, 37.2 , 37.21, 37.22, 37.23, 37.24, 37.25, 37.26,
       37.27, 37.28, 37.29, 37.3 , 37.31, 37.32, 37.33, 37.34, 37.35,
       37.36, 37.37, 37.38, 37.39, 37.4 , 37.41, 37.42, 37.43, 37.44,
       37.45, 37.46, 37.47, 37.48, 37.49, 37.5 , 37.51, 37.52, 37.53,
       37.54, 37.55, 37.56, 37.57, 37.58, 37.59, 37.6 , 37.61, 37.62,
       37.63])

参考文献:
[1] 由numpy.arange函数看双精度浮点数的精度问题:https://blog.csdn.net/Yvettre/article/details/79545629
[2] np.arange与浮点参数无法正常工作:https://www.it1352.com/1686769.html

发表回复