I was asked wheter I know a practical application of the Binomial Theorem in Computer Science. One well known problem in numerical mathematics is the so called ‘cancellaion’ that happens, when two almost equal numbers are subtracted.
In the term \((a-b)^2\) exact this can happen, if \(a\) and \(b\) are almost equal. On the other hand, by applying the Binomial Theorem, the substraction \(a-b\) can be preveted, as \((a-b)^2 = a^2 - 2ab + b^2\). We demonstrate this behavior for various \(a\)s and \(b\)s that are almost equal, i.e., \(b=a-\epsilon\), such that \((a-b)^2=(a-a+\epsilon)^2=\epsilon^2\), and \(a^2-2ab+b^2=a^2-2a(a-\epsilon)+(a-\epsilon)^2\). Forthermore we demonstrate that computing \(a^2-2ab+b^2\) is not allways numerical euqal to \(a^2+b^2-2ab\) in such settings.
## examples with a and b almost equal
## this distroies precision by the term a-b, the so called cancellation
## see https://stat.ethz.ch/Teaching/maechler/R/useR_2018/Maechler_Accuracy.pdf
bs <- function(a, b) a^2 - 2*a*b + b^2
bt <- function(a, b) a^2 + b^2 - 2*a*b
bf <- function(a, b) (a-b)^2
eps <- 1e-1
a <- 1; b <- a - eps
rs <- bs(a,b); rt <- bt(a,b); rf <- bf(a,b)
format(rs, digits=22); format(rt, digits=22); format(rf, digits=22)
## [1] "0.01000000000000000888178"
## [1] "0.01000000000000000888178"
## [1] "0.009999999999999995003996"
rs == rf; rs==rt; rf==rt
## [1] FALSE
## [1] TRUE
## [1] FALSE
rs == eps^2; rf==eps^2; rt==eps^2
## [1] FALSE
## [1] FALSE
## [1] FALSE
a <- 10; b <- a - 1e-1
rs <- bs(a,b); rt <- bt(a,b); rf <- bf(a,b)
format(rs, digits=22); format(rt, digits=22); format(rf, digits=22)
## [1] "0.0100000000000051159077"
## [1] "0.009999999999990905052982"
## [1] "0.009999999999999929084504"
rs == rf; rs==rt; rf==rt
## [1] FALSE
## [1] FALSE
## [1] FALSE
rs == eps^2; rf==eps^2; rt==eps^2
## [1] FALSE
## [1] FALSE
## [1] FALSE
a <- 1e8; b <- a - 1e-1
rs <- bs(a,b); rt <- bt(a,b); rf <- bf(a,b)
format(rs, digits=22); format(rt, digits=22); format(rf, digits=22)
## [1] "2"
## [1] "0"
## [1] "0.009999998807907140019324"
rs == rf; rs==rt; rf==rt
## [1] FALSE
## [1] FALSE
## [1] FALSE
rs == eps^2; rf==eps^2; rt==eps^2
## [1] FALSE
## [1] FALSE
## [1] FALSE
as <- c(1,10,1e5,1e8)
n <- 16
eps <- 10^-(1:n)
wahr <- eps^2
for (a in as) {
m <- data.frame(a=rep(a, n))
m$b <- a - eps
m$d <- bs(m$a, m$b) - bf(m$a, m$b)
m$e <- bs(m$a, m$b) - bt(m$a, m$b)
m$t1 <- bs(m$a, m$b) - wahr
m$t2 <- bf(m$a, m$b) - wahr
m$t3 <- bt(m$a, m$b) - wahr
plot(1:n, m$e, type="b", main=bquote(
"Error of "(a^2 - 2*a*b + b^2) - (a-b)^2*" with "*c(a,b)==c(.(a),.(a)-10^-x)),
axes=FALSE, xlab="x", ylab="Error", ylim=c(min(m[,-c(1,2)]), max(m[,-c(1,2)])))
axis(1, 1:n); axis(2)
#abline(0,0, col="red", lty=2)
lines(1:n, m$d, type="b", col="blue")
lines(1:n, m$t1, type="l", col="green")
lines(1:n, m$t2, type="l", col="orange")
lines(1:n, m$t3, type="l", col="violet")
}
There are a lot of (technical) questions that may be asked to explain the above behavior. But the main point here was to demonstrate that knowledge of the Binomial Thereom can be applied to Computer Science to better understand what is going on in such situations.