整数和浮点数
整数和浮点值是算术和计算的基本构建块。 这种值的内置表示称为数字基元,而整数和浮点数在代码中作为直接值的表示称为数字字面量。 例如,`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 |
'错误`(0) |
'真`(1) |
-
浮点类型
整数
字面整数以标准方式表示。
julia> 1
1
julia> 1234
1234
整数字面量的默认类型取决于目标系统具有的体系结构—32位或64位:
# 32-разрядная система:
julia> typeof(1)
Int32
# 64-разрядная система:
julia> typeof(1)
Int64
Julia内部变量 'Sys.WORD_SIZE'表示目标系统是32位还是64位:
# 32-разрядная система:
julia> Sys.WORD_SIZE
32
# 64-разрядная система:
julia> Sys.WORD_SIZE
64
Julia还定义了类型`Int`和’UInt',它们分别是系统自己的有符号和无符号整数类型的别名。:
# 32-разрядная система:
julia> Int
Int32
julia> UInt
UInt32
# 64-разрядная система:
julia> Int
Int64
julia> UInt
UInt64
无法仅使用32位表示但可以用64位表示的大整数字面量总是产生64位整数,而与系统类型无关。:
# 32-или 64-разрядная система:
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
朱莉娅>类型(x)
UInt64
朱莉娅>x=0x111122222333344445555666677778888
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’值将创建’BigInt’值。 它不是无符号类型,但它是唯一一个足够大的内置类型来表示如此大的整数值。
二进制、八进制和十六进制文本可以在无符号文本前面有一个"-"符号。 它们创建一个与无符号字面量大小相同的无符号整数,并添加二进制值。
julia> -0x2
0xfe
julia> -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]
返回的值 `typemin'和 `typemax',总是有一个指定的参数类型。 (上面的表达式使用了几个尚未审查的函数,包括 循环, 行和 插值。 但是,对于具有一定编程经验的用户来说,它应该相当简单易懂。)
溢出行为
在Julia中,超过给定类型的最大可表示值导致循环进位。:
julia> x = typemax(Int64)
9223372036854775807
julia> x + 1
-9223372036854775808
julia> x + 1 == typemin(Int64)
true
具有Julia整数类型的算术运算按其性质执行https://en.wikipedia.org/wiki/Modular_arithmetic [模块化算术],反映了现代计算机硬件上整数算术的特点。 在可能发生溢出的情况下,明确检查可能导致的旁路效应是非常重要的。 在模块中 '基地。Checked'一组带有溢出检查的算术运算可用,在溢出的情况下会导致错误。 在任何情况下溢出都是不可接受的情况下,建议使用类型 'BigInt',如中所述 任意精度算术。
下面是溢出行为的示例以及可能的解决方法。
julia> 10^19
-8446744073709551616
朱莉娅>大(10)^19
10000000000000000000
划分错误
整数除法(`div’函数)有两种例外情况:除零和除最小负数(`typemin')到—1。 在这两种情况下,有 'DivideError'。 余数和模数计算函数(`rem`和`mod')调用 `DivideError'如果他们的第二个参数是零。
浮点数
字面浮点数以标准格式表示,如有必要,使用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
朱莉娅>类型(x)
漂浮物32
朱莉娅>2.5f-4
0.00025f0
值可以很容易地转换为类型。 'Float32`:
julia> x = Float32(-1.5)
-1.5f0
julia> typeof(x)
Float32
也允许浮点十六进制文字,但仅作为值。 'Float64',其中’p’在基2指数之前:
julia> 0x1p0
1.0
julia> 0x1.8p3
12.0
julia> x = 0x.4p-1
0.125
julia> typeof(x)
Float64
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 [两个零]--正和负。 它们彼此相等,但具有不同的二进制表示,使用函数可以看出 'bitstring':
julia> 0.0 == -0.0
true
julia> bitstring(0.0)
"0000000000000000000000000000000000000000000000000000000000000000"
julia> bitstring(-0.0)
"1000000000000000000000000000000000000000000000000000000000000000"
特殊浮点值
有三个定义的标准浮点值不对应于实数直线上的任何点。:
'漂浮16` | '漂浮32` | '漂浮64` | 姓名 | 资料描述 |
---|---|---|---|---|
'Inf16` |
'Inf32` |
'Inf` |
正无穷大 |
值大于所有最终浮点值。 |
|
|
|
负无穷大 |
值小于所有最终浮点值。 |
`NaN16' |
`NaN32' |
`南' |
不是数字 |
不`==`任何浮点值(包括自身)的值 |
有关这些无限浮点值相对于彼此和其他浮点值的排序的进一步讨论,请参阅 数值比较。 根据https://en.wikipedia.org/wiki/IEEE_754-2008 [IEEE754标准]这些浮点值是某些算术运算的结果:
julia> 1/Inf
0.0
julia> 1/0
Inf
julia> -5/0
-Inf
朱莉娅>0.000001/0
资讯
朱莉娅>0/0
南
朱莉娅>500+Inf
资讯
朱莉娅>500-Inf
-Inf
朱莉娅>Inf+Inf
资讯
朱莉娅>Inf-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中,有一种方法 'eps',它允许您获得`1.0`和下一个最大的可表示浮点值之间的距离:
julia> eps(Float32)
1.1920929f-7
julia> eps(Float64)
2.220446049250313e-16
julia> eps() # то же, что и 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
朱莉娅>nextfloat(x)
1.2500001f0
朱莉娅>prevfloat(x)
1.2499999f0
julia>bitstring(prevfloat(x))
"00111111100111111111111111111111"
朱莉娅>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标准]。 但是,它不能在互联网上免费提供。
-
关于表示浮点数的选项的简要但明确的描述可以在主题中找到https://www.johndcook.com/blog/2009/04/06/anatomy-of-a-floating-point-number /[文章]约翰*D*库克,以及在他的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 /[Bruce Dawson关于浮点数的博客文章]。
-
大卫*戈德伯格(David Goldberg)在一篇论文中提出了浮点数的有趣而详细的讨论以及与计算精度相关的问题https://citeseerx.ist.psu.edu/viewdoc/download ?doi=10.1.1.22.6768&rep;=rep1&type;=pdf[What Every Computer Scientist Should Know About Floating-Point Arithmetic](每个计算机科学家都应该知道的关于浮点算术的知识)。
-
有关浮点数的历史、基本原理和问题的更详细的文档,以及数值计算中许多其他主题的讨论,可在https://people…eecs。berkeley.edu /~wkahan/[出版物集]来自https://en.wikipedia.org/wiki/William_Kahan [威廉*卡汉],广为人知的"浮点之父"。 这篇文章可能特别感兴趣https://people…eecs。berkeley.edu /~wkahan/ieee754status/754story。html【浮点运算老人访谈】(浮点运算之父访谈)。
任意精度算术
Julia具有内置库,用于使用任意精度整数和浮点数执行计算。 https://gmplib.org [GNU多精度算术库(GMP)]和https://www.mpfr.org [GNU MPFR库],分别。 对于Julia中的任意精度整数和浮点数,类型可用 `BigInt'和 'BigFloat',分别。
有构造函数可以从原始数值类型创建这些类型。 要从`AbstractString’构建类型,您可以使用 字符串文字 `@big_str'或 '解析'。 "BigInt"也可以作为整数文字输入,如果它们对于其他内置整数类型来说太大。 请注意,由于Base中没有无符号任意精度整数类型(在大多数情况下,BigInt就足够了),因此您可以使用十六进制,八进制和二进制文字(除了十进制)。
一旦创建,它们与所有其他数字类型一起用于算术运算,因为 转型及推广#conversion-and-promotion【类型转换提升机制】在Julia:
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
julia> BigFloat(2.0^66) / 3
2.459565876494606882133333333333333333333333333333333333333333333333333333333344e+19
julia> factorial(BigInt(40))
815915283247897734345611269596115894272000000000
但是,上述基元类型之间的类型提升和 'BigInt'/'BigFloat'不是自动的,必须明确指定。
julia> x = typemin(Int64)
-9223372036854775808
朱莉娅>x=x-1
9223372036854775807
朱莉娅>类型(x)
Int64
julia>y=BigInt(typemin(Int64))
-9223372036854775808
朱莉娅>y=y-1
-9223372036854775809
朱莉娅>打字(y)
比金特
默认精度(以有效数字的位数为单位)和舍入操作模式 `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
之间的关系 'setprecision'或 |
数值文字系数
为了使普通的数值公式和表达式更容易理解,在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
这两个表达式都被解释为函数的应用程序:如果任何不是数字字面量的表达式后紧跟括号,则此表达式被解释为适用于括号中的值的函数(有关函数的更 功能)。 因此,在这两种情况下都会发生错误,因为left值不是函数。
上述句法改进显着降低了编写普通数学公式时出现的视觉噪声。 请注意,数字文字系数与标识符或其乘以的括号中的表达式之间不应有空格。
句法冲突
相邻字面量系数的语法可能与数字字面量的某些语法冲突:十六进制、八进制和二进制整数字面量以及浮点字面量的工程表示法。 以下是出现句法冲突的一些情况。
-
十六进制整数字面量表达式'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'。