Evaluación de trucos para multiplicaciones aproximadas
En Street Fighting Mathematics (leedlo) hay un capítulo en el que se discuten trucos para realizar mental y aproximadamente operaciones del tipo 3600 × 4.4 × 10^4 × 32.
La recomendación es la siguiente: contar ceros primero, gestionar las cifras significativas después. En el caso anterior, el autor identifica 8 ceros (tres del 3600, cuatro del 10^4 y uno del 32), quedando como cifras significativas 3.6, 4.4 y 3.2.
Para estas últimas, recomienda aproximarlas a 1, pocos (alrededor de 3) y 10. Pocos es una cifra que vale tres y cuyo cuadrado es 10. Por lo tanto, 3.6 × 4.4 × 3.2 es el cubo de pocos, es decir, treinta. De manera que la aproximación de 3600 × 4.4 × 10^4 × 32 es un tres seguido de nueve ceros (en realidad, es un cinco seguido de nueve ceros).
Así que en el ejemplo del libro la cosa, más o menos, funciona. Como no podía ser de otra manera. Pero, ¿y en general?
Lo que podemos hacer es generar muchas secuencias de secuencias de números, aplicar el triquito a cada una de ellas y comparar el producto real con el estimado. Para secuencias de tres números (entre 1 y 10), se obtiene la siguiente distribución del log2 de los cocientes:
Y el código:
simplificar <- function(x){
if (x < 1.7)
return(1L)
if (x < 5)
return(3L)
return(10L)
}
multiplicar <- function(x){
x <- x[x != 1L]
if (length(x) == 0)
return(1)
prod <- 10^(length(x[x == 10L]))
x <- x[x != 10L]
if (length(x) == 0)
return(prod)
x <- length(x)
prod <- prod * 10^(x %/% 2) * 3^(x %% 2)
prod
}
foo <- function(n){
x <- x <- runif(n, min = 1, max = 10)
c(prod(x), multiplicar(sapply(x, simplificar)))
}
res <- t(replicate(10000, foo(3)))
hist(log2(res[,1] / res[,2]), breaks = 50,
freq = FALSE,
col = "steelblue",
main = "log2 del ratio real/estimación)",
xlab = "", ylab = "")
abline(v = -1, col = "red")
abline(v = 1, col = "red")