miércoles, 5 de septiembre de 2007

Precisión arbitraria en la aritmética REXX

Una de las características de la familia REXX (REXX clásico, Object REXX, NetREXX y otras variaciones) que la diferencia de otros lenguajes de programación más extendidos es su aritmética.

En ella no nos encontramos cosas como los clásicos conceptos de variables numéricas de tipo int, float o double... pero de lo que quisiera hablar hoy es de una característica concreta de la aritmética REXX: la precisión arbitraria.

¿Qué queremos decir con precisión arbitraria?

El siguiente código imprime el resultado del cociente de 1 entre 3:

say 1/3

es decir: 0.333333333. Cualquiera que tenga claras ciertas nociones de matemáticas básicas sabrá que en realidad eso no es 1/3, sino simplemente una aproximación con 9 cifras significativas a 1/3 porque la representación decimal de 1/3 tiene infinitos decimales.

REXX nos da el resultado con 9 cifras significativas porque es el número de cifras con el que trabaja.

Si hacemos lo siguiente:

say 1000000000 + 1

obtendremos 1.00000000E+9. Es decir, que perdemos ese 1 que hemos sumado. Puede que bajo ciertas circunstancias nos interesase ese dígito, pero dado que el lenguaje trabaja con 9 cifras significativas y que ese dígito extra sobrepasa los 9 parece que debamos quedarnos sin el mismo. Y aquí es donde entra en juego el carácter arbitrario de la precisión:

numeric digits 100
say 1000000000 + 1


Con esta sentencia nueva en el código, el resultado se convierte en 1000000001. Y en el caso anterior de 1/3 obtendríamos una ristra de cien cifras significativas (es decir, cien bonitos números 3 uno detrás del otro). La instrucción numeric digits nos permite variar el número de cifras significativas.

Consideremos la clásica función factorial escrita iterativamente:

factorial: procedure
parse arg n
factorial = 1
do i = 1 for n
factorial = factorial * i
end
return factorial


Si ejecutamos:

say factorial(100)

el resultado es 9.33262137E+157. Mientras que si ejecutamos:

numeric digits 1000
say factorial(100)


el resultado es exactamente el factorial de 100:

93326215443944152681
69923885626670049071
59682643816214685929
63895217599993229915
60894146397615651828
62536979208272237582
51185210916864000000
000000000000000000.

Intentad haced esto utilizando exclusivamente la aritmética básica de otro lenguaje de programación y probablemente descubrais que no podeis o es terriblemente más complicado. Esto no significa que REXX sea mejor, simplemente que es diferente.

No hay comentarios: