arange 管步长,linspace 管个数,logspace 管等比。三个函数三种需求。 arange 的终点不包含,和 Python 的 range 一样。 小数序列别用 arange 数个数——浮点误差会让它多给一个或少给一个。
上一篇是一个个给值。这一篇按规则批量造,画函数图像、造测试数据全靠它。 三个函数名字很像,区别只在「你关心步长还是关心个数」。
一、arange:管步长
np.arange(5) 给 0 到 4,np.arange(1, 10, 2) 给 1、3、5、7、9。
np.arange(0, 1, 0.25) 给 0、0.25、0.5、0.75。
终点不包含,和 Python 的 range 一致。要含终点就多加一步。
三个参数是起点、终点、步长。只给一个参数时,它被当成终点,起点默认 0。
二、小数步长的坑
np.arange(0, 1, 0.1) 打出 10 个数,最后一个是 0.90000000000000002。
它理论上是 0.9,实际存的比 0.9 略大一点点——二进制存不下 0.1。
所以这个数组到底是 10 个还是 11 个,取决于浮点误差累积到哪。
小数别用 arange 数个数。要「刚好 N 个」就用 linspace。 整数序列用 arange 完全没问题,整数没有精度问题。
三、linspace:管个数
np.linspace(0, 1, 5) 给 0、0.25、0.5、0.75、1,五个数,两端都含。
步长是 (1-0)/(5-1) = 0.25——这个数是除出来的,不是累加出来的。
所以它没有累加误差。画函数图像一律用它。
endpoint=False 去掉终点,变成 0、0.2、0.4、0.6、0.8。
四、logspace:等比
np.logspace(0, 2, 3) 给 1、10、100——从 10 的 0 次方到 10 的 2 次方。
np.logspace(0, 3, 4) 给 1、10、100、1000,每次乘 10。
默认底数是 10,可以用 base 参数改成别的。
画对数坐标、造跨几个数量级的测试数据时用它。等比数列就是这个。
五、动手 Demo:从数值范围创建数组
三个函数各造几个,把小数步长的浮点误差现场打出来。 最后对比 arange 和 linspace 造同一段区间,看结果差多少。
import numpy as np
print("arange(5) %s" % np.arange(5))
print("arange(1,10,2) %s" % np.arange(1, 10, 2))
print("arange(0,1,0.25) %s" % np.arange(0, 1, 0.25))
A = np.arange(0, 1, 0.1)
print("arange 小数:%d 个,最后 %.17f" % (len(A), A[-1]))
B = np.linspace(0, 1, 10)
print("linspace :%d 个,最后 %.17f" % (len(B), B[-1]))
print("两者最后一个是否相等:%s" % (A[-1] == B[-1]))
print("linspace(0,1,5) %s" % np.linspace(0, 1, 5))
print("linspace(0,1,5,endpoint=False) %s" % np.linspace(0, 1, 5, endpoint=False))
print("logspace(0,2,3) %s" % np.logspace(0, 2, 3))
print("logspace(0,3,4) %s" % np.logspace(0, 3, 4))
实跑输出:
--------------------------------------------------------------------
从数值范围创建数组
--------------------------------------------------------------------
① arange:管步长
--------------------------------------------------------------------
arange(5):[0 1 2 3 4]
arange(1, 10, 2):[1 3 5 7 9]
arange(0, 1, 0.25):[0. 0.25 0.5 0.75]
arange 的终点不包含,和 Python 的 range 一样。
! 小数步长会有精度问题:arange(0, 1, 0.1) 最后一个可能不是 0.9 而是 0.9000000000000001。
② 小数步长的坑
--------------------------------------------------------------------
arange(0, 1, 0.1) 一共 10 个,最后一个是 0.90000000000000002。
它理论上是 0.9,实际存的比 0.9 略大一点点——上面那 17 位小数就是证据,因为二进制存不下 0.1。
要「刚好 N 个」就用 linspace,别用 arange。
! 小数别用 arange 数个数。它可能多给一个也可能少给一个,取决于浮点误差。
③ linspace:管个数
--------------------------------------------------------------------
linspace(0, 1, 5):[0. 0.25 0.5 0.75 1. ],一共 5 个,两端都含。
linspace(0, 1, 5, endpoint=False):[0. 0.2 0.4 0.6 0.8],不含终点。
步长是 (1-0)/(5-1) = 0.25,这个数是算出来的,不是累加出来的。
! linspace 的分段是「除出来的」,所以没有累加误差。画函数图像一律用它。
④ logspace:指数步长
--------------------------------------------------------------------
logspace(0, 2, 3):[ 1. 10. 100.],从 10 的 0 次方到 10 的 2 次方。
logspace(0, 3, 4):[ 1. 10. 100. 1000.],每次乘 10。
它默认底数是 10,可以用 base 参数改。
! 画对数坐标的图、造跨几个数量级的测试数据时用它。等比数列就是这个。
⑤ 三个函数怎么选
--------------------------------------------------------------------
| 你要什么 | 用哪个 |
|---|---|
| 固定步长,终点不关心 | arange |
| 固定个数,两端要卡准 | linspace |
| 等比(每次乘同一个倍数) | logspace |
一句话:arange 数步长,linspace 数个数。
! 整数序列用 arange 没问题,小数的序列一律 linspace。
A[-1] == B[-1] 给 False——这就是浮点误差的直接证据,两个「0.9」并不相等。
要判两个小数相等,别用 ==,用 abs(a - b) < 1e-9 这种写法。
30 秒实验
- 把 arange(0, 1, 0.1) 换成 arange(0, 1.1, 0.1),看元素个数变成几个。
- 用 linspace 造 100 个数,算相邻两个的差,看是不是全都是 0.01。
- 想一想:为什么 linspace 没有累加误差?
常见误区
- 小数序列用 arange 数个数:个数不确定,随浮点误差浮动。
- 以为 arange 含终点:和 range 一样不含,要含得自己加。
- 两个小数用 == 比:0.1+0.2 和 0.3 判不相等。
- linspace 第三个参数理解错:它是「个数」不是「步长」。
自测三问(点开对答案)
1. arange 和 linspace 最本质的区别? —— arange 你给步长、它算个数;linspace 你给个数、它算步长。 2. 为什么小数序列推荐用 linspace? —— 它是除法算出来的端点,没有累加误差;arange 靠累加,误差会积累。 3. logspace(0, 2, 3) 给什么? —— [1, 10, 100]。从 10 的 0 次方到 10 的 2 次方,等比三个数。范围能造了,但真实数据往往带随机性。下一篇讲随机数,还有那条铁律:给种子。
- ☐ (本篇完,下一篇 6.4 随机数组与随机种子)