假设我有一个n只能输入值的整数[0, 10].我应该声明它n::Int是关于它的一般性,n::Int8还是n::UInt8简约或n::Int6464位系统?
请说明新手的原因,例如风格,表现.
背景:我特林学习朱莉娅并迅速迷失在类的字眼type,immutable,syntactic sugar!我想我读过这个:https://docs.julialang.org/en/release-0.5/manual/integers-and-floating-point-numbers/
Ste*_*ski 13
区分两种不同的情况很重要.
存储:如果您的类型存储n为其中一个字段,或者作为数组中的值存储,那么您一定要考虑使用Int8或UInt8.即使单个值的节省空间可以忽略不计,如果创建了许多类型的实例并将其存储在集合中,那么节省的空间也会迅速变得显着.假设您有一个Foo带字段的类型n,那么您可以这样做:
struct Foo
n::UInt8
end
Run Code Online (Sandbox Code Playgroud)
将值分配给对象的n字段时Foo,它将自动转换为UInt8,如果无法忠实转换该值,则会引发错误:
julia> Foo(123) # Ints are automatically converted to UInt8
Foo(0x7b)
julia> typeof(ans.n)
UInt8
julia> Foo(500) # if too large, an error is raised
ERROR: InexactError()
Stacktrace:
[1] Foo(::Int64) at ./REPL[1]:2
julia> Foo(-1) # ditto if too small
ERROR: InexactError()
Stacktrace:
[1] Foo(::Int64) at ./REPL[1]:2
julia> Foo(2?/?)
Foo(0x02)
Run Code Online (Sandbox Code Playgroud)
如果分配的值已经是正确的类型,则不需要检查,因此没有开销.
Dispatch:如果你正在编写一个n以参数形式出现的函数的方法,那么在n参数上放置一个类型注释就像在语义上有意义一样没有坏处.在您描述的情况下,似乎任何类型的整数值都是合理的,因此使用n::Integer可能是合适的.例如,如果想要为Foo对象实现已检查的构造函数,则可以执行以下操作:
struct Foo
n::UInt8
function Foo(n::Integer)
0 <= n <= 10 || throw(ArgumentError("n not in [0, 10]: $n"))
return new(n)
end
end
Run Code Online (Sandbox Code Playgroud)
现在,如果给出[0,10]之外的值,则抛出错误:
julia> Foo(123)
ERROR: ArgumentError: n not in [0, 10]: 123
Stacktrace:
[1] Foo(::Int64) at ./REPL[26]:2
julia> Foo(3)
Foo(0x03)
Run Code Online (Sandbox Code Playgroud)
这种Foo结构适用于任何类型的整数,检查它是否在正确的范围内,然后转换为UInt8.这比内置构造函数稍微有点限制Foo,它会很乐意接受任何类型的n参数并尝试将其转换为UInt8- 即使参数不是整数类型.如果需要这种行为,你可以进一步放松类型签名n::Real,n::Number(或者甚至n::Any,虽然这似乎过多).
请注意,紧密键入的方法参数没有性能优势 - 实际参数类型的专用代码无论如何都是按需生成的.