整数和浮点数
整数和浮点值是算术和计算的基本构建块。 这些值的内置表示形式称为数字基元,而整数和浮点数在代码中作为直接值的表示形式称为数字字面量。 例如, 1 是一个整数字面量,而 1.0 是浮点字面量;它们作为对象的二进制内存中表示是数字基元。
Julia提供了广泛的原始数字类型,并且在它们上面定义了完整的算术和按位运算符以及标准数学函数。 这些映射直接映射到现代计算机上本机支持的数字类型和操作,从而使Julia能够充分利用计算资源。 此外,Julia还为 任意精度算术,它可以处理在本机硬件表示中无法有效表示的数值上的操作,但代价是性能相对较慢。
以下是Julia的原始数字类型:
**整数类型:*
| 类型 | 签名? | 位数 | 最小值 | 最大值 |
|---|---|---|---|---|
✓ |
8 |
-2^7 |
2^7 - 1 |
|
8 |
0 |
2^8 - 1 |
||
✓ |
16 |
-2^15 |
2^15 - 1 |
|
16 |
0 |
2^16 - 1 |
||
✓ |
32 |
-2^31 |
2^31 - 1 |
|
32 |
0 |
2^32 - 1 |
||
✓ |
64 |
-2^63 |
2^63 - 1 |
|
64 |
0 |
2^64 - 1 |
||
✓ |
128 |
-2^127 |
2^127 - 1 |
|
128 |
0 |
2^128 - 1 |
||
N/A |
8 |
|
|
**浮点类型:*
| 类型 | 精密度 | 位数 |
|---|---|---|
16 |
||
32 |
||
64 |
整数
字面整数以标准方式表示:
julia> 1
1
julia> 1234
1234
整数字面量的默认类型取决于目标系统是具有32位体系结构还是64位体系结构:
# 32-bit system:
julia> typeof(1)
Int32
# 64-bit system:
julia> typeof(1)
Int64
Julia内部变量 系统。字_大小指示目标系统是32位还是64位:
# 32-bit system:
julia> Sys.WORD_SIZE
32
#64位系统:
朱莉娅>Sys.字_大小
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> x = 0x1
0x01
julia> typeof(x)
UInt8
julia> x = 0x123
0x0123
julia> typeof(x)
UInt16
julia> x = 0x1234567
0x01234567
julia> typeof(x)
UInt32
julia> x = 0x123456789abcdef
0x0123456789abcdef
julia> typeof(x)
UInt64
julia> x = 0x11112222333344445555666677778888
0x11112222333344445555666677778888
朱莉娅>类型(x)
UInt128
这种行为基于以下观察:当使用无符号十六进制文本表示整数值时,通常使用它们来表示固定的数字字节序列,而不仅仅是整数值。
还支持二进制和八进制文本:
julia> x = 0b10
0x02
julia> typeof(x)
UInt8
julia> x = 0o010
0x08
julia> typeof(x)
UInt8
julia> x = 0x00000000000000001111222233334444
0x00000000000000001111222233334444
julia> typeof(x)
UInt128
至于十六进制字面量,二进制和八进制字面量产生无符号整数类型。 二进制数据项的大小是所需的最小大小,如果文字的前导数字不是 0. 在前导零的情况下,大小由具有相同长度但前导数字的文字所需的最小大小决定 1. 意思是:
* 0x1 和 0x12 是 UInt8 文字,
* 0x123 和 0x1234 是 UInt16 文字,
* 0x12345 和 0x12345678 是 UInt32 文字,
* 0x123456789 和 0x1234567890adcdef 是 UInt64 文字等。
即使存在对值没有贡献的前导零位数,它们也会用于确定文字的存储大小。 所以 0x01 是一个 UInt8 而 0x0001 是一个 UInt16.
这允许用户控制大小。
无符号文字(以 0x)编码整数太大而不能表示为 UInt128 价值观将构建 比金特 值代替。 这不是无符号类型,但它是唯一一个足够大的内置类型来表示如此大的整数值。
二进制、八进制和十六进制文本可以由 - 紧跟在无符号字面值的前面。 它们产生一个无符号整数,其大小与无符号字面量相同,并且两者是值的补码:
julia> -0x2
0xfe
朱莉娅>-0x0002
0xfffe
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]
溢出行为
在Julia中,超过给定类型的最大可表示值会导致包装行为:
julia> x = typemax(Int64)
9223372036854775807
julia> x + 1
-9223372036854775808
julia> x + 1 == typemin(Int64)
true
与Julia的整数类型的算术运算固有地执行https://en.wikipedia.org/wiki/Modular_arithmetic[模块化算术],反映了现代计算机硬件上整数算术的特点。 在可能出现溢出的情况下,显式检查这种溢出可能导致的包装效果至关重要。 该 基地。检查过模块提供了一套带有溢出检查的算术运算,如果发生溢出,会触发错误。 对于在任何情况下都不能容忍溢出的用例,使用 比金特类型,详见 任意精度算术,是可取的。
溢出行为的示例以及如何潜在地解决它如下所示:
julia> 10^19
-8446744073709551616
julia> big(10)^19
10000000000000000000
浮点数
字面浮点数以标准格式表示,使用https://en.wikipedia.org/wiki/Scientific_notation#E_notation[电子符号]必要时:
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
julia> x = 0.5f0
0.5f0
julia> typeof(x)
Float32
julia> 2.5f-4
0.00025f0
值可以转换为 漂浮物32轻松:
julia> x = Float32(-1.5)
-1.5f0
julia> typeof(x)
Float32
十六进制浮点文字也是有效的,但仅作为 漂浮64值,与 p 在基数-2指数之前:
julia> 0x1p0
1.0
julia> 0x1.8p3
12.0
julia> x = 0x.4p-1
0.125
julia> typeof(x)
Float64
还支持半精度浮点数(漂浮物16)在所有平台上,使用支持此数字格式的硬件上使用的本机指令。 否则,操作在软件中实现,并使用 漂浮物32进行中间计算。 作为内部实现细节,这是通过使用LLVM的https://llvm.org/docs/LangRef.html#half-precision-floating-point-intrinsics[脧锚脧赂`一半`]类型,其行为类似于GCC 脧锚脧赂`-fexcess-精度=16`标志为C/C做++ 密码。
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)
浮点零
浮点数有https://en.wikipedia.org/wiki/Signed_zero[两个零],正零和负零。 它们彼此相等,但具有不同的二进制表示,如可以使用 比特串功能:
julia> 0.0 == -0.0
true
julia> bitstring(0.0)
"0000000000000000000000000000000000000000000000000000000000000000"
julia> bitstring(-0.0)
"1000000000000000000000000000000000000000000000000000000000000000"
特殊浮点值
有三个指定的标准浮点值不对应于实数线上的任何点:
漂浮物16 |
漂浮物32 |
漂浮64 |
姓名 | 资料描述 |
|---|---|---|---|---|
|
|
|
正无穷大 |
大于所有有限浮点值的值 |
|
|
|
负无穷大 |
小于所有有限浮点值的值 |
|
|
|
不是数字 |
一个值不 |
有关这些非有限浮点值如何相对于彼此和其他浮点数排序的进一步讨论,请参阅 数字比较。 由https://en.wikipedia.org/wiki/IEEE_754-2008[IEEE754标准],这些浮点值是某些算术运算的结果:
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
julia> 500 - Inf
-Inf
julia> Inf + Inf
Inf
julia> Inf - Inf
NaN
julia> Inf * Inf
Inf
朱莉娅>Inf/Inf
南
朱莉娅>0*Inf
南
julia>楠==楠
错误
朱莉娅>南!=南
真的
茱莉亚>楠<楠
错误
縺薙>縺、縺ァ縺呐
错误
julia> (typemin(Float16),typemax(Float16))
(-Inf16, Inf16)
julia> (typemin(Float32),typemax(Float32))
(-Inf32, Inf32)
julia> (typemin(Float64),typemax(Float64))
(-Inf, Inf)
机器epsilon
大多数实数不能用浮点数精确表示,因此对于许多目的来说,重要的是要知道两个相邻的可表示浮点数之间的距离,这通常被称为https://en.wikipedia.org/wiki/Machine_epsilon[机器epsilon]。
Julia提供 每股收益,这给出了之间的距离 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 作为 漂浮物32和 漂浮64值,分别。 该 每股收益函数也可以将浮点值作为参数,并给出该值与下一个可表示浮点值之间的绝对差值。 那就是, 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> x = 1.25f0
1.25f0
julia> nextfloat(x)
1.2500001f0
julia> prevfloat(x)
1.2499999f0
julia> bitstring(prevfloat(x))
"00111111100111111111111111111111"
julia> bitstring(x)
"00111111101000000000000000000000"
julia> bitstring(nextfloat(x))
"00111111101000000000000000000001"
此示例突出了相邻可表示浮点数也具有相邻二进制整数表示的一般原则。
舍入模式
如果数字没有精确的浮点表示,则必须将其四舍五入为适当的可表示值。 然而,如有需要,可根据https://en.wikipedia.org/wiki/IEEE_754-2008[IEEE754标准]。
使用的默认模式始终为 RoundNearest拢潞,舍入到最接近的可表示值,关系舍入到具有甚至最低有效位的最接近值。
背景及参考资料
浮点运算包含许多微妙之处,对于不熟悉底层实现细节的用户来说,这可能会令人惊讶。 然而,这些微妙之处在大多数关于科学计算的书籍中有详细的描述,并且在下面的参考文献中也有详细的描述:
*浮点算术的权威指南是https://standards.ieee.org/standard/754-2008.html[IEEE754-2008标准];但是,它不是免费在线提供的。 *有关浮点数如何表示的简短而清晰的演示文稿,请参阅John D.Cook的https://www.johndcook.com/blog/2009/04/06/anatomy-of-a-floating-point-number/[文章]关于这个问题,以及他的https://www.johndcook.com/blog/2009/04/06/numbers-are-a-leaky-abstraction/[引言]关于这种表示在行为上与实数的理想化抽象有何不同而产生的一些问题。 *也推荐布鲁斯*道森的https://randomascii.wordpress.com/2012/05/20/thats-not-normalthe-performance-of-odd-floats/[浮点数系列博文]. *有关浮点数的优秀,深入的讨论以及在使用它们计算时遇到的数值精度问题,请参阅David Goldberg的论文https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.22.6768&rep;=rep1&type;=pdf[每个计算机科学家应该知道的关于浮点运算]。 *有关浮点数的历史、基本原理和问题的更广泛的文档,以及数值计算中许多其他主题的讨论,请参阅https://people.eecs.berkeley.edu/~wkahan/[收藏着作]威廉*卡汉,俗称"浮点之父"。 特别感兴趣的可能是https://people.eecs.berkeley.edu/~wkahan/ieee754status/754story.html【浮点数老人专访】。
任意精度算术
为了允许使用任意精度整数和浮点数进行计算,Julia包装了https://gmplib.org[GNU多精度算术库(GMP)]和https://www.mpfr.org[GNU MPFR库],分别。 该 比金特和 大块头,大块头类型在Julia中分别可用于任意精度整数和浮点数。
存在构造函数以从原始数值类型创建这些类型,并且 字符串文字 @big_str或 解析,解析可用于从构造它们 抽象字符串s. 比金特当s对于其他内置整数类型来说太大时,也可以作为整数文本输入。 请注意,由于没有无符号任意精度整数类型 基地 (比金特 在大多数情况下是足够的),十六进制,八进制和二进制文字可以使用(除了十进制文字)。
一旦创建,他们参与算术与所有其他数字类型感谢朱莉娅的 转换及推广#conversion-and-promotion【类型提升转换机制】:
julia> BigInt(typemax(Int64)) + 1
9223372036854775808
julia> big"123456789012345678901234567890" + 1
123456789012345678901234567891
julia> parse(BigInt, "123456789012345678901234567890") + 1
123456789012345678901234567891
julia> string(big"2"^200, base=16)
"100000000000000000000000000000000000000000000000000"
julia> 0x100000000000000000000000000000000-1 == typemax(UInt128)
true
julia> 0x000000000000000000000000000000000
0
julia> typeof(ans)
BigInt
julia> big"1.23456789012345678901"
1.234567890123456789010000000000000000000000000000000000000000000000000000000004
julia>parse(BigFloat,"1.23456789012345678901")
1.234567890123456789010000000000000000000000000000000000000000000000000000000004
朱莉娅>BigFloat(2.0^66)/3
2.459565876494606882133333333333333333333333333333333333333333333333333344e+19
朱莉娅>阶乘(BigInt(40))
815915283247897734345611269596115894272000000000
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
默认精度(以有效位数为单位)和舍入模式 大块头,大块头操作可以通过调用全局更改 精确的,精确的和 定界,定界,并且所有进一步的计算都将考虑到这些变化。 或者,精度或舍入只能在特定代码块的执行中通过使用与 做 座:
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
数值字面量系数的优先级略低于一元运算符(如否定)的优先级。 所以 -2x 被解析为 (-2)*x 和 √2x 被解析为 (√2)*x. 但是,数字字面量系数与一元运算符结合使用时的解析类似。 例如 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. 类似的歧义出现在八进制和二进制文本中,如 0o777 或 0b01001010.
*浮点文字表达式 1e10 可以解释为数字字面量 1 乘以变量 e10,并且类似地与等价物 E 表格。
*32位浮点文字表达式 1.5f22 可以解释为数字字面量 1.5 乘以变量 f22.
在所有情况下,歧义都被解决,有利于解释为数字文字:
*表达式以 0x/0o/0b 始终是十六进制/八进制/二进制文本。
*以数字文字开头的表达式,后跟 e 或 E 总是浮点文字。
*以数字文字开头的表达式,后跟 f 始终是32位浮点文字。
不像 E,相当于 e 由于历史原因,在数字文字中, F 只是另一封信,表现得不像 f 在数字文字中。 因此,以数字文字开头的表达式后跟 F 被解释为数字字面量乘以变量,这意味着,例如, 1.5F22 等于 1.5*F22.