stringtranslate.com

Unidad en el último lugar

En informática y análisis numérico , la unidad en el último lugar o unidad de menor precisión ( ulp ) es el espaciado entre dos números de punto flotante consecutivos , es decir, el valor que representa el dígito menos significativo (dígito más a la derecha) si es 1. Se utiliza como medida de precisión en cálculos numéricos. [1]

Definición

La definición más común es: En base con precisión , si , entonces , [2] donde es el exponente mínimo de los números normales. En particular, para los números normales , y para los subnormales .

Otra definición, sugerida por John Harrison, es ligeramente diferente: es la distancia entre los dos números de punto flotante más cercanos y (es decir, que satisface y ), asumiendo que el rango del exponente no está acotado en la parte superior. [3] [4] Estas definiciones difieren solo en potencias con signo del radix. [2]

La especificación IEEE 754 (seguida por todo el hardware de punto flotante moderno) requiere que el resultado de una operación aritmética elemental (suma, resta, multiplicación, división y raíz cuadrada desde 1985, y FMA desde 2008) se redondee correctamente , lo que implica que al redondear al más cercano, el resultado redondeado está dentro de 0,5 ulp del resultado matemáticamente exacto, utilizando la definición de John Harrison; por el contrario, esta propiedad implica que la distancia entre el resultado redondeado y el resultado matemáticamente exacto se minimiza (pero para los casos intermedios, se satisface con dos números de punto flotante consecutivos). Las bibliotecas numéricas de buena reputación calculan las funciones trascendentales básicas entre 0,5 y aproximadamente 1 ulp. Solo unas pocas bibliotecas las calculan dentro de 0,5 ulp, siendo este problema complejo debido al dilema del creador de tablas . [5]

Desde la década de 2010, los avances en las matemáticas de punto flotante han permitido que las funciones correctamente redondeadas sean casi tan rápidas en promedio como estas funciones anteriores, menos precisas. Una función correctamente redondeada también sería completamente reproducible. Un hito intermedio anterior fueron las funciones ulp 0.501, [ aclaración necesaria ] que teóricamente solo producirían un redondeo incorrecto de cada 1000 entradas aleatorias de punto flotante. [6]

Ejemplos

Ejemplo 1

Sea un número de punto flotante positivo y supongamos que el modo de redondeo activo es redondear al más cercano, igual a par , denotado . Si , entonces . En caso contrario, o , dependiendo del valor del dígito menos significativo y del exponente de . Esto se demuestra en el siguiente código Haskell escrito en un mensaje interactivo: [ cita requerida ]

> hasta ( \ x -> x == x + 1 ) ( + 1 ) 0 :: Flotante         1.6777216e7> es - 11.6777215e7> es + 11.6777216e7

Aquí comenzamos con 0 en precisión simple (binary32) y sumamos 1 repetidamente hasta que la operación no cambie el valor. Dado que la mantisa de un número de precisión simple contiene 24 bits, el primer entero que no es exactamente representable es 2 24 +1, y este valor se redondea a 2 24 en redondeo al más cercano, empata con par. Por lo tanto, el resultado es igual a 2 24 .

Ejemplo 2

El siguiente ejemplo en Java aproxima π como un valor de punto flotante al encontrar los dos valores dobles que se encuentran entre paréntesis : .

// π con 20 dígitos decimales BigDecimal π = new BigDecimal ( "3.14159265358979323846" );    // trunca a un doble punto flotante double p0 = π . doubleValue (); // -> 3.141592653589793 (hex: 0x1.921fb54442d18p1)   // p0 es menor que π, por lo que busca el siguiente número representable como double double p1 = Math . nextUp ( p0 ); // -> 3.1415926535897936 (hex: 0x1.921fb54442d19p1)   

Entonces se determina como .

// ulp(π) es la diferencia entre p1 y p0 BigDecimal ulp = new BigDecimal ( p1 ). subtract ( new BigDecimal ( p0 )); // -> 4.44089209850062616169452667236328125E-16 // (esto es precisamente 2**(-51))     // mismo resultado al utilizar la función de biblioteca estándar double ulpMath = Math . ulp ( p0 ); // -> 4.440892098500626E-16 (hex: 0x1.0p-51)   

Ejemplo 3

Otro ejemplo, en Python , también escrito en un indicador interactivo, es:

>>> x  =  1.0 >>> p  =  0 >>> mientras  x  !=  x  +  1 : ...  x  =  x  *  2 ...  p  =  p  +  1 ... >>> x 9007199254740992.0 >>> p 53 >>> x  +  2  +  1 9007199254740996.0

En este caso, comenzamos con x = 1y lo duplicamos repetidamente hasta x = x + 1. De manera similar al Ejemplo 1, el resultado es 2 53 porque el formato de punto flotante de doble precisión utiliza un mantisa de 53 bits.

Soporte de idiomas

Las bibliotecas Boost C++ proporcionan las funciones boost::math::float_next, boost::math::float_prior, boost::math::nextafter y boost::math::float_advancepara obtener valores de punto flotante cercanos (y distantes), [7] y boost::math::float_distance(a, b)para calcular la distancia de punto flotante entre dos dobles. [8]

La biblioteca del lenguaje C proporciona funciones para calcular el siguiente número de punto flotante en una dirección dada: nextafterfy nexttowardfpara float, nextaftery nexttowardpara double, nextafterly nexttowardlpara long double, declaradas en <math.h>. También proporciona las macros FLT_EPSILON, DBL_EPSILON, LDBL_EPSILON, que representan la diferencia positiva entre 1.0 y el siguiente número mayor representable en el tipo correspondiente (es decir, el ulp de uno). [9]

La biblioteca estándar de Java proporciona las funciones Math.ulp(double)y Math.ulp(float). Se introdujeron con Java 1.5.

La biblioteca estándar de Swift proporciona acceso al siguiente número de punto flotante en una dirección determinada a través de las propiedades de instancia nextDowny nextUp. También proporciona la propiedad de instancia ulpy la propiedad de tipo ulpOfOne(que corresponde a macros de C como FLT_EPSILON[10] ) para los tipos de punto flotante de Swift. [11]

Véase también

Referencias

  1. ^ Goldberg, David (marzo de 1991). "Lo que todo informático debería saber sobre aritmética de punto flotante". Encuestas de computación de la ACM . 23 (1): 5–48. doi : 10.1145/103162.103163 . S2CID  : 222008826.(Con el apéndice "Diferencias entre las implementaciones de IEEE 754": [1], [2]).
  2. ^ ab Müller, Jean-Michel; Brunie, Nicolás; de Dinechin, Florent; Jeannerod, Claude-Pierre; Joldes, Mioara; Lefèvre, Vicente; Melquiond, Guillaume; Revol, Nathalie ; Torres, Serge (2018) [2010]. Manual de aritmética de coma flotante (2 ed.). Birkhäuser . doi :10.1007/978-3-319-76526-6. ISBN 978-3-319-76525-9.
  3. ^ Harrison, John. "Una teoría de la aritmética de punto flotante comprobada por máquina" . Consultado el 17 de julio de 2013 .
  4. ^ Muller, Jean-Michel (2005–11). "Sobre la definición de ulp(x)". INRIA Technical Report 5504. ACM Transactions on Mathematical Software, Vol. V, No. N, noviembre de 2005. Recuperado en 2012-03 de http://ljk.imag.fr/membres/Carine.Lucas/TPScilab/JMMuller/ulp-toms.pdf.
  5. ^ Kahan, William. "Un logaritmo demasiado inteligente" . Consultado el 14 de noviembre de 2008 .
  6. ^ Brisebarre, Nicolas; Hanrot, Guillaume; Muller, Jean-Michel; Zimmermann, Paul (mayo de 2024). "Evaluación correctamente redondeada de una función: ¿por qué, cómo y a qué costo?".
  7. ^ Aumenta el float_advance.
  8. ^ Aumenta la distancia flotante.
  9. ^ Especificación ISO/IEC 9899:1999 (PDF) . p. 237, §7.12.11.3 Las funciones nextafter y §7.12.11.4 Las funciones nexttoward .
  10. ^ "ulpOfOne - FloatingPoint | Documentación para desarrolladores de Apple". Apple Inc. Apple Inc. Consultado el 18 de agosto de 2019 .
  11. ^ "FloatingPoint - Biblioteca estándar de Swift | Documentación para desarrolladores de Apple". Apple Inc. Apple Inc. Consultado el 18 de agosto de 2019 .

Bibliografía