17 de mayo de 2021

Dígitos significativos en Visual FoxPro

Artículo original: Significant digits in Visual FoxPro
http://www.foxpert.com/foxpro/knowlbits/files/knowlbits_201102_1.html
Autor: Christof Wollenhaupt
Traductor: Luis María Guayán

Steve Bodnar hizo una pregunta interesante en Twitter: ¿Por qué obtiene resultados diferentes para las siguientes dos líneas?

? Round(512.9250000000,2) && 512.92
? Round(512.925000000,2) && 512.93

Nuestra educación matemática nos dice que no debería importar con cuántos ceros se rellene el número. El resultado tiene que ser el mismo. Las computadoras comúnmente no comparten la opinión de los usuarios, ni usan la misma base que los humanos. Vivimos en un mundo decimal (a excepción de unas pocas medidas no métricas, algunos países simplemente se niegan a darse por vencidos), las computadoras viven en un mundo binario. Lo que es un número casi perfecto para usar, 512,925, es de hecho 512,924999999999 para la computadora.

Visual FoxPro, como la mayoría de los otros lenguajes, usa números de punto flotante para expresar fracciones. Esos números no tienen una precisión fija, a diferencia de los números decimales que usamos. Trabajar con números de punto flotante de 15 dígitos sería engorroso rápidamente, ni coinciden con lo que usamos en Visual FoxPro en realidad. Nadie quiere una factura con la cantidad indicada hasta el millonésimo de centavo.

Visual FoxPro encontró varias soluciones a lo que es básicamente un problema de presentación. Por un lado, tenemos comandos oscuros que casi nadie puede explicar correctamente, como SET DECIMALS y SET FIXED.

Para simplificar las cosas, hasta el punto de que ya no vemos lo que sucede detrás de escena, Visual FoxPro realiza un seguimiento de la cantidad de dígitos que tiene cada valor flotante. Esta es una información adicional que no forma parte del valor numérico en sí.

512,9250000000 y 512,925000000 no son los mismos valores. Ambos tienen el mismo valor de coma flotante 512,924999999999. El primero tiene una precisión de 13, el segundo tiene una precisión de 12. Con un número como este, es bastante fácil averiguar cuántos lugares significativos tiene el número. Solo cuente sus dígitos. Pero, ¿qué hay de usar este número en cualquier tipo de cálculo? ¿Cómo sabe Visual FoxPro cuántos lugares digitales tendrá el resultado? Cuando se ejecuta el siguiente código:

? 512.925000000 font "Courier new"
? 512.925000000+0 font "Courier new"
? 512.925000000*1 font "Courier new"

Ud. notará que el número sigue siendo el mismo (afortunadamente, de lo contrario tendríamos cosas más serias de las que preocuparnos), sin embargo, sigue desplazándose hacia la derecha. ¿Porque es eso?

Cuando Visual FoxPro imprime un valor en la pantalla, lo hace de acuerdo con la precisión almacenada con el valor. No hay forma de pedir directamente a Visual FoxPro esos valores.

Alguien, probablemente un aprendiz deficiente hace 25 años, especificó para cada operación por cuántos dígitos el resultado podría variar de los valores que participan en la operación. El simple hecho de imprimir el número no tiene ningún efecto, por lo tanto, se imprime alineado con el borde izquierdo. Cuando agrega dos números, nunca puede agregar más de un dígito a la izquierda. 9 + 9 es 18. Por lo tanto, la operación de suma deja espacio para un desbordamiento potencial y agrega un dígito. Visual FoxPro examina ambos lados del separador decimal por separado. Agregar un número 4,1 y 1,4 da como resultado un número 5,4, que es el número máximo de dígitos en cada lado más uno para el desbordamiento. Las multiplicaciones combinan el número de dígitos:

? 1.11*1.1 font "Courier new"
? 1.11*1.10 font "Courier new"
? 01.11*01.10 font "Courier new"

Las multiplicaciones también dejan espacio para el carácter del signo. En la primera línea multiplicamos un valor de 1,2 y 1,1. El resultado tiene un total de 6 dígitos significativos: uno para el signo, dos para los números enteros y tres para la fracción. Al agregar ceros, cambia la precisión de la expresión. Sumar cero a la fracción da como resultado cuatro lugares decimales (2 + 2), pero no mueve el número a la derecha. Sin embargo, agregar ceros al número entero da como resultado que la parte del número entero ahora sea cuatro en lugar de dos dígitos. El número entero se desplaza dos caracteres a la derecha.

Teniendo esto en cuenta, resulta fácil comprender el problema del redondeo. La última pieza que necesita saber, como señaló amablemente Jody Meyer en Twitter, es que Visual FoxPro usa una precisión interna de 15 dígitos. ROUND(), como cualquier otra operación, cambia el número de lugares significativos de su resultado. Si pasa un valor entero, obtiene el mismo valor más dos lugares decimales.

Comencemos con el segundo valor del ejemplo de Steve para mostrar cómo funciona Visual FoxPro. El operando tiene 12 posiciones decimales. ROUND() agregará otros 2. El resultado será un valor de punto flotante con 14 lugares significativos. Cada valor que participa en la operación se redondea a esa precisión. 512,924999999999, el valor almacenado con un máximo de 15 lugares significativos, se redondea a 512,92500000000, un valor con 14 dígitos. Por lo tanto, el resultado de la operación ROUND() es 512,93.

La primera línea, aunque tiene 13 dígitos. Sumar los dos dígitos de las operaciones ROUND() da como resultado un enorme número de 15 dígitos. Esto maximiza el número de dígitos que admite Visual FoxPro. Siguiendo el mismo patrón, el valor de 512,924999999999 se redondea a 15 dígitos. En otras palabras, permanece sin cambios. El tercer lugar decimal es ahora un cuatro en lugar de un cinco. Como resultado, Visual FoxPro redondea hacia abajo a 512,92.


No hay comentarios. :

Publicar un comentario

Los comentarios son moderados, por lo que pueden demorar varias horas para su publicación.