程序员必知:对比python学julia(第二章)

简介: 程序员必知:对比python学julia(第二章)

2.1.问题描述

  二话不说,先上图:

图一、勾股定理图形 图二、勾股树

  怎么样?是不是很漂亮?勾股树是根据勾股定理绘制的可以无限重复的图形,重复多次之后呈现为树状。据说勾股树最早是由古希腊数学家毕达哥拉斯绘制,因此又称之为毕达哥拉斯树。这种图形在数学上称为分形图,它们中的一个部分与其整体或者其他部分都十分相似,分形体内任何一个相对独立的部分,在一定程度上都是整体的再现和缩影。这就是分 形图的自相似特性。

  我国古代把直角三角形称为勾股形,并且直角边中较小者为勾,另一长直角边为股,斜边为弦,所以把这个定理称为勾股定理。

  公元前 6 世纪,古希腊数学家毕达哥拉斯证明了勾股定理,因而西方人都习惯地称这个定理为毕达哥拉斯定理。

  勾股定理的定义:在平面上的一个直角三角形中,两个直角边边长的平方加起来等于斜边长的平方。

  用数学语言表达为a2+b2=c2,用图形表达如上图一所示。

  以图一中的勾股定理图为基础,让两个较小的正方形按勾股定理继续“生长”,又能画出新一代的勾股定理图,如此一直画下去,最终得到一棵完全由勾股定理图组成的树状图形(见图二) ,称其为勾股树再恰当不过。

  下面我们用Python和Julia分别绘制勾股树分形图

2.2.算法分析

  利用分形图的自相似特性,先构造出分形图的基本图形,再不断地对基本图形进行复制,就能绘制出分形图。 针对勾股树分形图,其绘制步 如下:

  (1) 先画出图一所示的勾股定理图形作为基本图形,将这一过程封装为一个绘图函数,以便迸行递归调用。

  (2) 在绘两个小正方形之前,分别以直角三角形两条直角边作为下一代勾股定理图形中直角三角形的斜边以递归方式调用绘图函数画出下一代的基本图形。

  (3) 重复执行前两步,最终可绘出一棵勾股树的分形图。由于是递归调用,需要递归的终止条件,这里设置为某一代勾股定理图的直角三角形的斜边小于某个数值时就结束递归调用。

  如图三所示,这是一棵经典勾股树分形图的绘制过程,可以看到它从一个勾股定理图开始,逐步成长为一棵茂盛的勾股树。

图三 经典勾股树绘制过

2.3.编程解题

  Python语言内置了一个绘图模块”海龟绘图(Turtle Graphics)”,非常适合绘制勾股树。

  海归绘图模块是早期的 LOGO 编程语言在 Python 语言中的实现。使用这个模块绘图时,可以把屏幕当成一块画布,通过控制一个小三角形(或小海龟)的画笔在画布上移动 从而在它前进的路径上绘制出图形。这和 Scratch 中画笔的功能类似。

  海归绘图(turtle) 模块提供一套用于绘图的函数,在使用之前要先导人 turtle 模块。

  打开 IDLE环境,在 Python Shell 窗口中使用 import 语句导人 turtle 模块:

  ]> import turtle

  输人下面一行代码:

  ]> turtle.fd(100)

  这时会出现一个标题为 Python Turtle Graphics 的窗 口 ,在窗口中央有一个小三角形图标向右移动并画出一条直线,如图四所示。

  如果看不到这个窗口,可能是被 Python Shell 窗口遮挡住了。

图四

  如果不想每次都用turtle.fd(100)这种方式,可以用下面的方式,就简洁很多:

  ]> from turtle import

  ]> fd(100)

  关于海龟绘图模块的画布坐标系统、画笔运动控制、画笔设置等,可以参考原书或网上查询相关资料,这里不再赘述。

让我们来看看最终的Pyton代码:

1 '''

2 程序:绘制勾股树

3 作者:苏秦@小海豚科学馆公众号

4 来源:图书《Python趣味编程:从入门到人工智能》

5 '//代码效果参考:http://www.zidongmutanji.com/zsjx/493083.html

''

6 from turtle import

7 from math import cos, radians

8

9 def square(b):

10 '''画正方形'''

11 for i in range(4):

12 fd(b)

13 right(90)

14

15 def draw(b):

16 '''画勾股树'''

17 if b < 50: return

18

19 square(b)

20

21 fd(b)

22 left(30)

23 draw(b cos(radians(30)))

24 square(b cos(radians(30)))

25

26 right(90)

27 fd(b cos(radians(30)))

28 draw(b cos(radians(60)))

29 square(b cos(radians(60)))

30

31 right(90)

32 fd(b cos(radians(60)))

33 right(30)

34 fd(b)

35 right(90)

36 fd(b)

37 right(90)

38

39 if name == 'main':

40 speed(0)

41 up()

42 goto(50, -250)

43 down()

44 seth(90)

45 //代码效果参考:http://www.zidongmutanji.com/zsjx/524313.html

draw(100)

  不幸的是,julia语言没有内置类似海龟绘图的模块,不过好在已经有人提供了第三方库实现类似海龟绘图的功能。这个第三方库就是Luxor,并且是开源的,开源地址在这里:https://github.com/JuliaGraphics/Luxor.jl。

  Luxor是绘制简单静态矢量图形的Julia包,它提供了用于处理形状、多边形、剪切蒙版、PNG和SVG图像、海龟图形和简单动画的基本绘图功能和实用工具。以上是Julia开发文档中的介绍原话(当然,原话是英文的),笔者觉得已经非常清晰全面,就原文照搬过来了。

  首先用我们之前介绍的方法安装Luxor包,当然最简单的方法就是在REPL环境下输入:using Luxor,如果没有安装Luxor包,编程环境会提示你没有安装该包,是否要安装,输入y,接下来跟着提示操作,就能顺利安装Luxor包。

  然后我们来看一个例子:

1 using Luxor

2 Drawing(500, 500, "my-drawing.svg")

3 origin()

4 setcolor("red")

5 circle(Point(0, 0), 100, :fill)

6 finish()

7 preview()

  这段简短的代码完成以下工作:

绘制一个500单位的正方形(通常我们称之为画布),并以SVG格式保存在“my-drawing.svg”中。

将零点从左上角移动到中心。图形引擎通常从左上角开始测量(偶尔从左下角开始),但如果从中心开始,则更容易计算出物体的位置。

origin()函数将0/0点(坐标原点)移动到图形的中心。

选择200种左右颜色中的一个(在colors .jl中定义)。

以x = 0, y = 0为圆心绘制一个半径为100个单位的圆,并用当前的颜色填充它。

完成绘制并在屏幕上显示它。(笔者注:Luxor没有图形界面,它通常打开操作系统默认浏览器显示svg文件,默认图像软件显示PNG图片等,并且该功能只在REPL环境下有效)。

  关于Luxor更多的绘图知识,不在本文的讨论范围内。这里重点介绍在Luxor中包含的海龟绘图模块。

  Luxor提供了一些基本的“海龟图形”功能。控制海龟:向前、转弯、圆形、方向、朝向、矩形、向下、向上、笔画颜色、笔画宽度和重新定位,等等,并且角度以度而不是弧度为单位(这一点与Python的海龟绘图模块不同)。

  定义一个海龟对象是这样的:turtle=Turtle().而下面的代码将绘制一条直线:

?1234using Luxorturtle=Turtle()Forward(turtle,100)finish()

  以下是海龟绘图模块的动作函数:

海龟绘图函数

对应动作

Forward

More forward by d units

Turn

Increase the turtle's rotation by n degrees

Circle

Draw filled circle centered at current pos

HueShift

Shift the Hue of the turtle's pen color by n

Message

Output text

Orientation

Set the turtle's orientation to n degrees

Pen_opacity_random

Set opacity to random value

Pencolor

Set the Red, Green, and Blue values

Pendown

Start drawing

Penup

Stop drawing

PenWidth</a>

Set the width of the line to n

Pop

Move turtle to the value stored on the stack

Push

Save the turtle's position on the stack

Randomize_saturation

Randomize the saturation of the current color

Rectangle

Draw filled rectangle centered at current pos

Reposition

Place turtle at new position

Towards

Rotate turtle to face towards a point

  具体函数的参数大家可以到这个网址查阅:

  据此我们可以用Luxor的海龟绘图模块来绘制勾股树了。打开VSCode,新建ggs.li,输入代码如下:

1 =#

2 using Luxor

3

4 function square(turtle::Turtle,b)

5 #画正方形

6 for i in 1:4

7 Forward(turtle,b)

8 Turn(turtle,-90)

9 end

10 end

11

12 function draw(turtle::Turtle,b)

13 #画勾股树'''

14 if b < 5

15 return

16 end

17 square(turtle,b)

18

19 Forward(turtle,b)

20 Turn(turtle,30)

21 draw(turtle,b cosd(30))

22 square(turtle,b cosd(30))

23

24 Turn(turtle,-90)

25 Forward(turtle,b cosd(30))

26 draw(turtle,b cosd(60))

27 square(turtle,b cosd(60))

28

29 Turn(turtle,-90)

30 Forward(turtle,b cosd(60))

31 Turn(turtle,-30)

32 Forward(turtle,b)

33 Turn(turtle,-90)

34 Forward(turtle,b)

35 Turn(turtle,-90)

36 end

37

38 function main()

39 Drawing(1000, 800, "ggs.svg")

40 origin()

41 turtle=Turtle()

42 #@svg begin

43 draw(turtle,100)

44 #end

45 finish()

46 end

47 main()

  这段代码会在代码文件同目录下生成ggs.svg文件,并绘制一幅勾股树图形。

  对比Python代码,我们可以发现它们之间没有多大差别。有一点要注意,Python的三角函数的参数是弧度,所以要用radians函数将度转换为弧度(如:cos(radians(30))),而julia分cos()、cosd()两类函数,前者的参数是单位是弧度,后者的参数单位是度。

相关文章
|
3月前
|
缓存 监控 程序员
Python中的装饰器是一种特殊类型的声明,它允许程序员在不修改原有函数或类代码的基础上,通过在函数定义前添加额外的逻辑来增强或修改其行为。
【6月更文挑战第30天】Python装饰器是无侵入性地增强函数行为的工具,它们是接收函数并返回新函数的可调用对象。通过`@decorator`语法,可以在不修改原函数代码的情况下,添加如日志、性能监控等功能。装饰器促进代码复用、模块化,并保持源代码整洁。例如,`timer_decorator`能测量函数运行时间,展示其灵活性。
37 0
|
3天前
|
算法 程序员 Python
程序员必看!Python复杂度分析全攻略,让你的算法设计既快又省内存!
在编程领域,Python以简洁的语法和强大的库支持成为众多程序员的首选语言。然而,性能优化仍是挑战。本文将带你深入了解Python算法的复杂度分析,从时间与空间复杂度入手,分享四大最佳实践:选择合适算法、优化实现、利用Python特性减少空间消耗及定期评估调整,助你写出高效且节省内存的代码,轻松应对各种编程挑战。
15 1
|
1月前
|
设计模式 JSON 程序员
豆瓣评分9.4!Python程序员必读的《流畅的Python》,放这里了!
Python 官方教程的开头是这样写的:“Python 是一门既容易上手又强大的编程语言。””这句话本身并无大碍,但需要注意的是,正因为它既好学又好用,所以很多Python程序员只用到了其强大功能的一小部分,只需要几个小时,经验丰富的程序员就能学会用 Python 写出实用的程序。 然而随着这最初高产的几个小时变成数周甚至数月,在那些先入为主的编程语言的影响下,开发者们会慢慢地写出带着“口音”的 Python 代码。即便 Python 是你的初恋,也难逃此命运。因为在学校里,亦或是那些入门书上,教授者往往会有意避免只跟语言本身相关的特性。
|
1月前
|
设计模式 JSON 程序员
豆瓣评分9.4!Python程序员必读的《流畅的Python》,放这里了!
Python 官方教程的开头是这样写的:“Python 是一门既容易上手又强大的编程语言。””这句话本身并无大碍,但需要注意的是,正因为它既好学又好用,所以很多Python程序员只用到了其强大功能的一小部分,只需要几个小时,经验丰富的程序员就能学会用 Python 写出实用的程序。 然而随着这最初高产的几个小时变成数周甚至数月,在那些先入为主的编程语言的影响下,开发者们会慢慢地写出带着“口音”的 Python 代码。即便 Python 是你的初恋,也难逃此命运。因为在学校里,亦或是那些入门书上,教授者往往会有意避免只跟语言本身相关的特性。
|
1月前
|
程序员 Python
[oeasy]python0028_女性程序员_Eniac_girls_bug_Grace
回顾上次内容,我们了解到 `.py` 文件中的代码是按顺序一行行被解释执行的,可以使用 `pdb3 hello.py` 来调试程序。此外,我们探讨了“bug”这一术语的由来,它最早是在 1947 年由 Grace Murray Hopper 发现的一只真正的飞蛾所引起的计算机故障,从此“debugging”成了查找并修复程序错误的过程。早期的程序员大多为女性,因为她们通常更加细心且有耐心,这些特质对于检查错综复杂的线路和编程工作至关重要。编程与编织有着相似之处,都需要细致和有条理的操作。最后,我们认识到 bug 的存在是程序员工作的基础,没有 bug 就不需要程序员去修正它们。
36 3
|
1月前
|
存储 JSON 程序员
Python文件操作与数据持久化:强大功能简化存储管理,助力程序员高效实现业务逻辑
【8月更文挑战第6天】数据是现代计算机程序的核心,但其存储与管理常常构成开发挑战。Python凭借其强大的文件操作与数据持久化机制,显著提升了编程效率。Python的文件处理简单直观,通过内置`open`函数即可轻松实现文本或二进制文件的读写。例如,仅需几行代码就能完成文本写入。此外,Python支持多种数据持久化方案,如文本文件、CSV、JSON及数据库操作。利用内置`json`模块,可以便捷地进行JSON数据的序列化与反序列化,实现数据的有效存储与检索。这些特性使得Python成为数据管理和存储的理想选择,让开发者能够更加专注于业务逻辑的实现。
28 0
|
2月前
|
存储 大数据 程序员
逆袭吧,程序员!Python堆与优先队列的使用秘籍,助你轻松解决复杂问题!
【7月更文挑战第9天】Python的堆和优先队列是高效工具,对比列表在删除最小元素时的O(n)复杂度,堆提供O(log n)操作。优先队列利用堆数据结构,按优先级处理元素,而非FIFO。示例中,heapq模odule创建最小堆实现任务优先级执行,显示了其在解决复杂问题时的威力,助力程序员提升效率,实现编程挑战的逆袭。
35 2
|
2月前
|
程序员 Python
程序员必看!Python闭包与装饰器的高级应用,让你的代码更优雅、更强大
【7月更文挑战第7天】Python中的闭包和装饰器是高级特性,用于增强代码功能。闭包是内部函数记住外部作用域的变量,常用于动态函数和函数工厂。示例展示了`make_multiplier_of`返回记住n值的`multiplier`闭包。装饰器则是接收函数并返回新函数的函数,用于不修改原函数代码就添加功能。`my_decorator`装饰器通过`@`语法应用到`say_hello`函数上,展示了在调用前后添加额外行为的能力。这两种技术能提升代码的优雅性和效率。
32 3
|
2月前
|
监控 程序员 持续交付
`pylint`是一个高度可配置的Python代码分析工具,它可以帮助程序员查找代码中的错误、样式问题、可能的bug以及不符合编码标准的部分。
`pylint`是一个高度可配置的Python代码分析工具,它可以帮助程序员查找代码中的错误、样式问题、可能的bug以及不符合编码标准的部分。