Ch2.2.2 Floating Point Numbers, Part 2

Floating Point & Numerical Processor

  • Storing numbers in double precision has advantages for numerical processor handling numbers.

title

  • The basics:
  • Numbers and arithmetic

title

Example 1: Addition

  • For addition or subtraction, both numbers should be in a common exponent.
  • One can be converted to the other by changing the mantissa.
  • After this conversion, the numbers are added or subtracted, then the result stored as a new floating point number.
200 + 2000 = 2.0*10^2 + 2.0*10^3
           = 2.0*10^2 + 20*10^2 
           = 22*10^2
           = 2.2*10^3

Example 1: Multiplication

  • For multiplication and division, no need to change exponent.
  • To multiply two numbers, the mantissae are multiplied and exponents are added.
200 * 2000 = (2.0*10^2)*(2.0*10^3)
           = (2.0*2.0)*(10^2*10^5) 
           = 4.0*10^5

\[ \begin{align*} (200)(2000) & = (2.0 \times 10^2 ) (2.0 \times 10^3 ) \\ & =(2.0*2.0) \times (10^2*10^3) \\ & = 4.0 \times 10^{5} \end{align*} \]

Example 1: Division

  • For multiplication and division, no need to change exponent.
  • For division, divide mantissae & subtract exponents.
200 / 2000 = (2.0*10^2)/(2.0*10^3)
           = (2.0/2.0)*(10^2/10^3) 
           = 1.0*10^(-1)

\[ \begin{align*} \frac{200}{2000} & = \frac{2.0 \times 10^2}{2.0 \times 10^3}\\ & = \left( \frac{2.0}{2.0} \right) \times \left(\frac{10^2}{10^3} \right) \\ & = 1 \times 10^{-1} \end{align*} \]

Example 2: Addition

  • Show computer arithmetic steps
50 + 500  = 
          =
          =
          =
  • From Example 1:
200 + 2000 = 2.0*10^2 + 2.0*10^3
           = 2.0*10^2 + 20*10^2 
           = 22*10^2
           = 2.2*10^3

Example 2: Addition

  • Show computer arithmetic steps
50 + 500   = 5.0*10^1 + 5.0*10^2
           = 5.0*10^1 + 50*10^1 
           = 55*10^1
           = 5.5*10^2

Example 2: Multiplication

  • Show computer arithmetic steps
50 * 500  = 
          =
          =
          =
  • From Example 1:
200 * 2000 = (2.0*10^2)*(2.0*10^3)
           = (2.0*2.0)*(10^2*10^5) 
           = 4.0*10^5

Example 2: Multiplication

  • Show computer arithmetic steps
50 * 500   = 5.0*10^1 * 5.0*10^2
           = (5.0*5.0)*(10^1*10^2) 
           = 25.0*10^3
           = 2.5*10^4

Example 2: Division

  • Show computer arithmetic steps
50 / 500  = 
          =
          =
  • From Example 1:
200 / 2000 = (2.0*10^2)/(2.0*10^3)
           = (2.0/2.0)*(10^2/10^3) 
           = 1.0*10^(-1)

Example 2: Division

  • Show computer arithmetic steps
50 / 500 = (5.0*10^1)/(5.0*10^2)
           = (5.0/5.0)*(10^1/10^2) 
           = 1.0*10^(-1)

Floating Point Special Values

  • Floating point numbers permit several special values to be stored.
  • The most important of these is NaN, or “not a number.”
0/0
[1] NaN
sqrt(-1)
[1] NaN

Floating Point NaN

  • Once introduced into into an expression, NaN will generally propagate through entire expression:
(x <- 0/0)
[1] NaN
sqrt(5) + cos(x) 
[1] NaN

Floating Point NaN

NaN+5 
[1] NaN
NaN*5
[1] NaN
NaN/5
[1] NaN

Floating Point NaN

NaN/NaN
[1] NaN
NaN^2
[1] NaN
NaN^0
[1] 1

Floating Point NaN

(x <- 0/0)
[1] NaN
is.nan(x)
[1] TRUE
is.nan(2)
[1] FALSE

NaN and NA

  • NaN is not equal to itself:
NaN == NaN
[1] NA
  • NA is different from NaN in that NA is not a part of the IEEE standard for floating point numbers.
  • NA is a construction of R used to represent a value that is not known, as a placeholder.
  • NA says no result was available or the result is missing.

NA

  • NA can be used to fill in a value that is missing.
x <- c(3,1,4,NA,5,9)
x[2:4]
[1]  1  4 NA
x > 3
[1] FALSE FALSE  TRUE    NA  TRUE  TRUE

Inf

  • The value of infinity is the result of a couple of operations, including exceeding basic storage requirements.
  • Within most algebraic frameworks, division by 0 yields an undefined result, but not with R.
1/0
[1] Inf
1/Inf
[1] 0

Inf

  • Infinity is also the next larger number than the maximum value of stored double precision number.
  • For instance, if you double the value of .Machine$double.xmax, the number returned is Inf:
.Machine$double.xmax
[1] 1.797693e+308
2*(.Machine$double.xmax)
[1] Inf

NaN and Inf

1 / 0
[1] Inf
Inf - Inf
[1] NaN
Inf + Inf
[1] Inf

NaN and Inf

-1 / 0
[1] -Inf
Inf * Inf
[1] Inf
Inf/Inf
[1] NaN

Inf

1/Inf
[1] 0
1+1/Inf
[1] 1
(1+1/Inf)^Inf
[1] 1

Inf

(1+1/Inf)^Inf
[1] 1
n <- seq(1,100,by = 20)
(1+1/n)^n
[1] 2.000000 2.656263 2.685856 2.696330 2.701690

Plot 1

n <- seq(1,100,by = 20)
(y <- (1+1/n)^n)
[1] 2.000000 2.656263 2.685856 2.696330 2.701690
plot(n,y)

plot of chunk unnamed-chunk-28

Plot 2

n <- seq(1,100,by = 20)
(y <- (1+1/n)^n)
[1] 2.000000 2.656263 2.685856 2.696330 2.701690
plot(n,y, type = "b", pch = 10, frame = FALSE, 
     col = "blue", xlab = "n", ylab = "y", 
     lty = 2, lwd = 2)

plot of chunk unnamed-chunk-31

Negative 0

  • The double precision data type has a signed zero, or \( \pm 0 \).
  • The negative sign tends to propagate as expected:
3/(-0)
[1] -Inf
  • Otherwise it acts like 0:
3*(-0)
[1] 0

Special Values Conclusion

  • These special values give the floating point system a way to handle exceptional conditions.
  • In some other environments, division by zero automatically terminates the program.
  • By returning a Inf or NaN, floating point allows computation to continue while indicating something has gone wrong.
1/0
[1] Inf