2. Julia:面向对象编程和函数式编程模式之争
在学习julia之前,先谈谈编程模式:面向对象编程和函数式编程模式。
网上有太多关于这两个编程模式之争的文章了。
有的认为面向对象编程效率低下,有的是面向对象编程的忠实支持者,面向对象的十四种模式让人沉醉。说实话,没个几年的磨练,理解不了面向对象编程。一个问题,一百个面向对象的编程高手,能写出一百种面向对象的设计方案。哪个是正确的呢?没有正确的方案,只有能正确运行的程序。
函数式编程,它是利器!但我的水平有限,我没有办法完全严格采用函数式编程来解决我面临的问题。但julia是不鼓励我们用面向对象的方式编程的,它鼓励函数式编程。
好了,我们开始学习julia之旅!
我要解决一个与科学计算相关的问题:飞机飞行过程噪声对环境的影响。首先要建立飞行轨迹,再根据飞行轨迹分成段,然后根据段和计算点之间的关系进行计算。一个飞机场每天可能会有上万条飞机飞行轨迹,每条飞行轨迹有约30个点组成,约十万个计算点。
来吧!让我们用Python写一段代码!
import time
a=1
t1=time.perf_counter()
for i in range(0,10000):for j in range(0,30):for k in range(0,100000):a=a+1t2=time.perf_counter()
print(a)
print(t2-t1)
在电脑前等了会,程序怎么没运行啊?好像在运行?我进入了漫长的等待中。
用Julia也写了一段。F5运行(调试模式):
function la()a=0for i=1:10000for j=1:30for k=1:100000a=a+1endendendreturn a
end@time print(la())
我又进入了漫长的等待中。先去洗点水果吃。
我真的等不下去了,Python,约1000秒。300亿个循环。我什么算法也没写呢?这个速度,再加多少集群也没用。那利用numpy矢量化吧!好!果然快了。慢慢的,我发现不会写程序了。说好的Python写程序快,工作效率高的,在哪呢?
julia,约1000000秒,我勒个去!用REPL模式运行:
30000000000 0.011406 seconds (3.82 k allocations: 211.634 KiB, 98.18% compilation time)
0.011406秒,这个速度真不慢!回头用空用C测试一下。
再加两个0试试:
3000000000000 0.011846 seconds (3.82 k allocations: 211.634 KiB, 98.44% compilation time)
居然时间不增加,什么鬼?
好吧,不管了,反正知道Julia快就行了!开始学习Julia吧。
回到我们的问题。
每个飞行轨迹点有坐标和速度、点到起点的距离、功率、倾斜角。学过面向对象的都知道,我们可以把坐标建立一个类,Point3D(x,y,z),在把轨迹点建立一个类,Profile(坐标和速度、点到起点的距离、功率、倾斜角)。有一个问题,Profile与Point3D之间的关系,是继承关系,还是组合关系呢?面向对象的工程师会对他有不同的理解。Python还支持Profile数组的矢量化计算吗?估计不行。那Julia呢。由于Julia不支持面向对象编程,所以,两个类之间只能是组合关系。突然发现,没有选择是最好的选择:
# 空间坐标
struct Point3Dx::Float64y::Float64z::Float64 # aeroplane height
end# 飞行剖面
struct ProfilePoint::Point3D # 空间位置V::Float64 # groundspeed。速度s::Float64 # distance along the ground track。点到起点的距离P::Float64 # noise-related power parameter。功率ϵ::Float64 # bank angle。倾斜角
end
# 飞行轨迹段
struct SegmentProfilebegainPf #段的起点参数endPf #段的终点参数
end
#根据飞行轨迹的集合生成飞行轨迹段的集合
function getsegment(pf) SP=[]for i =1 : length(pf)-1insert!(SP,i,SegmentProfile(pf[i],pf[i+1]))endreturn SP
end
#测试一下程序
# 构造飞行剖面数据
listpf=[Profile(Point3D(0,0,0),0,0,0,0),Profile(Point3D(300,0,0),100,300,50,0),Profile(Point3D(600,0,0),130,600,100,0),Profile(Point3D(1000,0,0),150,1000,150,0),Profile(Point3D(1500,0,0),200,1500,200,0)]print(listpf)
print("\n")
listSg=getsegment(listpf) # 根据飞行剖面数据获得飞行段数据
print(listSg)
运行一下,正确执行!
> Connecting to debugger... Done!
Profile[Profile(Point3D(0.0, 0.0, 0.0), 0.0, 0.0, 0.0, 0.0), Profile(Point3D(300.0, 0.0, 0.0), 100.0, 300.0, 50.0, 0.0), Profile(Point3D(600.0, 0.0, 0.0), 130.0, 600.0, 100.0, 0.0), Profile(Point3D(1000.0, 0.0, 0.0), 150.0, 1000.0, 150.0, 0.0), Profile(Point3D(1500.0, 0.0, 0.0), 200.0, 1500.0, 200.0, 0.0)]
Any[SegmentProfile(Profile(Point3D(0.0, 0.0, 0.0), 0.0, 0.0, 0.0, 0.0), Profile(Point3D(300.0, 0.0, 0.0), 100.0, 300.0, 50.0, 0.0)), SegmentProfile(Profile(Point3D(300.0, 0.0, 0.0), 100.0, 300.0, 50.0, 0.0), Profile(Point3D(600.0, 0.0, 0.0), 130.0, 600.0, 100.0, 0.0)), SegmentProfile(Profile(Point3D(600.0, 0.0, 0.0), 130.0, 600.0, 100.0, 0.0), Profile(Point3D(1000.0, 0.0, 0.0), 150.0, 1000.0, 150.0, 0.0)), SegmentProfile(Profile(Point3D(1000.0, 0.0, 0.0), 150.0, 1000.0, 150.0, 0.0), Profile(Point3D(1500.0, 0.0, 0.0), 200.0, 1500.0, 200.0, 0.0))]
面向对象编程与函数式编程的区别是什么?简单来说,面向对象就是把方法写到对象中,面向函数就是把方法写到对象外。面向对象就是对对象进行抽象,面向函数,就是把函数进行抽象,让函数能适应所有的对象。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
