当前位置:K88软件开发文章中心编程语言非主流编程语言Julia → 文章内容

Julia 常见问题

减小字体 增大字体 作者:佚名  来源:网上搜集  发布时间:2019-1-15 16:28:34

由 陈 创建, 最后一次修改 2016-08-12 常见问题会话和 REPL如何删除内存中的对象?Julia 没有 MATLAB 的 clear 函数;在 Julia 会话(准确来说,Main 模块)中定义了一个名字的话,它就一直在啦。如果你很关心内存使用,你可以用占内存的小的来替换大的。例如,如果 A 是个你不需要的大数组,可以先用 A = 0 来释放内存。下一次进行垃圾回收的时候,内存就会被释放了;你也可以直接调用 gc() 来回收。如何在会话中修改 type/immutable 的声明?有时候你定义了一种类型但是后来发现你需要添加一个新的域。当你尝试在 REPL 里这样做时就会出错 ERROR: invalid redefinition of constant MyTypeMain 模块里的类型不能被重新定义。当你在开发新代码时这会变得极其不方便,有一个很好的办法来处理。模块是可以用重新定义的办法来替换,所以把你的所有的代码封装在一个模块里就能够重新定义类型以及常数。你不能把类型名导入到 Main 里再去重新定义,但是你可以用模块名来解决这个问题。换句话说,当你开发的时候可以用这样的工作流 include("mynewcode.jl") # this defines a module MyModule obj1 = MyModule.ObjConstructor(a, b) obj2 = MyModule.somefunction(obj1) # Got an error. Change something in "mynewcode.jl" include("mynewcode.jl") # reload the module obj1 = MyModule.ObjConstructor(a, b) # old objects are no longer valid, must reconstruct obj2 = MyModule.somefunction(obj1) # this time it worked! obj3 = MyModule.someotherfunction(obj2, c) ...函数我把参数 x 传递给一个函数, 并在函数内修改它的值, 但是在函数外 x 的值并未发生变化, 为什么呢?假设你像这样调用函数:julia> x = 10julia> function change_value!(y) # Create a new function y = 17 endjulia> change_value!(x)julia> x # x is unchanged!10在 Julia 里, 所有的函数(包括 change_value!()) 都不能修改局部变量的所属的类。如果 x 被函数调用时被定义为一个不可变的对象(比如实数), 就不能修改; 同样地,如果 x 被定义为一个 Dict 对象,你不能把它改成 ASCIIString。但是需要主要的是: 假设 x 是一个数组(或者任何可变类型)。 你不能让 x 不再代表这个数组,但由于数组是可变的对象,你能修改数组的元素: julia> x = [1,2,3] 3-element Array{Int64,1}: 1 2 3 julia> function change_array!(A) # Create a new function A[1] = 5 end julia> change_array!(x) julia> x 3-element Array{Int64,1}: 5 2 3这里我们定义了函数 change_array!(), 把整数 5 分配给了数组的第一个元素。 当我们把 x 传读给这个函数时,注意到 x 依然是同一个数组,只是数组的元素发生了变化。我能在函数中使用 using 或者 import 吗?不行,在函数中不能使用 using 或 import。如果你要导入一个模块但只是在某些函数里使用,你有两种方案::使用 import import Foo function bar(...) ... refer to Foo symbols via Foo.baz ... end把函数封装到模块里: module Bar export bar using Foo function bar(...) ... refer to Foo.baz as simply baz .... end end using Bar类型,类型声明和构造方法什么是“类型稳定”?这意味着输出的类型是可以由输入类型预测出来。特别地,这表示输出的类型不能因输入的值的变化而变化。下面这段代码 不是 类型稳定的 function unstable(flag::Bool) if flag return 1 else return 1.0 end end这段代码视参数的值的不同而返回一个 Int 或是 Float64。 因为 Julia 无法在编译时预测函数返回值类型,任何使用这个函数的计算都得考虑这两种可能的返回类型,这样很难生成快速的机器码。为什么看似合理的运算 Julia 还是返回 DomainError?有些运算数学上讲得通但是会产生错误: julia> sqrt(-2.0) ERROR: DomainError in sqrt at math.jl:128 julia> 2^-5 ERROR: DomainError in power_by_squaring at intfuncs.jl:70 in ^ at intfuncs.jl:84这时由类型稳定造成的。对于 sqrt, 大多数用户会用 sqrt(2.0) 得到一个实数而不是得到一个复数 1.4142135623730951 + 0.0im。 也可以把 sqrt 写成当参数为负的时候返回复数,但是这将不再是 类型稳定而且 sqrt 会变的很慢。在这些情况下,你可以选择 输入类型 来得到想要的 输出类型 : julia> sqrt(-2.0+0im) 0.0 + 1.4142135623730951im julia> 2.0^-5 0.03125Julia 为什么使用本机整数运算?Julia 会应用机器运算的整数计算。这意味着 int 值的范围是有界的,是在两界之间取值的,所以添加,减去,乘以和除以一个整数都可能导致上溢或下溢,这可能会导致一些不好的后果,这种情况在一开始会让人感到很不安。 julia> typemax(Int) 9223372036854775807 julia> ans+1 -9223372036854775808 julia> -ans -9223372036854775808 julia> 2*ans 0显然,这远远不能用数学的方法来表现,您可能会认为 Julia 与一些高级编程语言会公开给用户这一情况相比来说不是那么理想。然而这对于效率和透明度都非常珍贵的数值工作来说,相比之下,替代品更是糟糕。这里有一个选择是来检查每个整数操作的溢出情况,并且由于溢出情况而提高结果值到大一些的整数类型,例如 Int128 或 BigInt。不幸的是,这就引进了在每个整数操作上都会有的主要负担(想想增加一个循环计数器) - 这需要发射代码在算术指令后执行程序时的溢出检查,并且需要一些分支来解决潜在溢出问题。更糟糕的是,这会导致每一个计算,在涉及整数时都是不稳定的。正如我们上面提到的,类型的稳定性是有效的代码生成的关键。如果您不能指望整数运算的结果是整数,那么按 C 和 Fortran 编译器方式做的简单代码,想要生成速度快是不可能的。这个方法还有一个可以避免不稳定类型外观的变化,就是把 Int 和 BigInt 合并成

[1] [2] [3] [4]  下一页


Julia 常见问题