Notxor tiene un blog

Defenestrando la vida


Utilizar guile como calculadora

Los que me conocen saben que llevo tiempo hablándoles de las maravillas de algunas herramientas como bc, una gran calculadora que he utilizado durante años y que sigo utilizando, aunque cada vez menos. bc se está viendo desplazada en mi línea de comandos como calculadora por guile, pero ¿qué es guile?

guile ¿Eso no es un lenguaje de programación?

Pues sí, guile es un scheme. Su nombre son las siglas de GNU's Ubiquitous Intelligent Language for Extensions. Que como indican es un lenguaje creado para proporcionar extensiones a otros programas y de hecho consiste, principalmente, en una librería pensada para ser ensamblada con cualquier otro programa y ser utilizada para escribir scripts que amplíen la funcionalidad del mismo.

Como he dicho antes, es un scheme, lenguaje derivado de LISP. Iba a decir del antiguo LISP pero es mejor puntualizar a eterno LISP.

Además, para mi propósito de hoy, guile viene con un intérprete y se puede lanzar desde línea de comandos y utilizarlo de forma interactiva.

Calculadora para la línea de comandos

Utilizo en mi ordenador como gestor de ventanas i3vm. Es un buen gestor, muy eficaz, pero para serlo se basa mucho en el uso del teclado minimizando el uso del ratón. Para utilizarlo procuro tener las aplicaciones que más utiliza a un golpe de teclas (o dos, si contamos con la tecla mod). Por ejemplo, una consola la abro pulsando mod+enter.

Por ello, me es mucho más sencillo cuando necesito una calculadora pulsar mod+enter y teclear bc que buscar la calculadora gráfica que haya instalada y manejarla con el ratón. bc además proporciona una calculadora programable muy potente, incluso puedes definir funciones para realizar cálculos complejos como si un lenguaje de programación fuera. Pero ¿por qué estoy sustituyendo bc con guile? Lo mejor para explicarlo es ver un ejemplo:

> bc
bc 1.07.1
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
(2/3)+(1/3)
0
scale=2
(2/3)+(1/3)
.99
scale=5
(2/3)+(1/3)
.99999
quit

El primer resultado de (2/3)+(1/3) es totalmente inexacto. Se va ajustando según modificamos el valor de la variable scale que nos dice qué cantidad de decimales debe calcular. Sin embargo, vemos que son en realidad aproximaciones. Vamos al mismo ejemplo desde guile:

GNU Guile 2.0.14
Copyright (C) 1995-2016 Free Software Foundation, Inc.

Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'.
This program is free software, and you are welcome to redistribute it
under certain conditions; type `,show c' for details.

Enter `,help' for help.
scheme@(guile-user)> (+ (/ 2 3) (/ 1 3))
$1 = 1

Si comparamos las dos formas de cálculo veremos que guile es más preciso, todos sabemos que (2/3)+(1/3) son (3/3) o lo que es lo mismo 1. La primera respuesta de bc es 0 algo inaceptable, pero empieza a acercarse según el valor de la variable scale que determina cuántos decimales se calcularán.

Usando guile como calculadora

Muchas veces descarto temas sobre los que escribir porque me da la sensación de que son tan básicos que todo el mundo los conoce ya, o son tan sencillos que no merece la pena escribir sobre ellos. Luego veo esos mismos temas en otro blog y pienso que quizá podría haberlo escrito yo, porque no era tan básico o tan simple para la mayoría de la gente. Este es uno de esos casos en los que tengo casi descartado el borrador y he pensado al revés: a lo mejor no es tan básico y tan simple o a alguien le puede interesar.

Cualquier lenguaje interpretado se puede utilizar como calculadora. He utilizado también Python alguna vez para lo mismo, aunque generalmente he venido usando más bc como calculadora de consola.

Cálculos sencillos

La peculiaridad de guile, como cualquier otro scheme o descendiente de LISP utiliza una notación rara para la mayoría de los mortales y hay que acostumbrarse a ella. En este tipo de lenguajes todo es una lista y todo se presenta en una lista. El primer elemento de la lista es la función que evaluará el intérprete y los demás elementos son los datos que necesita la función para ser evaluada. Un ejemplo de cálculos sencillos con guile.

scheme@(guile-user)> (+ 2 3)
$1 = 5
scheme@(guile-user)> (- 4 2)
$2 = 2
scheme@(guile-user)> (- $1 $2)
$3 = 3
scheme@(guile-user)> (+ $1 2)
$4 = 7
scheme@(guile-user)> (+ 1 2 3 4)
$5 = 10
scheme@(guile-user)> (- $5 $3 1 1)
$6 = 5

Para realizar el cálculo de (2+3) se utiliza una notación que puede parecer extraña. En realidad es muy sencilla de entender, la expresión (+ 2 3) la podemos desglosar en sus componentes más sencillos. Para empezar está la pareja de (). Esos signos nos delimitan una lista. Como he dicho antes, el intérprete evaluará el primer elemento de la lista, lo que quiere decir que el intérprete espera que sea una expresión «ejecutable». En nuestro caso, hay una función que se llama + que lo que hace al ser evaluada es sumar la lista de argumentos que se le pasen, en este caso 2 y 3.

Pero además, vemos que guile va guardando los resultados en variables que marca con un carácter $ y esas variables se pueden utilizar en los cálculos. Algo muy interesante cuando los cálculos son complejos y los divides en partes o cuando quieres almacenar alguna constante que emplearás en varios cálculos.

scheme@(guile-user)> (/ 21 3)
$3 = 7
scheme@(guile-user)> (/ 21 3 7)
$4 = 1
scheme@(guile-user)> (/ 21 3 7 2)
$5 = 1/2

Otro de los puntos a tener en cuenta es que las divisiones no se efectúan para convertir a decimal sino que las operaciones con enteros que no den otro entero, se guardan como fracciones.

Este hecho es fundamental para mantener la exactitud en los cálculos, no se emplean las aproximaciones decimales de las fracciones. Y por eso vemos que el resultado de la serie de divisiones (/ 21 3 7 2) se realiza de la siguiente manera:

21 / 3 → 7 / 7 → 1 / 2 → 1/2

Cálculos no tan sencillos

Hay algunos otros cálculos que no son operaciones básicas sino cosas más complicadas. Por ejemplo, algunas operaciones especiales sobre la división, como calcular el cociente o el resto.

scheme@(guile-user)> (quotient 7 3)
$1 = 2
scheme@(guile-user)> (modulo 7 3)
$2 = 1
scheme@(guile-user)>

También hay funciones para cálculo de exponentes (exp) o logaritmos (log), o para las funciones trigonométricas sin, cos, tan, asin, acos, atan. Por ejemplo:

scheme@(guile-user)> (* 4 (atan 1))
$3 = 3.141592653589793
scheme@(guile-user)>

Comentarios

Debido a algunos ataques mailintencionados a través de la herramienta de comentarios, se ha decidido activar un filtro antispam y guardar las direcciones IP con el único objeto de añadir a la lista de bloqueos las que correspondan a spam y otras actividades maliciosas.

Disculpen las molestias.