Números de punto flotante
MATLAB® representa números de punto flotante en formato de doble precisión o en formato de precisión simple. El formato predeterminado es el de doble precisión, pero puede pasar cualquier número a formato de precisión simple con una función sencilla de conversión.
Punto flotante de doble precisión
MATLAB construye el tipo de datos de doble precisión (o double
) de acuerdo con el estándar 754 del IEEE® para doble precisión. Cualquier valor almacenado como un double
requiere 64 bits, con formato como se muestra en la siguiente tabla:
Bits | Uso |
---|---|
| Signo ( |
| Exponente, sesgado por |
| Fracción |
Punto flotante de precisión simple
MATLAB construye el tipo de datos de precisión simple (o single
) de acuerdo con el estándar 754 del IEEE para precisión simple. Cualquier valor almacenado como un single
requiere 32 bits, con formato como se muestra en la siguiente tabla:
Bits | Uso |
---|---|
| Signo ( |
| Exponente, sesgado por |
| Fracción |
Dado que MATLAB almacena números de tipo single
usando 32 bits, requieren menos memoria que los números de tipo double
, que utilizan 64 bits. Sin embargo, dado que los números de tipo single
se almacenan con menos bits, se representan con menos precisión que los números de tipo double
.
Crear datos de punto flotante
Utilice la doble precisión para almacenar valores mayores que aproximadamente 3,4 x 1038 o menores que aproximadamente -3,4 x 1038. Para números que se encuentren entre estos dos límites, puede utilizar o bien la doble precisión o bien la precisión simple, pero la precisión simple requiere menos memoria.
Crear datos de doble precisión
Dado que el tipo numérico predeterminado para MATLAB es double
, puede crear un double
con una instrucción sencilla de asignación:
x = 25.783;
La función whos
muestra que MATLAB ha creado un arreglo de 1 por 1 de tipo double
para el valor que acaba de almacenar en x
:
whos x Name Size Bytes Class x 1x1 8 double
Utilice isfloat
si solo desea verificar que x
es un número de punto flotante. Esta función devuelve un 1 lógico (true
) si la entrada es un número de punto flotante y un 0 lógico (false
) si no lo es:
isfloat(x) ans = logical 1
Puede convertir otros datos numéricos, caracteres o cadenas, y datos lógicos a doble precisión mediante la función double
de MATLAB. En este ejemplo se convierte un entero con signo a punto flotante de doble precisión:
y = int64(-589324077574); % Create a 64-bit integer x = double(y) % Convert to double x = -5.8932e+11
Crear datos de precisión simple
Dado que MATLAB almacena datos numéricos como un double
de forma predeterminada, debe utilizar la función de conversión single
para crear un número de precisión simple:
x = single(25.783);
La función whos
devuelve los atributos de la variable x
en una estructura. El campo bytes
de esta estructura muestra que cuando se almacena x
como un simple, solo hacen falta 4 bytes en comparación con los 8 bytes necesarios para almacenarlo como un double
.
xAttrib = whos('x'); xAttrib.bytes ans = 4
Puede convertir otros datos numéricos, caracteres o cadenas, y datos lógicos a precisión simple mediante la función single
. En este ejemplo se convierte un entero con signo a punto flotante de precisión simple:
y = int64(-589324077574); % Create a 64-bit integer x = single(y) % Convert to single x = single -5.8932e+11
Operaciones aritméticas en números de punto flotante
En esta sección se describe qué clases puede utilizar en las operaciones aritméticas con números de punto flotante.
Operaciones de doble precisión
Puede realizar operaciones aritméticas básicas con double
y cualquiera de las siguientes otras clases. Cuando uno o más operandos son un entero (escalar o arreglo), el operando double
debe ser un escalar. El resultado es de tipo double
, salvo cuando se observe lo contrario:
single
: el resultado es de tiposingle
double
int*
ouint*
: el resultado tiene el mismo tipo de datos que el operando de enteroschar
logical
En este ejemplo se realizan operaciones aritméticas con datos de tipo char
y double
. El resultado es de tipo double
:
c = 'uppercase' - 32; class(c) ans = double char(c) ans = UPPERCASE
Operaciones de precisión simple
Puede realizar operaciones aritméticas básicas con single
y cualquiera de las siguientes otras clases. El resultado siempre es single
:
single
double
char
logical
En este ejemplo, de forma predeterminada, 7.5 es de tipo double
y el resultado es de tipo single
:
x = single([1.32 3.47 5.28]) .* 7.5; class(x) ans = single
Los valores más grandes y más pequeños para clases de punto flotante
Para las clases double
y single
, existe el número más grande y más pequeño que puede representar con ese tipo.
Los valores de doble precisión más grande y más pequeño
Las funciones de MATLAB realmax
y realmin
devuelven los valores máximos y mínimos que puede representar con el tipo de datos double
:
str = 'The range for double is:\n\t%g to %g and\n\t %g to %g'; sprintf(str, -realmax, -realmin, realmin, realmax) ans = The range for double is: -1.79769e+308 to -2.22507e-308 and 2.22507e-308 to 1.79769e+308
A los números mayores que realmax
o menores que -realmax
se les asignan los valores de infinito positivo y negativo, respectivamente:
realmax + .0001e+308 ans = Inf -realmax - .0001e+308 ans = -Inf
Los valores de precisión simple más grande y más pequeño
Las funciones de MATLAB realmax
y realmin
, cuando se llaman con el argumento 'single'
, devuelven los valores máximo y mínimo que puede representar con el tipo de datos single
:
str = 'The range for single is:\n\t%g to %g and\n\t %g to %g'; sprintf(str, -realmax('single'), -realmin('single'), ... realmin('single'), realmax('single')) ans = The range for single is: -3.40282e+38 to -1.17549e-38 and 1.17549e-38 to 3.40282e+38
A los números mayores que realmax('single')
o menores que -realmax('single')
se les asignan los valores de infinito positivo y negativo, respectivamente:
realmax('single') + .0001e+038 ans = single Inf -realmax('single') - .0001e+038 ans = single -Inf
Precisión de los datos de punto flotante
Si el resultado de un cálculo aritmético de punto flotante no es tan preciso como esperaba, es posible que se deba a las limitaciones de hardware de su equipo. Probablemente, el resultado sea un poco menos exacto porque el hardware no disponía de los suficientes bits para representar el resultado con una precisión perfecta. Por lo tanto, el valor resultante se ha truncado.
Precisión en doble precisión
Dado que existe solo un número finito de números de doble precisión, no puede representar todos los números en el almacenamiento de doble precisión. En cualquier ordenador, existe un pequeño vacío entre cada número de doble precisión y el siguiente número de doble precisión mayor. Puede determinar el tamaño de este vacío que limita la precisión de los resultados con la función eps
. Por ejemplo, para encontrar la distancia entre 5
y el siguiente número de doble precisión mayor, introduzca
format long eps(5) ans = 8.881784197001252e-16
Esto indica que no existen números de doble precisión entre 5 y 5 + eps(5)
. Si el cálculo de doble precisión devuelve la respuesta 5, el resultado solo es preciso dentro de eps(5)
.
El valor de eps(x)
depende de x
. En este ejemplo se muestra que, a medida que x
se hace más grande, también lo hace eps(x)
:
eps(50) ans = 7.105427357601002e-15
Si introduce eps
sin argumento de entrada, MATLAB devuelve el valor de eps(1)
, la distancia desde 1
hasta el siguiente número de doble precisión mayor.
Precisión en precisión simple
De forma similar, existen vacíos entre dos números de precisión simple cualesquiera. Si x
tiene el tipo single
, eps(x)
devuelve la distancia entre x
y el siguiente número de precisión simple mayor. Por ejemplo:
x = single(5); eps(x)
devuelve
ans = single 4.7684e-07
Observe que este resultado es mayor que eps(5)
. Dado que existen menos números de precisión simple que de doble precisión, los vacíos entre los números de precisión simple son mayores que los vacíos entre los números de doble precisión. Esto significa que los resultados de las operaciones aritméticas de precisión simple son menos precisos que los de las operaciones aritméticas de doble precisión.
Para un número x
de tipo double
, eps(single(x))
proporciona un límite superior para la cantidad con la que se redondea x
cuando se convierte de double
a single
. Por ejemplo, cuando convierte el número de doble precisión 3.14
a single
, se redondea con
double(single(3.14) - 3.14) ans = 1.0490e-07
La cantidad con la que 3.14
se redondea es inferior a
eps(single(3.14)) ans = single 2.3842e-07
Evitar problemas habituales con las operaciones aritméticas de punto flotante
Casi todas las operaciones en MATLAB se realizan con operaciones aritméticas de doble precisión, de acuerdo con el estándar 754 del IEEE. Dado que los ordenadores solo representan los números con una precisión finita (la doble precisión requiere 52 bits de mantisa), en ocasiones los cálculos producen resultados no intuitivos desde el punto de vista matemático. Es importante tener en cuenta que estos resultados no son bugs en MATLAB.
Utilice los siguientes ejemplos para ayudarle a identificar estos casos:
Ejemplo 1. Redondeo o lo que se obtiene no es lo que se espera
El número decimal 4/3
no se puede representar de manera exacta como una fracción binaria. Por esta razón, el siguiente cálculo no da cero, sino que revela la cantidad eps
.
e = 1 - 3*(4/3 - 1) e = 2.2204e-16
De manera similar, 0.1
no se puede representar de manera exacta como un número binario. Por tanto, obtiene el siguiente comportamiento no intuitivo:
a = 0.0; for i = 1:10 a = a + 0.1; end a == 1 ans = logical 0
Tenga en cuenta que el orden de las operaciones puede influir en el cálculo:
b = 1e-16 + 1 - 1e-16; c = 1e-16 - 1e-16 + 1; b == c ans = logical 0
Existen vacíos entre números de punto flotante. A medida que los números se hacen mayores, también lo hacen los vacíos, como demuestra:
(2^53 + 1) - 2^53 ans = 0
Dado que pi
no es realmente π, no resulta sorprendente que sin(pi)
no sea exactamente cero:
sin(pi) ans = 1.224646799147353e-16
Ejemplo 2. Cancelación catastrófica
Cuando se realizan restas con operandos casi iguales, en ocasiones puede producirse una cancelación de forma inesperada. A continuación, figura un ejemplo de una cancelación causada por empantanamiento (pérdida de precisión que hace que la suma sea insignificante).
sqrt(1e-16 + 1) - 1 ans = 0
Algunas funciones de MATLAB, como expm1
y log1p
, pueden utilizarse para compensar los efectos de una cancelación catastrófica.
Ejemplo 3. Operaciones de punto flotante y álgebra lineal
Redondeos, cancelaciones y otras cualidades de las operaciones aritméticas de punto flotante se combinan para producir cálculos sorprendentes cuando se resuelven problemas de álgebra lineal. MATLAB advierte de que la siguiente matriz A
está mal condicionada y, por lo tanto, el sistema Ax = b
puede ser susceptible a pequeñas perturbaciones:
A = diag([2 eps]); b = [2; eps]; y = A\b; Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.110223e-16.
Estos son tan solo algunos de los ejemplos que muestran cómo las operaciones aritméticas de punto flotante del IEEE afectan a los cálculos en MATLAB. Tenga en cuenta que todos los cálculos realizados en operaciones aritméticas de acuerdo con el estándar 754 del IEEE se ven afectados. Esto incluye las aplicaciones escritas en C o FORTRAN, así como MATLAB.
Referencias
[1] Moler, Cleve. “Floating Points.” MATLAB News and Notes. Fall, 1996.
[2] Moler, Cleve. Numerical Computing with MATLAB. Natick, MA: The MathWorks, Inc., 2004.