sessionInfo()
## R version 4.1.1 (2021-08-10)
## Platform: aarch64-apple-darwin20 (64-bit)
## Running under: macOS Big Sur 11.5.2
##
## Matrix products: default
## BLAS: /Library/Frameworks/R.framework/Versions/4.1-arm64/Resources/lib/libRblas.0.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/4.1-arm64/Resources/lib/libRlapack.dylib
##
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## loaded via a namespace (and not attached):
## [1] digest_0.6.27 R6_2.5.0 jsonlite_1.7.2 magrittr_2.0.1
## [5] evaluate_0.14 rlang_0.4.11 stringi_1.7.3 jquerylib_0.1.4
## [9] bslib_0.2.5.1 rmarkdown_2.10 tools_4.1.1 stringr_1.4.0
## [13] xfun_0.25 yaml_2.2.1 compiler_4.1.1 htmltools_0.5.1.1
## [17] knitr_1.33 sass_0.4.0
Question 1 What type do the above vectors hold?
a <- c(1L, "This is a character")
str(a)
## chr [1:2] "1" "This is a character"
b <- c(TRUE, "Hello World")
str(b)
## chr [1:2] "TRUE" "Hello World"
c <- c(FALSE, 2) # what is wrong here?
str(c)
## num [1:2] 0 2
In R, integers are specified by the suffix L
(e.g. 1L
is an integer 1). All other numbers are of class numeric
. Note the function is.integer
does not test whether a given variable has an integer value, but whether it belongs to the class integer.
So that integer or logical elements are coerced into characters to make a
and b
to be atomic vectors of characters.
2
here generates a numeric (double) instead of integer (without the suffix L
). Logical element is coerced to numeric and c
is an atomic vector of numeric.
# using the same objects a, b, c from the above question
a.logical <- as.logical(a)
a.integer <- as.integer(a)
## Warning: NAs introduced by coercion
a.numeric <- as.numeric(a)
## Warning: NAs introduced by coercion
b.logical <- as.logical(b)
b.integer <- as.integer(b)
## Warning: NAs introduced by coercion
b.numeric <- as.numeric(b)
## Warning: NAs introduced by coercion
c.logical <- as.logical(c)
c.integer <- as.integer(c)
c.numeric <- as.numeric(c)
c.character <- as.character(c)
d <- -5:5
d.logical <- as.logical(d)
Question 2 What do you get after the coercions? Does any one suprise you? Can you figure out why?
Vectors a
, b
, and c
already went through coercions before we explicitly coerce them. Therefore, when we explicitly coerce them, a
and b
are character vectors and c
is numeric vector.
Some surprises:
Although as.logical(1L) = TRUE
. as.logical("1") = FALSE
.
Only 0L
and 0
are coerced into FALSE
by as.logical()
. All others are coerced to TRUE
.
a
## [1] "1" "This is a character"
str(a.logical)
## logi [1:2] NA NA
str(a.integer)
## int [1:2] 1 NA
str(a.numeric)
## num [1:2] 1 NA
b
## [1] "TRUE" "Hello World"
str(b.logical)
## logi [1:2] TRUE NA
str(b.integer)
## int [1:2] NA NA
str(b.numeric)
## num [1:2] NA NA
c
## [1] 0 2
str(c.logical)
## logi [1:2] FALSE TRUE
str(c.integer)
## int [1:2] 0 2
str(c.numeric)
## num [1:2] 0 2
Question 3 Explain what you found.
First let’s create a vector \(\mathbf{v} = (969, 971, 972, \dots, 1022, 1023)\) of 54 elements
# finish the code below
v <- c(969, 971:1023)
# or
v <- 969:1023
v <- v[-2]
length(v)
## [1] 54
Then, let’s compute the sum \(\sum_{i=1}^{54}2^{v_i}\).
# finish the code below
v.power.sum <- sum(2^v)
v.power.sum
## [1] 1.797693e+308
well, the above sum returned Inf
as of last year. Clearly, some update of R has pushed this limit.
Let’s take a look over \(\mathbf{w} = (968, 969, 971, 972, \dots, 1022, 1023)\)
w <- c(968:969, 971:1023)
w
## [1] 968 969 971 972 973 974 975 976 977 978 979 980 981 982 983
## [16] 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998
## [31] 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013
## [46] 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
(w.power.sum <- sum(2^w))
## [1] Inf
How about only sum over 53 elements \(\sum_{i=2}^{54}2^{v_i}\) (note that the sum starts from \(v_2\)).
# finish the code below
v.power.sum.53 <- sum(2^v[-1])
v.power.sum.53
## [1] 1.797693e+308
How about only sum over 54 elements \[\sum_{i=2}^{55}2^{w_i}\]
w.power.sum.54 <- sum(2^w[-1])
w.power.sum.54
## [1] 1.797693e+308
Now let’s try putting the first element back
v.power.sum.second <- 2^v[1] + sum(2^v[-1])
v.power.sum.second
## [1] 1.797693e+308
and for w too.
w.power.sum.second <- 2^w[1] + sum(2^w[-1])
w.power.sum.second
## [1] 1.797693e+308
Reference - this should be the bigget number
biggest <- .Machine$double.xmax
biggest
## [1] 1.797693e+308
Findings:
The sum \(\sum_{i=1}^{55}2^{w_i}\) creates an overflow error for double
\(\sum_{i=2}^{55}2^{w_i}\) does not create overflow error
2^w[1] + sum(2^w[-1])
actually equals sum(2^w[-1])
. This is because adding two numbers of dramatically different magnitudes, we get a + b = b
! It is referred to as Catastrophic cancellation caused by the finite-precision arithmetic. You can read more here.