truncar round resueltos redondear punto operaciones limitar flotante float fijo entero ejercicios decimales con aritmetica floating-point double floating-accuracy ieee-754

floating-point - round - redondear decimales en java netbeans



¿Cómo simular el redondeo de precisión simple con dobles? (3)

Desea utilizar las funciones de biblioteca frexp y ldexp, que son funciones estándar de C99 y están disponibles en Lua.

frexp toma un número de punto flotante y separa la mantisa del exponente. La mantisa resultante es 0 o en uno de los rangos [0.5, 1.0) o (-1.0, 0.5]. A continuación, puede eliminar cualquier bit extra de la manera obvia ( floor(mantissa * 2^k)/2^k para valores no negativos, por ejemplo). (Editado para sumar :) Sería mejor restar k del exponente en la llamada a ldexp que hacer la división como se muestra, porque estoy bastante seguro de que Lua no garantiza que 2 ^ k es preciso.

ldexp es el inverso de frexp; Puedes usar eso para volver a juntar el número truncado.

No tengo idea de cómo hacer esto en Excel. Verifique el manual :) (Editado para agregar :) Supongo que podría obtener aproximadamente el mismo efecto al dividir el número entre 2 y la potencia del techo del registro 2 del número, y luego hacer la ronda binaria como se indicó anteriormente. y luego revertir el proceso para recrear el exponente original. Pero sospecho que los resultados ocasionalmente se encontrarían con peculiaridades con las ideas peculiares de Excel acerca de la aritmética.

Tuve un problema cuando intentaba reconstruir la fórmula utilizada en un sistema existente, una fórmula bastante simple de una entrada y una salida:

y = f(x)

Después de mucho desconcierto, we descubrir la fórmula que se ajusta a nuestros puntos de datos observados:

Y como puede ver, nuestro modelo teórico se ajusta muy bien a los datos observados:

Excepto cuando y = f(x) - actualY errores residuales (es decir, y = f(x) - actualY ), vemos que aparecen algunas líneas en los residuos:

Era obvio que estas líneas eran el resultado de aplicar un redondeo intermedio en nuestra fórmula, pero no era obvio dónde . Finalmente, se dio cuenta de que el sistema original (el que estamos intentando realizar ingeniería inversa) está almacenando valores en un tipo de datos Decimal intermedio:

  • Con precisión de 8 bits de la fracción.
  • utilizando el modelo de redondeo de 0,5 :

Podríamos simular esta precisión de 8 bits en la fracción por:

multiply by 128 (i.e. 2^8) apply the round divide by 128 (i.e. 2^8)

Cambiando nuestra ecuación anterior en:

Esto reduce significativamente los errores residuales:

Ahora, todo lo anterior no tiene relevancia para mi pregunta, excepto:

  1. Mostrar que la simulación de la representación numérica en la computadora puede ayudar al modelo.
  2. Para llamar la atención de la gente con bonitas imágenes y colores.
  3. Silencio críticos que would refuse a contribute hasta que explain por qué estoy haciendo mi pregunta

Ahora quiero simular números de punto flotante de Single Precision , dentro de un lenguaje de programación (y Excel) que usan números de punto flotante de Double Precision . Quiero hacer esto porque creo que es lo que se necesita.

En el ejemplo anterior, pensé que el sistema original estaba usando un Decimal data type with fixed 8-bit fractional precision using 0.5 round-up rules . Luego tuve que encontrar una manera de simular ese modelo de cálculo con Matemática Double . Ahora creo que el sistema original usa matemáticas de precisión Single , que quiero simular usando Double .

¿Cómo simulo el redondeo de precisión simple utilizando dobles?

En mi modelo actual, una vez más tengo residuos que caen dentro de los patrones lineales regulares, que son un signo revelador de redondeo:

El problema es que el error se vuelve más grande y solo visible, a medida que mis variables de entrada se hacen más grandes. Me di cuenta de que esto es probablemente causado por el hecho de que todos los números de punto flotante se normalizan en la "notación científica" IEEE 754 .

E incluso si estoy equivocado, todavía quiero intentarlo.

E incluso si no quiero probarlo, sigo haciendo la pregunta

¿Cómo simulo el redondeo de precisión Single utilizando Doubles ?

Me parece que todavía podría aplicar el concepto de "redondeo después de 8 bits fraccionarios" (aunque de 24 bits para el punto flotante de precisión simple), siempre que pueda "normalizar" el valor primero. p.ej

1234567898.76543

necesita ser convertido en (algo similar a):

1.23456789876543 E-09

Entonces podría aplicar mi "redondeo al bit 24" (es decir, 2 ^ 24 = 16,777,216)

floor(1.23456789876543E-09 * 16777216 + 0.5) / 16777216;

El problema, entonces, es qué combinación de sign , abs , ln , exp (u otras funciones) puedo aplicar para que pueda "normalizar" mi valor, redondearlo al n-ésimo lugar binario, luego "desnormalizarlo" ?

Nota : me doy cuenta de que la representación IEEE mantiene un 1 binario como el bit más significativo. Es posible que no necesite duplicar ese comportamiento para obtener resultados correctos. Por lo tanto, no es un factor decisivo, ni es un motivo para sugerir que todo el enfoque es un fracaso.

Ver también


Puede obtener la mayor parte del efecto del redondeo a precisión simple utilizando:

y = x + x * 0x1p29 - x * 0x1p29;

En la mayoría de los casos, esto produce el mismo resultado en y como si x se hubiera redondeado para flotar (IEEE 754 binario de 32 bits) y luego se convirtió de nuevo a doble (64 bits). Funciona agregando un valor (x * 0x1p29) que "empuja" algunos bits de x fuera del significando, provocando el redondeo en el bit 23 y luego restando el valor que se agregó. ( 0x1p29 es un punto flotante hexadecimal para 2 29 , 536870912.)

En casos raros, produce un resultado ligeramente diferente. Si simplemente desea reducir el ruido en un modelo, estos casos raros pueden ser despreciables. Si desea eliminarlos, entonces, en lugar de sumar y restar 2 29 x, puede encontrar la mayor potencia de 2 no mayor que xy sumar y restar 2 29 veces que en lugar de 2 29 x. (Para encontrar la potencia de 2, puede tomar el logaritmo de base dos y tomar el piso de eso. Sin embargo, todavía hay problemas de redondeo que pueden requerir compensación. Además, si la entrada puede ser cero o negativa, debe evitar el error que se produce al tomar su logaritmo.)

Además, esto no reproduce el comportamiento para los números que son subnormales en precisión simple o que se desbordan en precisión simple.

Finalmente, hay casos raros en los que calcular un resultado de doble precisión y luego redondear a precisión simple produce un resultado ligeramente diferente al cálculo de un resultado de precisión simple originalmente, y ningún método para redondear el resultado de precisión doble solucionará esto.


Usa código como este (C):

double x, y; / ... y gets a double value somewhere ... / x = (double)(float)y;

Después de eso, x (doble) tendrá un valor resultante del redondeo de y como flotación de precisión simple.