Mathematical Operations and Elementary Functions

Julia proporciona una colección completa de operadores aritméticos básicos y bit a bit en todos sus tipos primitivos numéricos, así como implementaciones portátiles y eficientes de una colección integral de funciones matemáticas estándar.

Arithmetic Operators

Los siguientes arithmetic operators son compatibles con todos los tipos numéricos primitivos:

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 literal numérico colocado directamente antes de un identificador o paréntesis, por ejemplo, 2x o 2(x + y), se trata como una multiplicación, excepto con una precedencia más alta que otras operaciones binarias. Consulta Numeric Literal Coefficients para más detalles.

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.

El signo ÷ se puede escribir cómodamente escribiendo \div<tab> en el REPL o en el IDE de Julia. Consulta el manual section on Unicode input para más información.

Aquí hay algunos ejemplos simples utilizando operadores aritméticos:

julia> 1 + 2 + 3
6

julia> 1 - 2
-1

julia> 3*2/12
0.5

(Por convención, tendemos a espaciar los operadores más estrechamente si se aplican antes que otros operadores cercanos. Por ejemplo, generalmente escribiríamos -x + 2 para reflejar que primero se niega x, y luego se suma 2 a ese resultado.)

Cuando se utiliza en multiplicación, false actúa como un cero fuerte:

julia> NaN * false
0.0

julia> false * Inf
0.0

Esto es útil para prevenir la propagación de valores NaN en cantidades que se sabe que son cero. Consulta Knuth (1992) para más información.

Boolean Operators

Los siguientes Boolean operators son compatibles con Bool tipos:

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

La negación cambia true a false y viceversa. Las operaciones de cortocircuito se explican en la página vinculada.

Tenga en cuenta que Bool es un tipo de entero y todas las reglas de promoción habituales y los operadores numéricos también están definidos en él.

Bitwise Operators

Los siguientes bitwise operators son compatibles con todos los tipos de enteros primitivos:

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

Aquí hay algunos ejemplos con operadores a nivel de bits:

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

Cada operador aritmético binario y operador a nivel de bits también tiene una versión de actualización que asigna el resultado de la operación de nuevo a su operando izquierdo. La versión de actualización del operador binario se forma colocando un = inmediatamente después del operador. Por ejemplo, escribir x += 3 es equivalente a escribir x = x + 3:

julia> x = 1
1

julia> x += 3
4

julia> x
4

Las versiones actualizadas de todos los operadores aritméticos binarios y bit a bit son:

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

Un operador de actualización vuelve a enlazar la variable en el lado izquierdo. Como resultado, el tipo de la variable puede cambiar.

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

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

julia> typeof(x)
Int64

Vectorized "dot" operators

Para cada operación binaria como ^, hay una operación "punto" correspondiente .^ que se define automáticamente para realizar ^ elemento por elemento en arreglos. Por ejemplo, [1, 2, 3] ^ 3 no está definido, ya que no hay un significado matemático estándar para "elevar al cubo" un arreglo (no cuadrado), pero [1, 2, 3] .^ 3 se define como el cálculo del resultado elemento a elemento (o "vectorizado") [1^3, 2^3, 3^3]. De manera similar, para operadores unarios como ! o , hay un correspondiente .√ que aplica el operador elemento por elemento.

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

Más específicamente, a .^ b se analiza como el "dot" call (^).(a,b), que realiza una operación de broadcast: puede combinar arreglos y escalares, arreglos del mismo tamaño (realizando la operación elemento a elemento), e incluso arreglos de diferentes formas (por ejemplo, combinando vectores fila y columna para producir una matriz). Además, como todas las "llamadas de punto" vectorizadas, estos "operadores de punto" son fusionados. Por ejemplo, si calculas 2 .* A.^2 .+ sin.(A) (o de manera equivalente @. 2A^2 + sin(A), usando el @. macro) para un arreglo A, realiza un único bucle sobre A, computando 2a^2 + sin(a) para cada elemento a de A. En particular, las llamadas de punto anidadas como f.(g.(x)) se fusionan, y los operadores binarios "adyacentes" como x .+ 3 .* x.^2 son equivalentes a llamadas de punto anidadas (+).(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).

Tenga en cuenta que la sintaxis de punto también es aplicable a los operadores definidos por el usuario. Por ejemplo, si define ⊗(A, B) = kron(A, B) para dar una sintaxis infija conveniente A ⊗ B para productos de Kronecker (kron), entonces [A, B] .⊗ [C, D] calculará [A⊗C, B⊗D] sin codificación adicional.

Combinar operadores de punto con literales numéricos puede ser ambiguo. Por ejemplo, no está claro si 1.+x significa 1. + x o 1 .+ x. Por lo tanto, esta sintaxis no está permitida, y se deben usar espacios alrededor del operador en tales casos.

Numeric Comparisons

Las operaciones de comparación estándar están definidas para todos los tipos numéricos primitivos:

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

Aquí hay algunos ejemplos 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

Los enteros se comparan de la manera estándar, mediante la comparación de bits. Los números de punto flotante se comparan de acuerdo con el IEEE 754 standard:

  • Los números finitos están ordenados de la manera habitual.
  • Cero positivo es igual pero no mayor que cero negativo.
  • Inf es igual a sí mismo y mayor que todo lo demás excepto NaN.
  • -Inf es igual a sí mismo y menor que todo lo demás excepto NaN.
  • NaN no es igual a, no es menor que, y no es mayor que nada, incluyendo a sí mismo.

El último punto es potencialmente sorprendente y, por lo tanto, vale la pena señalarlo:

julia> NaN == NaN
false

julia> NaN != NaN
true

julia> NaN < NaN
false

julia> NaN > NaN
false

y puede causar dolores de cabeza al trabajar con arrays:

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

Julia proporciona funciones adicionales para probar números en busca de valores especiales, lo que puede ser útil en situaciones como comparaciones de claves hash:

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 considera que los NaNs son iguales entre sí:

julia> isequal(NaN, NaN)
true

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

julia> isequal(NaN, NaN32)
true

isequal también se puede utilizar para distinguir ceros con signo:

julia> -0.0 == 0.0
true

julia> isequal(-0.0, 0.0)
false

Las comparaciones de tipos mixtos entre enteros con signo, enteros sin signo y flotantes pueden ser complicadas. Se ha tenido mucho cuidado para asegurar que Julia las realice correctamente.

Para otros tipos, isequal por defecto llama a ==, así que si deseas definir la igualdad para tus propios tipos, solo necesitas agregar un método 4d61726b646f776e2e436f64652822222c20223d3d2229_40726566. Si defines tu propia función de igualdad, probablemente deberías definir un método correspondiente hash para asegurar que isequal(x,y) implica hash(x) == hash(y).

Chaining comparisons

A diferencia de la mayoría de los lenguajes, con el notable exception of Python, las comparaciones se pueden encadenar arbitrariamente:

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

La comparación encadenada es a menudo bastante conveniente en el código numérico. Las comparaciones encadenadas utilizan el operador && para comparaciones escalares, y el operador & para comparaciones elemento a elemento, lo que les permite funcionar en arreglos. Por ejemplo, 0 .< A .< 1 da un arreglo booleano cuyas entradas son verdaderas donde los elementos correspondientes de A están entre 0 y 1.

Nota el comportamiento de evaluación de las comparaciones encadenadas:

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

La expresión del medio solo se evalúa una vez, en lugar de dos veces como lo haría si la expresión se escribiera como v(1) < v(2) && v(2) <= v(3). Sin embargo, el orden de las evaluaciones en una comparación encadenada no está definido. Se recomienda encarecidamente no usar expresiones con efectos secundarios (como imprimir) en comparaciones encadenadas. Si se requieren efectos secundarios, se debe usar explícitamente el operador de cortocircuito && (ver Short-Circuit Evaluation).

Elementary Functions

Julia proporciona una colección completa de funciones y operadores matemáticos. Estas operaciones matemáticas están definidas sobre una clase tan amplia de valores numéricos como permitan definiciones sensatas, incluidos enteros, números de punto flotante, racionales y números complejos, donde tales definiciones tengan sentido.

Además, estas funciones (como cualquier función de Julia) se pueden aplicar de manera "vectorizada" a arreglos y otras colecciones con el dot syntax f.(A), por ejemplo, sin.(A) calculará el seno de cada elemento de un arreglo A.

Operator Precedence and Associativity

Julia aplica el siguiente orden y asociatividad de las operaciones, de mayor a menor precedencia:

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

Para una lista completa de la precedencia de cada operador de Julia, consulta la parte superior de este archivo: src/julia-parser.scm. Ten en cuenta que algunos de los operadores allí no están definidos en el módulo Base, pero pueden tener definiciones proporcionadas por bibliotecas estándar, paquetes o código de usuario.

También puedes encontrar la precedencia numérica para cualquier operador dado a través de la función incorporada Base.operator_precedence, donde los números más altos tienen precedencia:

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 símbolo que representa la asociatividad del operador también se puede encontrar llamando a la función incorporada 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)

Tenga en cuenta que símbolos como :sin devuelven una precedencia de 0. Este valor representa operadores inválidos y no operadores de menor precedencia. De manera similar, a dichos operadores se les asigna una asociatividad :none.

Numeric literal coefficients, p. ej. 2x, se tratan como multiplicaciones con mayor precedencia que cualquier otra operación binaria, con la excepción de ^ donde tienen mayor precedencia solo como el exponente.

julia> x = 3; 2x^2
18

julia> x = 3; 2^2x
64

La yuxtaposición se analiza como un operador unario, que tiene la misma asimetría natural alrededor de los exponentes: -x^y y 2x^y se analizan como -(x^y) y 2(x^y), mientras que x^-y y x^2y se analizan como x^(-y) y x^(2y).

Numerical Conversions

Julia admite tres formas de conversión numérica, que difieren en su manejo de conversiones inexactas.

  • La notación T(x) o convert(T, x) convierte x en un valor del tipo T.

    • Si T es un tipo de punto flotante, el resultado es el valor representable más cercano, que podría ser infinito positivo o negativo.
    • Si T es un tipo entero, se genera un InexactError si x no es representable por T.
  • x % T convierte un entero x a un valor del tipo entero T congruente con x módulo 2^n, donde n es el número de bits en T. En otras palabras, la representación binaria se trunca para ajustarse.

  • El Rounding functions toma un tipo T como un argumento opcional. Por ejemplo, round(Int,x) es una forma abreviada de Int(round(x)).

Los siguientes ejemplos muestran las diferentes formas.

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

Vea Conversion and Promotion para saber cómo definir sus propias conversiones y promociones.

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

Para una visión general de por qué funciones como hypot, expm1, y log1p son necesarias y útiles, consulte la excelente pareja de publicaciones de blog de John D. Cook sobre el tema: expm1, log1p, erfc, y hypot.

Trigonometric and hyperbolic functions

Todas las funciones trigonométricas e hiperbólicas estándar también están definidas:

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

Estos son todos funciones de un solo argumento, con atan también aceptando dos argumentos que corresponden a una función tradicional atan2.

Además, sinpi(x) y cospi(x) se proporcionan para cálculos más precisos de sin(pi * x) y cos(pi * x) respectivamente.

Para calcular funciones trigonométricas con grados en lugar de radianes, añade el sufijo d a la función. Por ejemplo, sind(x) calcula el seno de x donde x se especifica en grados. La lista completa de funciones trigonométricas con variantes en grados es:

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

Special functions

Muchas otras funciones matemáticas especiales son proporcionadas por el paquete 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.