Tipos de datos de Julia
En los lenguajes de programación, hay operaciones matemáticas básicas y cálculos científicos, y sus tipos de datos más comunes sonenterosyde punto flotantenúmeros.Además, existe un«literal»término llamado «literal» (literal) se utiliza para expresar una notación de un valor fijo en el código fuente; los enteros, los números de punto flotante y las cadenas, etc., son literales.
Por ejemplo:
a=1 // a es una variable, 1 es un literal entero b=1.0 // b es una variable, 1.0 es un literal de punto flotanteJulia proporciona una gran variedad de tipos numéricos primitivos, y sobre ellos define todo un conjunto de operaciones aritméticas; además, ofrece operadores bit a bit y algunas funciones matemáticas estándar.
Tipos de enteros
La siguiente tabla enumera los tipos de enteros que admite Julia:
| Tipo | ¿Con signo? | Número de bits | Valor mínimo | Valor máximo |
|---|---|---|---|---|
| Int8 | ✓ | 8 | -2^7 | 2^7 – 1 |
| UInt8 | 8 | 0 | 2^8 – 1 | |
| Int16 | ✓ | 16 | -2^15 | 2^15 – 1 |
| UInt16 | 16 | 0 | 2^16 – 1 | |
| Int32 | ✓ | 32 | -2^31 | 2^31 – 1 |
| UInt32 | 32 | 0 | 2^32 – 1 | |
| Int64 | ✓ | 64 | -2^63 | 2^63 – 1 |
| UInt64 | 64 | 0 | 2^64 – 1 | |
| Int128 | ✓ | 128 | -2^127 | 2^127 – 1 |
| UInt128 | 128 | 0 | 2^128 – 1 | |
| Bool | N/A | 8 | false (0) | true (1) |
Formas de literales enteros:
Ejemplo
1
julia> 1234
1234
El tipo predeterminado de un literal entero depende de si el sistema de destino tiene arquitectura de 32 o 64 bits (la mayoría de los sistemas actuales son de 64 bits):
Ejemplo
julia> typeof(1)
Int32
# Sistema de 64 bits:
julia> typeof(1)
Int64
La variable integrada de JuliaSys.WORD_SIZEindica si el sistema de destino tiene arquitectura de 32 o 64 bits:
Ejemplo
julia> Sys.WORD_SIZE
32
# Sistema de 64 bits:
julia> Sys.WORD_SIZE
64
Julia también define los tipos Int y UInt, que son alias de los tipos de enteros nativos con signo y sin signo del sistema, respectivamente.
Ejemplo
julia> Int
Int32
julia> UInt
UInt32
# Sistema de 64 bits:
julia> Int
Int64
julia> UInt
UInt64
Comportamiento de desbordamiento
En Julia, superar el valor máximo representable de un tipo provoca un comportamiento de ajuste (wraparound):
Ejemplo
9223372036854775807
julia> x + 1
-9223372036854775808
julia> x + 1 == typemin(Int64)
true
Por lo tanto, la aritmética de enteros de Julia es en realidad una forma de aritmética modular, que refleja cómo los ordenadores modernos implementan la aritmética subyacente. En programas donde pueda producirse desbordamiento, es necesario comprobar explícitamente la aparición de ciclos en los límites de los valores máximo y mínimo. De lo contrario, se recomienda utilizar el tipo BigInt de aritmética de precisión arbitraria como alternativa.
A continuación se muestra un ejemplo de comportamiento de desbordamiento y cómo resolverlo:
Ejemplo
-8446744073709551616
julia> big(10)^19
10000000000000000000
Errores de división
En las dos siguientes situaciones excepcionales, la división de enteros desencadena un error DivideError:- Dividir por cero
- Dividir por el número negativo más pequeño
remLa función de resto ymodla función de módulo lanzan un error DivideError al dividir por cero; ejemplo:
Ejemplo
ERROR: DivideError: integer division error
Stacktrace:
[1] div at .\int.jl:260 [inlined]
[2] div at .\div.jl:217 [inlined]
[3] div at .\div.jl:262 [inlined]
[4] fld at .\div.jl:228 [inlined]
[5] mod(::Int64, ::Int64) at .\int.jl:252
[6] top-level scope at REPL[52]:1
julia> rem(1, 0)
ERROR: DivideError: integer division error
Stacktrace:
[1] rem(::Int64, ::Int64) at .\int.jl:261
[2] top-level scope at REPL[54]:1
Tipos de punto flotante
La siguiente tabla enumera los tipos de punto flotante que admite Julia:
| Tipo | Precisión | Número de bits |
|---|---|---|
| Float16 | Precisión media | 16 |
| Float32 | Precisión simple | 32 |
| Float64 | Precisión doble | 64 |
Además, el soporte completo para números complejos y racionales se construye sobre estos tipos de datos primitivos.
El formato de los literales de punto flotante se representa a continuación; cuando sea necesario, se puede usarEpara representarlo.
Ejemplo
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
Nota:
En la notación científica, para simplificar las fórmulas, se puede usar laEforma con ... para representar. Por ejemplo, 1.03 multiplicado por 10 elevado a la octava potencia se puede abreviar como «1.03E+08», donde «E» es la abreviatura de exponent (exponente).
Los resultados anteriores son todos valores de tipo Float64. Si se usa f en lugar de e, se pueden obtener literales de tipo Float32:
Ejemplo
0.5f0
julia> typeof(x)
Float32
julia> 2.5f-4
0.00025f0
Los valores numéricos se pueden convertir fácilmente alFloat32tipo:
julia> x = Float32(-1.5)
-1.5f0
julia> typeof(x)
Float32
También existen literales de punto flotante hexadecimales, pero solo se aplican a valores de tipo Float64. Generalmente se representan usando el prefijo p y un exponente en base 2:
Ejemplo
1.0
julia> 0x1.8p3
12.0
julia> x = 0x.4p-1
0.125
julia> typeof(x)
Float64
Julia también admite números de punto flotante de media precisión (Float16), pero se implementan medianteFloat32simulación por software.
julia> sizeof(Float16(4.))
2
julia> 2*Float16(4.)
Float16(8.0)
Guion bajo_Se puede usar como separador de dígitos:
Ejemplo
(10000, 5.0e-9, 0xdeadbeef, 0xb2)
El cero en los números de punto flotante
Los números de punto flotante tienen dos ceros: el cero positivo y el cero negativo. Son iguales entre sí, pero tienen representaciones binarias diferentes; se puede comprobar con la función bitstring:
Ejemplo
true
julia> bitstring(0.0)
"0000000000000000000000000000000000000000000000000000000000000000"
julia> bitstring(-0.0)
"1000000000000000000000000000000000000000000000000000000000000000"
Valores especiales de punto flotante
Hay tres valores estándar de punto flotante específicos que no se corresponden con ningún punto del eje de los números reales:
| Float16 | Float32 | Float64 | Nombre | Descripción |
|---|---|---|---|---|
| Inf16 | Inf32 | Inf | Infinito positivo | Un número mayor que todos los números de punto flotante finitos |
| -Inf16 | -Inf32 | -Inf | Infinito negativo | Un número menor que todos los números de punto flotante finitos |
| NaN16 | NaN32 | NaN | No es un número | Un valor que no es igual (==) a ningún valor de punto flotante (incluido sí mismo) |
A continuación se muestran algunos ejemplos de operaciones con números de punto flotante:
Ejemplo
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
julia> Inf / Inf
NaN
julia> 0 * Inf
NaN
julia> NaN == NaN
false
julia> NaN != NaN
true
julia> NaN < NaN
false
julia> NaN > NaN
false
También podemos usar las funciones typemin y typemax:
Ejemplo
(-Inf16, Inf16)
julia> (typemin(Float32),typemax(Float32))
(-Inf32, Inf32)
julia> (typemin(Float64),typemax(Float64))
(-Inf, Inf)
Precisión de la máquina
La mayoría de los números reales no se pueden representar con precisión mediante números de punto flotante, por lo que es necesario conocer la distancia entre dos números de punto flotante representables adyacentes, a la que generalmente se llama precisión de la máquina.
Julia proporciona laepsfunción, que puede dar la diferencia entre 1.0 y el siguiente número de punto flotante que Julia puede representar:
Ejemplo
1.1920929f-7
julia> eps(Float64)
2.220446049250313e-16
julia> eps() # Igual que eps(Float64)
2.220446049250313e-16
Estos valores son 2.0^-23 en Float32 y 2.0^-52 en Float64, respectivamente. La función eps también puede aceptar un valor de punto flotante como argumento y devolver la diferencia absoluta entre ese valor y el siguiente valor de punto flotante representable. Es decir, eps(x) produce un valor del mismo tipo que x, y x + eps(x) es exactamente el siguiente valor de punto flotante representable mayor que x:
Ejemplo
2.220446049250313e-16
julia> eps(1000.)
1.1368683772161603e-13
julia> eps(1e-27)
1.793662034335766e-43
julia> eps(0.0)
5.0e-324
La distancia entre dos números de punto flotante representables adyacentes no es constante; cuanto menor es el valor, menor es la distancia, y cuanto mayor es el valor, mayor es la distancia. En otras palabras, los números de punto flotante representables son más densos cerca del cero en el eje real y se vuelven cada vez más dispersos, a una velocidad exponencial, a medida que se alejan del cero. Por definición, eps(1.0) es igual a eps(Float64), porque 1.0 es un valor de punto flotante de 64 bits.
Julia también proporciona las funciones nextfloat y prevfloat, que devuelven, respectivamente, el siguiente número de punto flotante representable mayor o menor basado en el argumento:
Ejemplo
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"
Este ejemplo refleja el principio general de que los números de punto flotante representables adyacentes también tienen representaciones de enteros binarios adyacentes.
Modos de redondeo
Si un número no tiene una representación exacta en punto flotante, debe redondearse a un valor representable adecuado.
El modo predeterminado que usa Julia es siempreRoundNearest, es decir, redondear al valor representable más cercano; este valor redondeado usará la menor cantidad posible de dígitos significativos.
Ejemplo
1.5
julia> BigFloat("1.550564889",2,RoundNearest)
1.5
julia> BigFloat("1.560564889",2,RoundNearest)
1.5
Literales de 0 y 1
Julia proporciona funciones de literales de 0 y 1, que pueden devolver el tipo específico o el tipo de la variable dada.
| Función | Descripción |
|---|---|
| zero(x) | Literal cero del tipo x o del tipo de la variable x |
| one(x) | Literal uno del tipo x o del tipo de la variable x |
Estas funciones se pueden usar en comparaciones numéricas para evitar la sobrecarga innecesaria de conversión de tipos.
Por ejemplo:
Ejemplo
0.0f0
julia> zero(1.0)
0.0
julia> one(Int32)
1
julia> one(BigFloat)
1.0
Conversión de tipos
La conversión de tipos consiste en convertir una variable de un tipo a otro tipo de datos. Por ejemplo, si desea almacenar un valor de tipo float en un entero simple, necesita convertir forzosamente el tipo float al tipo int. Puede usar el operador de conversión forzada de tipos para convertir explícitamente un valor de un tipo a otro, como se muestra a continuación:
Julia admite tres tipos de conversión numérica, que difieren en cómo manejan las conversiones inexactas.Primera forma:
T(x) o convert(T,x)
Todo lo anterior convierte x al tipo T.
- Si T es un tipo de punto flotante, el resultado de la conversión es el valor representable más cercano, que puede ser infinito positivo o negativo.
- Si T es un tipo entero, se lanza un InexactError cuando x no puede ser representado por el tipo T.
Segunda forma:
x % TTambién se puede convertir el entero x a un tipo entero T, lo que equivale al resultado de x módulo 2^n, donde n es el número de bits de T.
Tercera forma:
Las funciones de redondeo aceptan un argumento opcional de tipo T. Por ejemplo, round(Int,x) esInt(round(x))una versión abreviada de.
Ejemplo
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: trunc(Int8, 128.0)
Stacktrace:
[...]