Julia语言与其他语言的异同

在编写Julia代码的过程中,会发现与其他语言有不少相似之处,例如Matlab、R或Python,但也有着明显的不同。通过与其他语言的对比,我们可以更加深入地理解Julia,也能够在熟悉其他语言的基础上,更快地学习Julia语言。

与Python相比

Python语言与Julia同为动态语言,都有着极为高效简洁的开发风格,主要差异有:

  • Julia代码编写格式无要求

众所周知,Python在代码编写时,是需要“游标卡尺”的,格式就是语法规则的一部分,而Julia语言没有这方面的限制,以关键字对(以end结束)形成构造完整的结构。

  • Julia中没有Python中的pass关键字
  • Julia中对数组、字符串等的索引是从1开始的,而不是像Python等语言那样从0开始。
  • 数组Slice索引时,Julia取得最后的元素

在对数组进行slice索引时,Julia按slice结构包括最后一个元素,但在Python最后一个元素并不在slice中。例如Julia中的a[2:3]取得第二个及第三个元素,相当于Python中的a[1:3],这是有所不同的,需要特别注意。

  • Julia不支持负值索引

在对数组索引时,Julia不支持Python中以负值的方式按倒序取得数组中的元素。但Julia可以通过end关键字取得数组中的最后一个元素,并可通过end-n获得倒数n个元素。

  • Julia数组采用列序存储,而Python中的NumPy默认采用的则是行序存储方式。
  • 运算符%在Julia中是取余操作,在Python中则是取模操作。
  • Julia更新运算符不会就地修改原变量

需要注意的是, Julia中的更新运算符与Python有着很大的不同,包括+=,-=等,不会就地修改原变量,例如:

julia> A = [1 1 1 1]

1×4 Array{Int64,2}:

 1  1  1  1



julia> B = A;



julia> B

1×4 Array{Int64,2}:

 1  1  1  1



julia> B += 3

1×4 Array{Int64,2}:

 4  4  4  4



julia> B

1×4 Array{Int64,2}:

 4  4  4  4



julia> A

1×4 Array{Int64,2}:

 1  1  1  1

其中的A并没有被改变,只是B被改变了。运算符+=只是相当于B=B+3操作,在此过程中,B=A建立的引用关系被解除,变量名B被重新绑定到了B+3生成的新数组上。

  • Julia参数默认表达式总会重新求值

在函数采用默认参数值的情况下,在函数每次运行时,Julia都会重新执行参数值中的表达式,不像Python那样只运行一次,这会带来很大的不同。例如在Julia中:

julia> f(x =rand()) = x

f (generic function with 2 methods)



julia> f()

0.8382948989948376



julia> f()

0.8835315579456324



julia> f()

0.32548534620112024

函数f()的每一次调用,参数rand()都会被执行,导致结果出现不同。而在Python中,则有着完全不同的表现:

>>> import random

>>> def f(x = random.randint(0,100)):

...   print x

...

>>> f()

24

>>> f()

24

>>> f()

24

可见参数中虽然使用了random生成随机数,但每次f()被调用,返回的都是同一个值,这是因为Python在函数被第一次调用时,参数表中的表达式就会被计算并被固化下来。

所以,如果读者原来熟悉Python,转而学习Julia语言,对这些不同点需要非常的小心,否则很容易出现难以察觉的错误。

​​​​​​​与Matlab相比

Julia与Matlab有不少相似之处,但在功能、句法等方面又有着很多的不同,包括:

  • Julia中数组下标采用方括号,而Matlab是圆括号。
  • Julia函数传参采用共享机制,复杂结构是引用方式;而Matlab是简单的传值。
  • 数组赋值在Julia中只是将原数据绑定到了新的名字,可以认为是新的引用,所以不会像Matlab那样要新建数组并赋值数据。
  • Julia不会在对数组元素的赋值时自动增长数组

在Matlab中,a(4) =3.2会自动创建数组a=[0 0 0 3.2];而a(5)=7时,因5超出a的长度导致a被自动增长,变成 [0 0 0 3.2 7]。但在Julia中,a[5]=7对元素的赋值时,如果5超出a实际长度,会抛出异常。若要对数组增加元素,Julia通过函数push!()或append!()进行,这种方法比Matlab中的a(end+1)=val这种方式更为高效。

  • 复数虚部在Julia中的标识符为im,而Matlab采用i或j标识符。
  • Matlab默认字面值为浮点数,但Julia会自动判断其最合适的类型。
  • Julia有真实的向量结构,而不是通过矩阵模拟。
  • 范围表达式在Julia中是独立类型

在Julia中,表达式a:b或a:b:c会构造类型为Range的独立对象,而不会像Matlab那样自动展开为向量。Julia可使用collect()将Range对象变成数组,但在实际使用中一般无需这种转换,因为在大部分情况下其使用与数组是一致的。而且因为懒计算的特点,有着更高的性能。这种对数组有一定代替性的Range对象,在一些函数或迭代操作中极为常用。

  • 两者返回结果的方式不同

Julia函数会将最后一个表达式的结果返回,除非有显式的return调用。若结果是多个,Julia则会自动将之组装为Tuple类型;Matlab则采用了nargout变量,描述返回值。

  • Julia在运行期间,没有严格的工作目录的概念。
  • Julia中排序函数sort()默认按列进行

Julia对数组调用sort(A)等价于sort(A,1),如果要对1×N数组的所有元素进行排序,使用sort(A)不会获得预期效果,通过sort(A,2)才可以。

  • 两者在数组比较运算时有所不同

在Julia中,如果A与B是数组,对它们的逻辑比较操作,如A==B则并不会返回布尔型的数组,给出每个元素的比较结果,而是要用点操作的方式,即A.==B才会得到这样的比较结果。

  • 在Julia中,位运算符&(与),|(或)和⊻(异或)分别等价于Matlab中的and操作符、or操作符及xor操作符,但在操作优先级方面略有不同。
  • Julia会自动检测跨行的表达式或语句结构,并不采用省略符来连接跨行的表达式。
  • 内置变量ans在Matlab的脚本中也会起效,但Julia的脚本中会被忽略。
  • Julia中声明的类型无法在运行期间像Matlab的class那样能够动态增加成员。如果涉及,Julia中最好采用Dict类型代替。
  • Maltab中只有一个全局作用域,但在Julia中每个模块都有着自己独立的全局作用域及命名空间。
  • 两者在过滤数组元素的方式上有所不同

在Matlab中,若要移除数组中不需要的元素,需通过逻辑索引就地修改原数组,例如x(x>3)或x(x>3)=[]选择或去除值>3的元素。在Julia中,提供了专门的高阶函数filter()及filter!()可用于达到此目的,例如可使用filter(z->z>3, x)或filter!(z->z>3,x)实现上述的功能。而且此两个函数能够减少临时内存的使用,有着较高的性能。

​​​​​​​与R相比

相比R语言,Julia在性能方面有着明显的优势。两者在语法及使用上差异主要是:

  • 单引号在Julia中用于表达某个字符值,而非是字符串类型。
  • R中要获得子字符串,需先将其转换为字符向量,但Julia中可直接以索引的方式取得。
  • 取模操作在R中是a %% b,在Julia中则是mod(a,b),%用于求取余数。
  • 创建向量时,Julia的[1,2,3]等效于R中的c(1,2,3)。
  • Julia中逻辑索引需原数组维度与阶数一致

在R语言中,c(1, 2, 3, 4)[c(TRUE, FALSE, TRUE, FALSE)]或c(1, 2, 3, 4)[c(TRUE, FALSE)]均可获得c(1, 3)这样的结果。但在Julia中,[1, 2, 3, 4][[true, false]]会抛出BoundsError异常,而[1, 2, 3, 4][[true, false, true, false]]才会获得想要的结果。

  • Julia二元运算符操作数均为数组时,维度与阶数需一致

在对两个数组操作时,Julia一般要求它们的维度与阶数一致,例如[1, 2, 3, 4] + [1, 2]这样的表述会抛出错误。而R语言只要求两者重叠即可,即c(1, 2, 3, 4) + c(1, 2)是有效的。

  • Julia的map()函数与R中的lapply()类似,但参数表述有差异。
  • Julia的矢量化操作更为简单

R中的mapply(choose,11:13,1:3)类似于Julia的broadcast(binomial,11:13,1:3)。而Julia提供了更为简洁的点运算,即binomial.(11:13,1:3)便可达到相同的效果。

  • 运算符->在Julia用于定义匿名函数,但在R中用于赋值操作。
  • Julia中没有R中的<-与<<-操作符。
  • 在对向量与矩阵进行连接时,Julia使用的是hcat()、vcat()及hvcat()函数,对应于R中的c()、rbind()及cbind()函数。
  • Julia中矩阵乘法使用A*B,R中需使用A %*% B。
  • 矩阵逐元乘积Julia中使用点运算A.*B实现,R中的则是A*B。

Julia的A’等效于R中的t(A),用于求解矩阵的转置,而!操作符则用于共轭转置。

  • 在Julia中,使用if结构、for及while时,条件表达式无需圆括号
  • Julia中数值1或0不能当布尔型用
  • 获得数组阶数,Julia使用size()函数,R使用nrow()及ncol()函数。
  • Julia的类型限定更为严格

在Julia中,标量、向量及矩阵都是不同的,但R语言中标量1与向量c(1)是相同的。

  • Julia 中的diag()及diagm()与R的同名函数有着不同的功能。
  • 在Julia中,函数结果不能直接作为赋值的左操作数,例如diag(A)=ones(n)是错误的。
  • Julia有着完善的自定义类型机制,也更为灵活便捷,不像R要借助S3或S4对象。
  • Julia有着更高效的参数传递机制

函数调用时,Julia采用共享传参机制,复杂类型通过引用方式传递。与R中的传值方式相比,显然有着更为高效的性能。

  • Julia中范围表达式有独立的类型

表达式a:b在R中是向量的简洁表述,但仍是向量;但在Julia中是独立的Range类型,是一种迭代器,不会自动展开为数组,在节省内存方面有着很大的优势。

  • 两者的最大最小等函数存在差异

Julia的max()和min()函数类似于R中的pmax()及pmin()函数;而R中的max()及min()对应于Julia中的maximum()及minimum()函数。

  • 两者中矢量化计算的意义有差异

R语言的代码如果要提升性能,往往要进行矢量化改造,但Julia中的矢量化计算多是一种方便的形式,不是性能的关键。

          ------- 节选自本人新书内容:魏坤著《Julia语言程序设计》,机械工业华章图文出版。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值