【Godot4.3】自定义数列类NumList
概述
数列是一种特殊数组。之前写过等比、等差数列、斐波那契等数列的求取函数。今天就汇总到一起,并添加其他的一些数列,比如平方数、立方数、三角形数等。
这里我首先采用以前比较喜欢的静态函数库的写法,然后在其基础上改进为基于类继承的类型体系。
等差数列和等比数列的名称
等差数列被称为算术级数(Arithmetic Sequence),因为它们的每一项是相邻两项的算术平均数(Arithmetic mean)。
等比数列被称为几何级数(Geometric Sequence),因为它们的每一项是相邻两项的几何平均数(Geometric mean)。
a,b的算数平均数 x = a + b 2 x=\frac{a+b}{2} x=2a+b,等差数列 a n = a n + 1 + a n − 1 2 a_n=\frac{a_{n+1}+a_{n-1}}{2} an=2an+1+an−1 ,所以等差数列又叫做算数级数。
a,b的几何平均数 x = a b x=\sqrt{ab} x=ab,等比数列 a n = a n + 1 a n − 1 a_n=\sqrt{a_{n+1}a_{n-1}} an=an+1an−1 ,所以等差数列又叫做几何级数。
在函数库和类中,我使用拼音dengbi
和dengcha
表示等比和等差数列,感觉比使用英文要更适合像我这样的“中国宝宝”体质。毕竟代码是拿来用的,让自己更容易理解更重要一些。
形数
通过观察几何图形(2D或3D)堆金字塔的形式,可以获得一类特殊数列,叫做形数。
三角形数就是最简单的形数,它对应于台球或保龄球的摆法。
可以很容易的得出它的规律: a n = 1 + 2 + 3.. + n a_n = 1+2+3..+n an=1+2+3..+n,也就是前n项自然数之和。
也可以看做是 a n = n × ( n + 1 ) 2 a_n=\frac{n×(n+1)}{2} an=2n×(n+1)。
平方数
a n = a 2 a_n=a^2 an=a2被称为平方数, 1 2 , 2 2 , 3 2 … n 2 1^2,2^2,3^2…n^2 12,22,32…n2,也就是: 1 , 4 , 9 , 16 , 25 … 1,4,9,16,25… 1,4,9,16,25…
观察每一项与前一项的差,就可以发现:后一项与前一项的差为 3 、 5 、 7 、 9 … 3、5、7、9… 3、5、7、9…,加上第一项1,就是奇数。
通过几何形式表示:
就可以发现一个规律:前n个奇数的和,等于 n 2 n^2 n2。
四面体数
将之前三角形数扩展到三维,就是四面体数。
其规律是: 1 + 3 + 6 + 10 + 15... 1+3+6+10+15... 1+3+6+10+15...,也就是前n个三角形数之和。
函数库代码
# ========================================================
# 名称:NumList
# 类型:静态函数库
# 简介:提供求常见数列前n项的函数
# 作者:巽星石
# Godot版本:v4.2.2.stable.official [15073afe3]
# 创建时间:2024年9月23日14:38:51
# 最后修改时间:2024年9月23日15:11:10
# ========================================================
class_name NumList
# 等比数列
# 返回前n项
static func dengbi(a1:int,bi:int,n:int) -> PackedInt32Array:
var arr:PackedInt32Array
arr.append(a1) # 第一项
for i in range(1,n):
var an = arr[arr.size()-1] # 上一项
arr.append(an * bi)
return arr
# 等差数列
# 返回前n项
static func dengcha(a1:int,cha:int,n:int) -> PackedInt32Array:
var arr:PackedInt32Array
arr.append(a1) # 第一项
for i in range(1,n):
var an = arr[arr.size()-1] # 上一项
arr.append(an + cha)
return arr
# 斐波那契数列
# 返回前n项
static func fbnq(n:int) -> PackedInt32Array:
var arr:PackedInt32Array
arr.append(1) # 第一项
for i in range(n-1):
var an = arr[arr.size()-2] + arr[arr.size()-1] if i>0 else 1
arr.append(an)
return arr
# 平方数
# 返回从start开始的n项
static func square(start:int,n:int) -> PackedInt32Array:
var arr:PackedInt32Array
for i in range(n):
var an = pow(start+i,2)
arr.append(an)
return arr
# 立方数
# 返回从start开始的n项
static func cubic(start:int,n:int) -> PackedInt32Array:
var arr:PackedInt32Array
for i in range(n):
var an = pow(start+i,3)
arr.append(an)
return arr
# 三角形数
# xn = n(n+1)/2
# 返回从start开始的n项
static func triangular_num(start:int,n:int) -> PackedInt32Array:
var arr:PackedInt32Array
for i in range(n):
var a = start+i
var an = (a * (a+1))/2
arr.append(an)
return arr
类型化改造
# ========================================================
# 名称:NumList
# 类型:类
# 简介:提供常见数列类型
# 作者:巽星石
# Godot版本:v4.3.stable.steam [77dcf97d8]
# 创建时间:2024年9月23日14:38:51
# 最后修改时间:2024年9月23日16:19:39
# ========================================================
class_name NumList
# 获取第n项
func get_item(n:int):
pass
# 获取从start开始的count项
func get_items(start:int,count:int) -> PackedInt32Array:
var arr:PackedInt32Array
for i in range(1,count+1):
arr.append(get_item(start + i - 1))
return arr
# 获取从start开始的count项和
func get_sum(start:int,count:int) -> int:
var sum:int
for i in range(1,count+1):
sum += get_item(start + i - 1)
return sum
# =============================== 等比数列 ===============================
# # a_n = a_1 * bi^{n-1}
class dengbi extends NumList:
var a1:int # 第一项
var bi:int # 公比
func _init(a1:int,bi:int) -> void:
self.a1 = a1
self.bi = bi
# 获取第n项
func get_item(n:int):
return a1 * pow(bi,n-1)
# =============================== 等差数列 ===============================
# a_n = a_1 + (n-1) * cha
class dengcha extends NumList:
var a1:int # 第一项
var cha:int # 公差
func _init(a1:int,cha:int) -> void:
self.a1 = a1
self.cha = cha
# 获取第n项
func get_item(n:int):
return a1 + (n-1) * cha
# =============================== 斐波那契数列 ===============================
# n_1 = n_2 = 1
# x_n = x_{n-1} + x_{n-2}
class fbnq extends NumList:
# 获取第n项
func get_item(n:int):
if n in [1,2]:
return 1
else:
return get_item(n-1) + get_item(n-2)
# =============================== 平方数数列 ===============================
# x_n = n^2
class square extends NumList:
# 获取第n项
func get_item(n:int):
return pow(n,2)
# =============================== 立方数数列 ===============================
# x_n = n^3
class cubic extends NumList:
# 获取第n项
func get_item(n:int):
return pow(n,3)
# =============================== 三角形数 ===============================
# x_n = n(n+1)/2
class triangular_num extends NumList:
# 获取第n项
func get_item(n:int):
return (n * (n+1)) / 2
可以看到,用类继承的形式,扩充新的数列类型,基本上只需要设定自己的一两个参数,并重写get_item()
方法就可以了。而求前N项以及前N项和这样的,根本不需要重写。
测试:
@tool
extends EditorScript
func _run():
var numlist = NumList.dengbi.new(2,2)
print(numlist.get_item(3)) # 第3项
print(numlist.get_items(3,6)) # 第3项开始的6项
print(numlist.get_sum(0,6)) # 前6项和
输出:
8
[8, 16, 32, 64, 128, 256]
64
等差数列:
var numlist = NumList.dengcha.new(2,2)
输出:
6
[2, 4, 6, 8, 10, 12]
42
斐波那契数列:
var numlist = NumList.fbnq.new()
2
[1, 1, 2, 3, 5, 8]
20
平方数:
var numlist = NumList.square.new()
9
[1, 4, 9, 16, 25, 36]
91
立方数:
var numlist = NumList.cubic.new()
27
[1, 8, 27, 64, 125, 216]
441
三角形数:
var numlist = NumList.triangular_num.new()
6
[1, 3, 6, 10, 15, 21]
56