前几日分享了juila的一些特性和安装,今天让我们来学一下这个基本的语法。我的主要的参考文档来自于:
http://web.mit.edu/julia_v0.6.0/julia/share/doc/julia/html/en/manual/integers-and-floating-point-numbers.html
官方文档,英文版的。这个教程我就不逐字逐句的翻译并写到这里了,我只写一些我自己感觉是有用的东西。
我觉得对于任何一门编程语言来说,它的数据类型都是要实熟悉的。
整数和浮点值是算术和计算的基本构建块。这种值的内置表示形式称为数字原语,而整数和浮点数的表示形式作为代码中的立即值称为数字文字。例如,1
是整数文字,1.0
而是浮点文字;它们作为对象的二进制内存表示形式是数字基元。
Julia提供了多种原始数字类型,并且在它们之上定义了算术和按位运算符以及标准数学函数的完整补充。这些直接映射到现代计算机本身支持的数字类型和运算上,从而使Julia可以充分利用计算资源。此外,Julia为Arbitrary Precision Arithmetic提供了软件支持,该软件可以处理无法在本机硬件表示中有效表示的数值上的运算,但会以相对较慢的性能为代价。
以下是Julia的原始数字类型:
类型 | 支持? | 位数 | 最小值 | 最大值 |
---|---|---|---|---|
Int8 | ✓ | 8 | -2 ^ 7 | 2 ^ 7-1 |
UInt8 | 8 | 0 | 2 ^ 8-1 | |
Int16 | ✓ | 16 | -2 ^ 15 | 2 ^ 15-1 |
UInt16 | 16 | 0 | 2 ^ 16-1 | |
Int32 | ✓ | 32 | -2 ^ 31 | 2 ^ 31-1 |
UInt32 | 32 | 0 | 2 ^ 32-1 | |
Int64 | ✓ | 64 | -2 ^ 63 | 2 ^ 63-1 |
UInt64 | 64 | 0 | 2 ^ 64-1 | |
Int128 | ✓ | 128 | -2 ^ 127 | 2 ^ 127-1 |
UInt128 | 128 | 0 | 2 ^ 128-1 | |
Bool | 不适用 | 8 | false (0) | true (1) |
类型 | 精确 | 位数 |
---|---|---|
Float16 | 半 | 16 |
Float32 | 单 | 32 |
Float64 | 双 | 64 |
此外,在这些原始数字类型的基础上,全面支持复杂和有理数。得益于灵活的,用户可扩展的类型升级系统,所有数字类型都可以自然地互操作而无需显式转换。
文字整数以标准方式表示:
julia> 1
1
julia> 1234
1234
整数文字的默认类型取决于目标系统是32位体系结构还是64位体系结构:
# 32-bit system:
julia> typeof(1)
Int32
# 64-bit system:
julia> typeof(1)
Int64
Julia内部变量Sys.WORD_SIZE
指示目标系统是32位还是64位:
# 32-bit system:
julia> Sys.WORD_SIZE
32
# 64-bit system:
julia> Sys.WORD_SIZE
64
Julia还定义了类型Int
和UInt
,分别是系统的有符号和无符号本机整数类型的别名:
# 32-bit system:
julia> Int
Int32
julia> UInt
UInt32
# 64-bit system:
julia> Int
Int64
julia> UInt
UInt64
无论系统类型如何,不能仅使用32位表示但可以用64位表示的较大整数文字总是会创建64位整数:
# 32-bit or 64-bit system:
julia> typeof(3000000000)
Int64
使用0x
前缀和十六进制(以16为基)数字输入和输出无符号整数0-9a-f
(大写数字A-F
也可用于输入)。无符号值的大小取决于所使用的十六进制数字的数量:
julia> 0x1
0x01
julia> typeof(ans)
UInt8
julia> 0x123
0x0123
julia> typeof(ans)
UInt16
julia> 0x1234567
0x01234567
julia> typeof(ans)
UInt32
julia> 0x123456789abcdef
0x0123456789abcdef
julia> typeof(ans)
UInt64
此行为基于以下观察结果:当人们使用无符号十六进制文字作为整数值时,通常是使用它们来表示固定的数字字节序列,而不仅仅是整数。
回想一下,该变量ans
已设置为在交互式会话中评估的最后一个表达式的值。当以其他方式运行Julia代码时,不会发生这种情况。
还支持二进制和八进制文字:
julia> 0b10
0x02
julia> typeof(ans)
UInt8
julia> 0o10
0x08
julia> typeof(ans)
UInt8
原始数字类型(例如整数)的最小和最大可表示值由typemin()
和typemax()
函数给出:
julia> (typemin(Int32), typemax(Int32))
(-2147483648, 2147483647)
julia> for T in [Int8,Int16,Int32,Int64,Int128,UInt8,UInt16,UInt32,UInt64,UInt128]
println("$(lpad(T,7)): [$(typemin(T)),$(typemax(T))]")
end
Int8: [-128,127]
Int16: [-32768,32767]
Int32: [-2147483648,2147483647]
Int64: [-9223372036854775808,9223372036854775807]
Int128: [-170141183460469231731687303715884105728,170141183460469231731687303715884105727]
UInt8: [0,255]
UInt16: [0,65535]
UInt32: [0,4294967295]
UInt64: [0,18446744073709551615]
UInt128: [0,340282366920938463463374607431768211455]
typemin()
和返回的值typemax()
始终是给定的参数类型。(上面的表达式使用了我们尚未介绍的几个功能,包括for循环,Strings和Interpolation,但是对于具有一些已有编程经验的用户来说,应该足够容易理解。)
在Julia中,超过给定类型的最大可表示值会导致环绕行为:
julia> x = typemax(Int64)
9223372036854775807
julia> x + 1
-9223372036854775808
julia> x + 1 == typemin(Int64)
true
因此,具有Julia整数的算术实际上是模数算术的一种形式。这反映了在现代计算机上实现的整数基础算术的特征。在可能发生溢出的应用中,显式检查溢出产生的环绕是必不可少的。否则,建议改用“ 任意精度算术”中的BigInt
类型。
整数除法(div
函数)有两种特殊情况:除以零,以及将最低的负数(typemin()
)除以-1。这两种情况都引发了DivideError
。余数和模数函数(rem
和mod
)DivideError
在第二个参数为零时抛出a 。
文字浮点数以标准格式表示:
julia> 1.0
1.0
julia> 1.
1.0
julia> 0.5
0.5
julia> .5
0.5
julia> -1.23
-1.23
julia> 1e10
1.0e10
julia> 2.5e-4
0.00025
以上结果均为Float64
数值。Float32
可以通过写一个f
代替来输入文字值e
:
julia> 0.5f0
0.5f0
julia> typeof(ans)
Float32
julia> 2.5f-4
0.00025f0
值可以Float32
轻松转换为:
julia> Float32(-1.5)
-1.5f0
julia> typeof(ans)
Float32
十六进制浮点文字也有效,但仅作为Float64
值使用:
julia> 0x1p0
1.0
julia> 0x1.8p3
12.0
julia> 0x.4p-1
0.125
julia> typeof(ans)
Float64
还支持半精度浮点数(Float16
),但它们在软件中实现并Float32
用于计算。
julia> sizeof(Float16(4.))
2
julia> 2*Float16(4.)
Float16(8.0)
下划线_
可以用作数字分隔符:
julia> 10_000, 0.000_000_005, 0xdead_beef, 0b1011_0010
(10000, 5.0e-9, 0xdeadbeef, 0xb2)
浮点数有两个零,正零和负零。它们彼此相等,但是具有不同的二进制表示形式,如使用bits
函数可以看到的:
julia> 0.0 == -0.0
true
julia> bits(0.0)
"0000000000000000000000000000000000000000000000000000000000000000"
julia> bits(-0.0)
"1000000000000000000000000000000000000000000000000000000000000000"
有三个指定的标准浮点值,它们与实数线上的任何点都不对应:
Float16 | Float32 | Float64 | 名称 | 描述 |
---|---|---|---|---|
Inf16 | Inf32 | Inf | 正无穷大 | 大于所有有限浮点值的值 |
-Inf16 | -Inf32 | -Inf | 负无穷大 | 小于所有有限浮点值的值 |
NaN16 | NaN32 | NaN | 不是数字 | 不==等于任何浮点值的值(包括其自身) |
有关这些非有限浮点值如何相对于彼此和其他浮点排序的进一步讨论,请参见“ 数值比较”。根据IEEE 754标准,这些浮点值是某些算术运算的结果:
julia> 1/Inf
0.0
julia> 1/0
Inf
julia> -5/0
-Inf
julia> 0.000001/0
Inf
julia> 0/0
NaN
julia> 500 + Inf
Inf
500 - Inf
-Inf
julia>
julia> Inf + Inf
Inf
julia> Inf - Inf
NaN
julia> Inf * Inf
Inf
julia> Inf / Inf
NaN
julia> 0 * Inf
NaN
该typemin()
和typemax()
功能也适用于浮点类型:
julia> (typemin(Float16),typemax(Float16))
(-Inf16, Inf16)
julia> (typemin(Float32),typemax(Float32))
(-Inf32, Inf32)
julia> (typemin(Float64),typemax(Float64))
(-Inf, Inf)
大多数实数不能用浮点数精确表示,因此,出于许多目的,重要的是要知道两个相邻的可表示浮点数之间的距离,这通常称为机器epsilon。
Julia提供了eps()
,它给出了1.0
与下一个更大的可表示浮点值之间的距离:
julia> eps(Float32)
1.1920929f-7
julia> eps(Float64)
2.220446049250313e-16
julia> eps() # same as eps(Float64)
2.220446049250313e-16
这些值是2.0^-23
与2.0^-52
作为Float32
和Float64
值分别为,。该eps()
函数还可以将浮点值用作参数,并给出该值和下一个可表示的浮点值之间的绝对差。也就是说,eps(x)
产生相同类型的一个值x
,使得x + eps(x)
是下一个可表示浮点值大于x
:
julia> eps(1.0)
2.220446049250313e-16
julia> eps(1000.)
1.1368683772161603e-13
julia> eps(1e-27)
1.793662034335766e-43
julia> eps(0.0)
5.0e-324
两个相邻的可表示浮点数之间的距离不是恒定的,但对于较小的值则较小,而对于较大的值较大。换句话说,可表示的浮点数在实数线中接近零的位置最密集,并且随着一个人远离零而呈指数增长。根据定义,eps(1.0)
与之相同,eps(Float64)
因为1.0
它是64位浮点值。
Julia还提供nextfloat()
和prevfloat()
函数,分别将下一个最大或最小的可表示浮点数返回给参数:
julia> x = 1.25f0
1.25f0
julia> nextfloat(x)
1.2500001f0
julia> prevfloat(x)
1.2499999f0
julia> bits(prevfloat(x))
"00111111100111111111111111111111"
julia> bits(x)
"00111111101000000000000000000000"
julia> bits(nextfloat(x))
"00111111101000000000000000000001"
此示例突出了一般原理,即相邻的可表示浮点数也具有相邻的二进制整数表示形式。
如果数字没有精确的浮点表示形式,则必须将其四舍五入为合适的可表示值,但是,如果需要,可以根据IEEE 754中提供的四舍五入模式更改进行四舍五入的方式标准。
julia> x = 1.1; y = 0.1;
julia> x + y
1.2000000000000002
julia> setrounding(Float64,RoundDown) do
x + y
end
1.2
使用的默认模式始终为RoundNearest
,四舍五入到最接近的可表示值,并用最小有效位向四舍五入到最接近的值。
警告
舍入通常是唯一正确的基本的算术函数(+()
,-()
,*()
,/()
和sqrt()
)和类型转换操作。许多其他函数假定RoundNearest
已设置默认模式,并且在其他取整模式下运行时可能会给出错误的结果。
为了允许使用任意精度的整数和浮点数进行计算,Julia分别包装了GNU多精度算术库(GMP)和GNU MPFR库。Julia中的BigInt
和BigFloat
类型分别适用于任意精度的整数和浮点数。
存在构造器以从原始数值类型创建这些类型,并且parse()
可以使用构造器从AbstractString
s 构造它们。一旦创建,由于Julia的类型提升和转换机制,它们可以与所有其他数字类型一起参与算术运算:
julia> BigInt(typemax(Int64)) + 1
9223372036854775808
julia> parse(BigInt, "123456789012345678901234567890") + 1
123456789012345678901234567891
julia> parse(BigFloat, "1.23456789012345678901")
1.234567890123456789010000000000000000000000000000000000000000000000000000000004
julia> BigFloat(2.0^66) / 3
2.459565876494606882133333333333333333333333333333333333333333333333333333333344e+19
julia> factorial(BigInt(40))
815915283247897734345611269596115894272000000000
但是,上述原始类型和BigInt
/ 之间的类型提升BigFloat
不是自动的,必须明确说明。
julia> x = typemin(Int64)
-9223372036854775808
julia> x = x - 1
9223372036854775807
julia> typeof(x)
Int64
julia> y = BigInt(typemin(Int64))
-9223372036854775808
julia> y = y - 1
-9223372036854775809
julia> typeof(y)
BigInt
BigFloat
可以通过调用setprecision()
和来全局更改默认精度(有效位数)和舍入模式setrounding()
,并且所有进一步的计算都将考虑这些更改。另外,精度或舍入只能在特定代码块的执行中通过与do
块使用相同的函数来更改:
julia> setrounding(BigFloat, RoundUp) do
BigFloat(1) + parse(BigFloat, "0.1")
end
1.100000000000000000000000000000000000000000000000000000000000000000000000000003
julia> setrounding(BigFloat, RoundDown) do
BigFloat(1) + parse(BigFloat, "0.1")
end
1.099999999999999999999999999999999999999999999999999999999999999999999999999986
julia> setprecision(40) do
BigFloat(1) + parse(BigFloat, "0.1")
end
1.1000000000004
为了使常用的数字公式和表达式更清晰,Julia允许变量在数字文字之后立即加前缀,这意味着乘法。这使得编写多项式表达式更加简洁:
julia> x = 3
3
julia> 2x^2 - 3x + 1
10
julia> 1.5x^2 - .5x + 1
13.0
这也使编写指数函数更加优雅:
julia> 2^2x
64
数字文字系数的优先级与一元运算符(如取反)的优先级相同。因此2^3x
被解析为2^(3x)
,并且2x^3
被解析为2*(x^3)
。
数值文字也可以作为括号表达式的系数:
julia> 2(x-1)^2 - 3(x-1) + 1
3
此外,带括号的表达式可以用作变量的系数,这意味着表达式与变量相乘:
julia> (x-1)x
6
但是,两个带括号的表达式并列,或者在带括号的表达式之前放置变量都不能用来表示乘法:
julia> (x-1)(x+1)
ERROR: MethodError: objects of type Int64 are not callable
julia> x(x+1)
ERROR: MethodError: objects of type Int64 are not callable
这两个表达式都被解释为函数应用程序:任何非数字文字的表达式,当其后紧跟一个括号时,都将被解释为应用于括号中值的函数(有关函数的更多信息,请参见函数)。因此,在这两种情况下,由于左侧的值不是函数,因此会发生错误。
以上语法增强功能显着降低了编写常用数学公式时产生的视觉噪声。请注意,数字文字系数与其相乘的标识符或括号表达式之间不得包含空格。
并置的文字系数语法可能与两个数字文字语法冲突:十六进制整数文字和浮点文字的工程符号。在某些情况下会出现语法冲突:
0xff
可以解释为数字文字0
乘以变量xff
。1e10
可以解释为数字文字1
乘以变量e10
,并以等效E
形式表示。在这两种情况下,我们都解决了模棱两可的问题,将其解释为数字文字:
0x
始终是十六进制文字。e
或的表达式E
始终是浮点文字。Julia提供的函数将返回与指定类型或给定变量类型相对应的文字0和1。
类型x或变量类型的文字零x
这些函数在数值比较中很有用,可避免不必要的类型转换带来的开销。
例子:
julia> zero(Float32)
0.0f0
julia> zero(1.0)
0.0
julia> one(Int32)
1
julia> one(BigFloat)
1.000000000000000000000000000000000000000000000000000000000000000000000000000000