Mathematical Operations and Elementary Functions

Julia fournit une collection complète d'opérateurs arithmétiques de base et d'opérateurs bit à bit pour tous ses types primitifs numériques, tout en offrant des implémentations portables et efficaces d'une collection complète de fonctions mathématiques standard.

Arithmetic Operators

Les éléments suivants arithmetic operators sont pris en charge sur tous les types numériques primitifs :

ExpressionNameDescription
+xunary plusthe identity operation
-xunary minusmaps values to their additive inverses
x + ybinary plusperforms addition
x - ybinary minusperforms subtraction
x * ytimesperforms multiplication
x / ydivideperforms division
x ÷ yinteger dividex / y, truncated to an integer
x \ yinverse divideequivalent to y / x
x ^ ypowerraises x to the yth power
x % yremainderequivalent to rem(x, y)

Un littéral numérique placé directement avant un identifiant ou des parenthèses, par exemple 2x ou 2(x + y), est traité comme une multiplication, sauf avec une priorité plus élevée que d'autres opérations binaires. Voir Numeric Literal Coefficients pour plus de détails.

Julia's promotion system makes arithmetic operations on mixtures of argument types "just work" naturally and automatically. See Conversion and Promotion for details of the promotion system.

Le signe ÷ peut être facilement tapé en écrivant \div<tab> dans le REPL ou l'IDE Julia. Voir le manual section on Unicode input pour plus d'informations.

Voici quelques exemples simples utilisant des opérateurs arithmétiques :

julia> 1 + 2 + 3
6

julia> 1 - 2
-1

julia> 3*2/12
0.5

(Par convention, nous avons tendance à espacer les opérateurs plus étroitement s'ils sont appliqués avant d'autres opérateurs voisins. Par exemple, nous écririons généralement -x + 2 pour refléter que d'abord x est négatif, puis 2 est ajouté à ce résultat.)

Lorsqu'il est utilisé dans une multiplication, false agit comme un zéro fort :

julia> NaN * false
0.0

julia> false * Inf
0.0

Ceci est utile pour prévenir la propagation des valeurs NaN dans des quantités qui sont connues pour être nulles. Voir Knuth (1992) pour la motivation.

Boolean Operators

Les Boolean operators sont pris en charge sur les Bool types :

ExpressionName
!xnegation
x && yshort-circuiting and
x || yshort-circuiting or

La négation change true en false et vice versa. Les opérations de court-circuit sont expliquées sur la page liée.

Notez que Bool est un type entier et que toutes les règles de promotion habituelles et les opérateurs numériques sont également définis sur celui-ci.

Bitwise Operators

Les éléments suivants bitwise operators sont pris en charge sur tous les types d'entiers primitifs :

ExpressionName
~xbitwise not
x & ybitwise and
x | ybitwise or
x ⊻ ybitwise xor (exclusive or)
x ⊼ ybitwise nand (not and)
x ⊽ ybitwise nor (not or)
x >>> ylogical shift right
x >> yarithmetic shift right
x << ylogical/arithmetic shift left

Voici quelques exemples avec des opérateurs bit à bit :

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)
0x84

Updating operators

Chaque opérateur arithmétique binaire et opérateur bit à bit a également une version de mise à jour qui assigne le résultat de l'opération à son opérande gauche. La version de mise à jour de l'opérateur binaire est formée en plaçant un = immédiatement après l'opérateur. Par exemple, écrire x += 3 est équivalent à écrire x = x + 3 :

julia> x = 1
1

julia> x += 3
4

julia> x
4

Les versions mises à jour de tous les opérateurs arithmétiques binaires et des opérateurs bit à bit sont :

+=  -=  *=  /=  \=  ÷=  %=  ^=  &=  |=  ⊻=  >>>=  >>=  <<=
Note

Un opérateur de mise à jour rebind la variable sur le côté gauche. En conséquence, le type de la variable peut changer.

julia> x = 0x01; typeof(x)
UInt8

julia> x *= 2 # Same as x = x * 2
2

julia> typeof(x)
Int64

Vectorized "dot" operators

Pour chaque opération binaire comme ^, il existe une opération "point" correspondante .^ qui est automatiquement définie pour effectuer ^ élément par élément sur des tableaux. Par exemple, [1, 2, 3] ^ 3 n'est pas défini, car il n'y a pas de signification mathématique standard à "élever au cube" un tableau (non carré), mais [1, 2, 3] .^ 3 est défini comme le calcul du résultat élément par élément (ou "vectorisé") [1^3, 2^3, 3^3]. De même, pour les opérateurs unaires comme ! ou , il existe un correspondant .√ qui applique l'opérateur élément par élément.

julia> [1, 2, 3] .^ 3
3-element Vector{Int64}:
  1
  8
 27

Plus précisément, a .^ b est analysé comme le "dot" call (^).(a,b), qui effectue une opération broadcast : il peut combiner des tableaux et des scalaires, des tableaux de la même taille (effectuant l'opération élément par élément), et même des tableaux de formes différentes (par exemple, en combinant des vecteurs de ligne et de colonne pour produire une matrice). De plus, comme tous les "appels par point" vectorisés, ces "opérateurs par point" sont fusionnés. Par exemple, si vous calculez 2 .* A.^2 .+ sin.(A) (ou équivalemment @. 2A^2 + sin(A), en utilisant le @. macro) pour un tableau A, cela effectue une unique boucle sur A, calculant 2a^2 + sin(a) pour chaque élément a de A. En particulier, les appels par point imbriqués comme f.(g.(x)) sont fusionnés, et les opérateurs binaires "adjacents" comme x .+ 3 .* x.^2 sont équivalents à des appels par point imbriqués (+).(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).

Notez que la syntaxe par point est également applicable aux opérateurs définis par l'utilisateur. Par exemple, si vous définissez ⊗(A, B) = kron(A, B) pour donner une syntaxe infixe pratique A ⊗ B pour les produits de Kronecker (kron), alors [A, B] .⊗ [C, D] calculera [A⊗C, B⊗D] sans codage supplémentaire.

Combiner des opérateurs de point avec des littéraux numériques peut être ambigu. Par exemple, il n'est pas clair si 1.+x signifie 1. + x ou 1 .+ x. Par conséquent, cette syntaxe est interdite, et des espaces doivent être utilisés autour de l'opérateur dans de tels cas.

Numeric Comparisons

Les opérations de comparaison standard sont définies pour tous les types numériques primitifs :

OperatorName
==equality
!=, inequality
<less than
<=, less than or equal to
>greater than
>=, greater than or equal to

Voici quelques exemples simples :

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

Les entiers sont comparés de manière standard – par comparaison de bits. Les nombres à virgule flottante sont comparés selon le IEEE 754 standard :

  • Les nombres finis sont ordonnés de la manière habituelle.
  • Le zéro positif est égal mais pas supérieur au zéro négatif.
  • Inf est égal à lui-même et supérieur à tout le reste sauf NaN.
  • -Inf est égal à lui-même et inférieur à tout le reste sauf NaN.
  • NaN n'est égal à rien, n'est pas inférieur à rien et n'est pas supérieur à rien, y compris lui-même.

Le dernier point est potentiellement surprenant et mérite donc d'être noté :

julia> NaN == NaN
false

julia> NaN != NaN
true

julia> NaN < NaN
false

julia> NaN > NaN
false

et peut causer des maux de tête lors du travail avec arrays :

julia> [1 NaN] == [1 NaN]
false

Julia fournit des fonctions supplémentaires pour tester les nombres pour des valeurs spéciales, ce qui peut être utile dans des situations comme les comparaisons de clés de hachage :

FunctionTests 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 considère les NaN comme égaux entre eux :

julia> isequal(NaN, NaN)
true

julia> isequal([1 NaN], [1 NaN])
true

julia> isequal(NaN, NaN32)
true

isequal peut également être utilisé pour distinguer les zéros signés :

julia> -0.0 == 0.0
true

julia> isequal(-0.0, 0.0)
false

Les comparaisons de types mixtes entre entiers signés, entiers non signés et flottants peuvent être délicates. Une grande attention a été portée pour s'assurer que Julia les effectue correctement.

Pour d'autres types, isequal appelle par défaut ==, donc si vous souhaitez définir l'égalité pour vos propres types, vous n'avez qu'à ajouter une méthode 4d61726b646f776e2e436f64652822222c20223d3d2229_40726566. Si vous définissez votre propre fonction d'égalité, vous devriez probablement définir une méthode correspondante hash pour garantir que isequal(x,y) implique hash(x) == hash(y).

Chaining comparisons

Contrairement à la plupart des langages, avec le notable exception of Python, les comparaisons peuvent être enchaînées de manière arbitraire :

julia> 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
true

La comparaison en chaîne est souvent très pratique dans le code numérique. Les comparaisons en chaîne utilisent l'opérateur && pour les comparaisons scalaires, et l'opérateur & pour les comparaisons élément par élément, ce qui leur permet de fonctionner sur des tableaux. Par exemple, 0 .< A .< 1 donne un tableau booléen dont les entrées sont vraies lorsque les éléments correspondants de A se situent entre 0 et 1.

Notez le comportement d'évaluation des comparaisons enchaînées :

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

L'expression du milieu n'est évaluée qu'une seule fois, plutôt que deux fois comme ce serait le cas si l'expression était écrite comme v(1) < v(2) && v(2) <= v(3). Cependant, l'ordre des évaluations dans une comparaison en chaîne est indéfini. Il est fortement recommandé de ne pas utiliser d'expressions avec des effets de bord (comme l'impression) dans des comparaisons en chaîne. Si des effets de bord sont nécessaires, l'opérateur de court-circuit && doit être utilisé explicitement (voir Short-Circuit Evaluation).

Elementary Functions

Julia fournit une collection complète de fonctions et d'opérateurs mathématiques. Ces opérations mathématiques sont définies sur une classe aussi large de valeurs numériques que le permettent des définitions sensées, y compris les entiers, les nombres à virgule flottante, les rationnels et les nombres complexes, partout où de telles définitions ont un sens.

De plus, ces fonctions (comme toute fonction Julia) peuvent être appliquées de manière "vectorisée" aux tableaux et autres collections avec le dot syntax f.(A), par exemple sin.(A) calculera le sinus de chaque élément d'un tableau A.

Operator Precedence and Associativity

Julia applique l'ordre et l'associativité des opérations suivants, de la plus haute priorité à la plus basse :

CategoryOperatorsAssociativity
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

Pour une liste complète de tous les opérateurs Julia et leur priorité, voir le haut de ce fichier : src/julia-parser.scm. Notez que certains des opérateurs là-bas ne sont pas définis dans le module Base, mais peuvent être définis par des bibliothèques standard, des paquets ou du code utilisateur.

Vous pouvez également trouver la priorité numérique pour tout opérateur donné via la fonction intégrée Base.operator_precedence, où des nombres plus élevés ont la priorité :

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)

Un symbole représentant l'associativité des opérateurs peut également être trouvé en appelant la fonction intégrée 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)

Notez que des symboles tels que :sin renvoient une priorité de 0. Cette valeur représente des opérateurs invalides et non des opérateurs de la plus basse priorité. De même, ces opérateurs se voient attribuer une associativité :none.

Numeric literal coefficients, par exemple 2x, sont traités comme des multiplications avec une priorité plus élevée que toute autre opération binaire, à l'exception de ^ où ils ont une priorité plus élevée uniquement en tant qu'exposant.

julia> x = 3; 2x^2
18

julia> x = 3; 2^2x
64

La juxtaposition se parse comme un opérateur unaire, qui a la même asymétrie naturelle autour des exposants : -x^y et 2x^y se parse comme -(x^y) et 2(x^y) tandis que x^-y et x^2y se parse comme x^(-y) et x^(2y).

Numerical Conversions

Julia prend en charge trois formes de conversion numérique, qui diffèrent par leur gestion des conversions inexactes.

  • La notation T(x) ou convert(T, x) convertit x en une valeur de type T.

    • Si T est un type à virgule flottante, le résultat est la valeur représentable la plus proche, qui peut être l'infini positif ou négatif.
    • Si T est un type entier, une InexactError est levée si x n'est pas représentable par T.
  • x % T convertit un entier x en une valeur de type entier T congruente à x modulo 2^n, où n est le nombre de bits dans T. En d'autres termes, la représentation binaire est tronquée pour s'adapter.

  • Le Rounding functions prend un type T comme argument optionnel. Par exemple, round(Int,x) est un raccourci pour Int(round(x)).

Les exemples suivants montrent les différentes formes.

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:
[...]

Voir Conversion and Promotion pour savoir comment définir vos propres conversions et promotions.

Rounding functions

FunctionDescriptionReturn type
round(x)round x to the nearest integertypeof(x)
round(T, x)round x to the nearest integerT
floor(x)round x towards -Inftypeof(x)
floor(T, x)round x towards -InfT
ceil(x)round x towards +Inftypeof(x)
ceil(T, x)round x towards +InfT
trunc(x)round x towards zerotypeof(x)
trunc(T, x)round x towards zeroT

Division functions

FunctionDescription
div(x, y), x÷ytruncated 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%yremainder; 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

FunctionDescription
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

FunctionDescription
sqrt(x), √xsquare root of x
cbrt(x), ∛xcube 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

Pour un aperçu des raisons pour lesquelles des fonctions comme hypot, expm1, et log1p sont nécessaires et utiles, consultez les excellents articles de blog de John D. Cook sur le sujet : expm1, log1p, erfc, et hypot.

Trigonometric and hyperbolic functions

Toutes les fonctions trigonométriques et hyperboliques standard sont également définies :

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

Ce sont toutes des fonctions à un seul argument, avec atan acceptant également deux arguments correspondant à une fonction traditionnelle atan2.

De plus, sinpi(x) et cospi(x) sont fournis pour des calculs plus précis de sin(pi * x) et cos(pi * x) respectivement.

Pour calculer des fonctions trigonométriques avec des degrés au lieu de radians, suffixez la fonction avec d. Par exemple, sind(x) calcule le sinus de xx est spécifié en degrés. La liste complète des fonctions trigonométriques avec des variantes en degrés est :

sind   cosd   tand   cotd   secd   cscd
asind  acosd  atand  acotd  asecd  acscd

Special functions

De nombreuses autres fonctions mathématiques spéciales sont fournies par le package 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., √√-a as √(√(-a)).
  • 2The operators +, ++ and * are non-associative. a + b + c is 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.