Mathematical Operations and Elementary Functions
Julia 提供了一整套基本算术和按位运算符,适用于所有数值原始类型,并且提供了便携、高效的标准数学函数的全面实现。
Arithmetic Operators
以下 arithmetic operators 在所有原始数字类型上都受支持:
| Expression | Name | Description |
|---|---|---|
+x | unary plus | the identity operation |
-x | unary minus | maps values to their additive inverses |
x + y | binary plus | performs addition |
x - y | binary minus | performs subtraction |
x * y | times | performs multiplication |
x / y | divide | performs division |
x ÷ y | integer divide | x / y, truncated to an integer |
x \ y | inverse divide | equivalent to y / x |
x ^ y | power | raises x to the yth power |
x % y | remainder | equivalent to rem(x, y) |
一个数字字面量直接放在标识符或括号之前,例如 2x 或 2(x + y),被视为乘法,优先级高于其他二元操作。有关详细信息,请参见 Numeric Literal Coefficients。
Julia的提升系统使得对不同类型参数的混合进行算术运算“自然且自动地”工作。有关提升系统的详细信息,请参见 Conversion and Promotion。
÷ 符号可以通过在 REPL 或 Julia IDE 中输入 \div<tab> 方便地输入。有关更多信息,请参见 manual section on Unicode input。
这里有一些使用算术运算符的简单示例:
julia> 1 + 2 + 3
6
julia> 1 - 2
-1
julia> 3*2/12
0.5(根据惯例,如果运算符在其他附近运算符之前应用,我们倾向于将运算符的间距缩得更紧。例如,我们通常会写 -x + 2 来反映首先对 x 取负,然后将 2 加到该结果上。)
在乘法中,false 作为 强零 作用:
julia> NaN * false
0.0
julia> false * Inf
0.0这对于防止已知为零的数量中传播 NaN 值是有用的。请参见 Knuth (1992) 以获取动机。
Boolean Operators
以下 Boolean operators 在 Bool 类型上受支持:
| Expression | Name |
|---|---|
!x | negation |
x && y | short-circuiting and |
x || y | short-circuiting or |
否定将 true 变为 false,反之亦然。短路操作在链接页面中进行了说明。
注意,Bool 是一种整数类型,所有通常的提升规则和数值运算符也适用于它。
Bitwise Operators
以下 bitwise operators 在所有原始整数类型上都受支持:
| Expression | Name |
|---|---|
~x | bitwise not |
x & y | bitwise and |
x | y | bitwise or |
x ⊻ y | bitwise xor (exclusive or) |
x ⊼ y | bitwise nand (not and) |
x ⊽ y | bitwise nor (not or) |
x >>> y | logical shift right |
x >> y | arithmetic shift right |
x << y | logical/arithmetic shift left |
这里有一些位运算符的示例:
julia> ~123
-124
julia> 123 & 234
106
julia> 123 | 234
251
julia> 123 ⊻ 234
145
julia> xor(123, 234)
145
julia> nand(123, 123)
-124
julia> 123 ⊼ 123
-124
julia> nor(123, 124)
-128
julia> 123 ⊽ 124
-128
julia> ~UInt32(123)
0xffffff84
julia> ~UInt8(123)
0x84Updating operators
每个二进制算术和按位运算符都有一个更新版本,它将操作的结果赋值回其左操作数。二进制运算符的更新版本是在运算符后面立即放置一个 =。例如,写 x += 3 等同于写 x = x + 3:
julia> x = 1
1
julia> x += 3
4
julia> x
4所有二进制算术和按位运算符的更新版本是:
+= -= *= /= \= ÷= %= ^= &= |= ⊻= >>>= >>= <<=一个更新操作符重新绑定左侧的变量。因此,变量的类型可能会改变。
julia> x = 0x01; typeof(x)
UInt8
julia> x *= 2 # Same as x = x * 2
2
julia> typeof(x)
Int64Vectorized "dot" operators
对于 每个 二元运算符,如 ^,都有一个对应的 "点" 运算符 .^,它 自动 定义为在数组上逐元素执行 ^。例如,[1, 2, 3] ^ 3 是未定义的,因为对(非方形)数组进行 "立方" 没有标准的数学意义,但 [1, 2, 3] .^ 3 被定义为计算逐元素(或 "向量化")的结果 [1^3, 2^3, 3^3]。 对于像 ! 或 √ 这样的单元运算符,同样有一个对应的 .√,它逐元素应用该运算符。
julia> [1, 2, 3] .^ 3
3-element Vector{Int64}:
1
8
27更具体地说,a .^ b 被解析为 "dot" call (^).(a,b),它执行一个 broadcast 操作:它可以组合数组和标量、相同大小的数组(逐元素执行操作),甚至不同形状的数组(例如,组合行向量和列向量以生成矩阵)。此外,像所有向量化的“点调用”一样,这些“点运算符”是融合的。例如,如果你计算 2 .* A.^2 .+ sin.(A)(或等效地使用 @. 2A^2 + sin(A),使用 @. 宏)对于数组 A,它会对 A 执行一个单一循环,为 A 的每个元素 a 计算 2a^2 + sin(a)。特别地,像 f.(g.(x)) 这样的嵌套点调用是融合的,而“相邻”的二元运算符如 x .+ 3 .* x.^2 等价于嵌套点调用 (+).(x, (*).(3, (^).(x, 2)))。
Furthermore, "dotted" updating operators like a .+= b (or @. a += b) are parsed as a .= a .+ b, where .= is a fused in-place assignment operation (see the dot syntax documentation).
注意,点语法也适用于用户定义的运算符。例如,如果你定义 ⊗(A, B) = kron(A, B) 来为 Kronecker 乘积提供一个方便的中缀语法 A ⊗ B(kron),那么 [A, B] .⊗ [C, D] 将计算 [A⊗C, B⊗D],无需额外编码。
将点运算符与数字字面量结合可能会造成歧义。例如,1.+x 并不清楚是指 1. + x 还是 1 .+ x。因此,这种语法是不允许的,在这种情况下必须在运算符周围使用空格。
Numeric Comparisons
标准比较操作适用于所有原始数值类型:
| Operator | Name |
|---|---|
== | equality |
!=, ≠ | inequality |
< | less than |
<=, ≤ | less than or equal to |
> | greater than |
>=, ≥ | greater than or equal to |
这里有一些简单的例子:
julia> 1 == 1
true
julia> 1 == 2
false
julia> 1 != 2
true
julia> 1 == 1.0
true
julia> 1 < 2
true
julia> 1.0 > 3
false
julia> 1 >= 1.0
true
julia> -1 <= 1
true
julia> -1 <= -1
true
julia> -1 <= -2
false
julia> 3 < -0.5
false整数以标准方式进行比较——通过比特比较。浮点数的比较依据 IEEE 754 standard:
- 有限数以通常的方式排序。
- 正零等于但不大于负零。
Inf等于它自己,并且大于除了NaN以外的所有其他值。-Inf等于它自己,并且小于除了NaN以外的所有其他值。NaN不等于、也不小于、也不大于任何东西,包括它自己。
最后一点可能令人惊讶,因此值得注意:
julia> NaN == NaN
false
julia> NaN != NaN
true
julia> NaN < NaN
false
julia> NaN > NaN
false并且在处理 arrays 时可能会导致头痛:
julia> [1 NaN] == [1 NaN]
falseJulia 提供了额外的函数来测试数字的特殊值,这在哈希键比较等情况下非常有用:
| Function | Tests if |
|---|---|
isequal(x, y) | x and y are identical |
isfinite(x) | x is a finite number |
isinf(x) | x is infinite |
isnan(x) | x is not a number |
isequal 将 NaN 视为彼此相等:
julia> isequal(NaN, NaN)
true
julia> isequal([1 NaN], [1 NaN])
true
julia> isequal(NaN, NaN32)
trueisequal 还可以用来区分有符号零:
julia> -0.0 == 0.0
true
julia> isequal(-0.0, 0.0)
false混合类型的比较(有符号整数、无符号整数和浮点数之间)可能会很棘手。为了确保 Julia 正确地进行这些比较,已经进行了大量的工作。
对于其他类型,isequal 默认调用 ==,因此如果您想为自己的类型定义相等性,则只需添加一个 4d61726b646f776e2e436f64652822222c20223d3d2229_40726566 方法。如果您定义了自己的相等性函数,您可能还应该定义一个相应的 hash 方法,以确保 isequal(x,y) 意味着 hash(x) == hash(y)。
Chaining comparisons
与大多数语言不同,notable exception of Python,比较可以任意链式连接:
julia> 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
true链式比较在数值代码中通常非常方便。链式比较使用 && 运算符进行标量比较,而使用 & 运算符进行逐元素比较,这使得它们可以在数组上工作。例如,0 .< A .< 1 会生成一个布尔数组,其条目在 A 的相应元素介于 0 和 1 之间时为真。
注意链式比较的评估行为:
julia> v(x) = (println(x); x)
v (generic function with 1 method)
julia> v(1) < v(2) <= v(3)
2
1
3
true
julia> v(1) > v(2) <= v(3)
2
1
false中间的表达式只会被评估一次,而不是像将表达式写成 v(1) < v(2) && v(2) <= v(3) 时那样评估两次。然而,链式比较中的评估顺序是未定义的。强烈建议不要在链式比较中使用具有副作用的表达式(例如打印)。如果需要副作用,应显式使用短路 && 运算符(参见 Short-Circuit Evaluation)。
Elementary Functions
Julia 提供了一套全面的数学函数和运算符。这些数学运算被定义在尽可能广泛的数值类别上,以便进行合理的定义,包括整数、浮点数、有理数和复数,只要这些定义是合理的。
此外,这些函数(像任何Julia函数一样)可以以“向量化”的方式应用于数组和其他集合,使用 dot syntax f.(A),例如 sin.(A) 将计算数组 A 中每个元素的正弦值。
Operator Precedence and Associativity
朱莉亚按照以下运算的顺序和结合性进行操作,从最高优先级到最低优先级:
| Category | Operators | Associativity |
|---|---|---|
| Syntax | . followed by :: | Left |
| Exponentiation | ^ | Right |
| Unary | + - ! ~ ¬ √ ∛ ∜ ⋆ ± ∓ <: >: | Right[1] |
| Bitshifts | << >> >>> | Left |
| Fractions | // | Left |
| Multiplication | * / % & \ ÷ | Left[2] |
| Addition | + - | ⊻ | Left[2] |
| Syntax | : .. | Left |
| Syntax | |> | Left |
| Syntax | <| | Right |
| Comparisons | > < >= <= == === != !== <: | Non-associative |
| Control flow | && followed by || followed by ? | Right |
| Pair | => | Right |
| Assignments | = += -= *= /= //= \= ^= ÷= %= |= &= ⊻= <<= >>= >>>= | Right |
有关 每个 Julia 运算符优先级的完整列表,请参见此文件的顶部: src/julia-parser.scm。请注意,那里的一些运算符在 Base 模块中未定义,但可能会由标准库、包或用户代码提供定义。
您还可以通过内置函数 Base.operator_precedence 查找任何给定运算符的数值优先级,其中较高的数字具有优先权:
julia> Base.operator_precedence(:+), Base.operator_precedence(:*), Base.operator_precedence(:.)
(11, 12, 17)
julia> Base.operator_precedence(:sin), Base.operator_precedence(:+=), Base.operator_precedence(:(=)) # (Note the necessary parens on `:(=)`)
(0, 1, 1)一个表示运算符结合性的符号也可以通过调用内置函数 Base.operator_associativity 来找到:
julia> Base.operator_associativity(:-), Base.operator_associativity(:+), Base.operator_associativity(:^)
(:left, :none, :right)
julia> Base.operator_associativity(:⊗), Base.operator_associativity(:sin), Base.operator_associativity(:→)
(:left, :none, :right)请注意,像 :sin 这样的符号返回优先级 0。这个值表示无效的运算符,而不是最低优先级的运算符。同样,这些运算符被分配了结合性 :none。
Numeric literal coefficients,例如 2x,被视为乘法,其优先级高于任何其他二元运算,除了 ^,在作为指数时它们的优先级更高。
julia> x = 3; 2x^2
18
julia> x = 3; 2^2x
64并列解析起来像一个一元运算符,它在指数周围具有相同的自然不对称性:-x^y 和 2x^y 解析为 -(x^y) 和 2(x^y),而 x^-y 和 x^2y 解析为 x^(-y) 和 x^(2y)。
Numerical Conversions
Julia 支持三种数值转换形式,它们在处理不精确转换时有所不同。
符号
T(x)或convert(T, x)将x转换为类型T的值。- 如果
T是浮点类型,则结果是最接近的可表示值,这可能是正无穷大或负无穷大。 - 如果
T是整数类型,当x不能被T表示时,将引发InexactError。
- 如果
x % T将整数x转换为与x模2^n同余的整数类型T的值,其中n是T中的位数。换句话说,二进制表示被截断以适应。Rounding functions 将类型
T作为可选参数。例如,round(Int,x)是Int(round(x))的简写。
以下示例展示了不同的形式。
julia> Int8(127)
127
julia> Int8(128)
ERROR: InexactError: trunc(Int8, 128)
Stacktrace:
[...]
julia> Int8(127.0)
127
julia> Int8(3.14)
ERROR: InexactError: Int8(3.14)
Stacktrace:
[...]
julia> Int8(128.0)
ERROR: InexactError: Int8(128.0)
Stacktrace:
[...]
julia> 127 % Int8
127
julia> 128 % Int8
-128
julia> round(Int8,127.4)
127
julia> round(Int8,127.6)
ERROR: InexactError: Int8(128.0)
Stacktrace:
[...]查看 Conversion and Promotion 以了解如何定义您自己的转换和促销。
Rounding functions
| Function | Description | Return type |
|---|---|---|
round(x) | round x to the nearest integer | typeof(x) |
round(T, x) | round x to the nearest integer | T |
floor(x) | round x towards -Inf | typeof(x) |
floor(T, x) | round x towards -Inf | T |
ceil(x) | round x towards +Inf | typeof(x) |
ceil(T, x) | round x towards +Inf | T |
trunc(x) | round x towards zero | typeof(x) |
trunc(T, x) | round x towards zero | T |
Division functions
| Function | Description |
|---|---|
div(x, y), x÷y | truncated division; quotient rounded towards zero |
fld(x, y) | floored division; quotient rounded towards -Inf |
cld(x, y) | ceiling division; quotient rounded towards +Inf |
rem(x, y), x%y | remainder; satisfies x == div(x, y)*y + rem(x, y); sign matches x |
mod(x, y) | modulus; satisfies x == fld(x, y)*y + mod(x, y); sign matches y |
mod1(x, y) | mod with offset 1; returns r∈(0, y] for y>0 or r∈[y, 0) for y<0, where mod(r, y) == mod(x, y) |
mod2pi(x) | modulus with respect to 2pi; 0 <= mod2pi(x) < 2pi |
divrem(x, y) | returns (div(x, y),rem(x, y)) |
fldmod(x, y) | returns (fld(x, y), mod(x, y)) |
gcd(x, y...) | greatest positive common divisor of x, y,... |
lcm(x, y...) | least positive common multiple of x, y,... |
Sign and absolute value functions
| Function | Description |
|---|---|
abs(x) | a positive value with the magnitude of x |
abs2(x) | the squared magnitude of x |
sign(x) | indicates the sign of x, returning -1, 0, or +1 |
signbit(x) | indicates whether the sign bit is on (true) or off (false) |
copysign(x, y) | a value with the magnitude of x and the sign of y |
flipsign(x, y) | a value with the magnitude of x and the sign of x*y |
Powers, logs and roots
| Function | Description |
|---|---|
sqrt(x), √x | square root of x |
cbrt(x), ∛x | cube root of x |
hypot(x, y) | hypotenuse of right-angled triangle with other sides of length x and y |
exp(x) | natural exponential function at x |
expm1(x) | accurate exp(x) - 1 for x near zero |
ldexp(x, n) | x * 2^n computed efficiently for integer values of n |
log(x) | natural logarithm of x |
log(b, x) | base b logarithm of x |
log2(x) | base 2 logarithm of x |
log10(x) | base 10 logarithm of x |
log1p(x) | accurate log(1 + x) for x near zero |
exponent(x) | binary exponent of x |
significand(x) | binary significand (a.k.a. mantissa) of a floating-point number x |
有关为什么像 hypot、expm1 和 log1p 这样的函数是必要和有用的概述,请参阅 John D. Cook 关于该主题的优秀博客文章对:expm1, log1p, erfc 和 hypot。
Trigonometric and hyperbolic functions
所有标准的三角函数和双曲函数也被定义为:
sin cos tan cot sec csc
sinh cosh tanh coth sech csch
asin acos atan acot asec acsc
asinh acosh atanh acoth asech acsch
sinc cosc这些都是单参数函数,atan 还接受两个参数,对应于传统的 atan2 函数。
此外,sinpi(x) 和 cospi(x) 被提供用于更准确地计算 sin(pi * x) 和 cos(pi * x)。
为了使用度数而不是弧度计算三角函数,请在函数后加上 d。例如,sind(x) 计算 x 的正弦,其中 x 以度数表示。带有度数变体的三角函数完整列表是:
sind cosd tand cotd secd cscd
asind acosd atand acotd asecd acscdSpecial functions
许多其他特殊数学函数由包 SpecialFunctions.jl 提供。
- 1The unary operators
+and-require explicit parentheses around their argument to disambiguate them from the operator++, etc. Other compositions of unary operators are parsed with right-associativity, e. g.,√√-aas√(√(-a)). - 2The operators
+,++and*are non-associative.a + b + cis parsed as+(a, b, c)not+(+(a, b), c). However, the fallback methods for+(a, b, c, d...)and*(a, b, c, d...)both default to left-associative evaluation.