how to calculate the Euclidean norm of a vector in R?

后端 未结 10 1083
灰色年华
灰色年华 2021-02-01 13:22

I tried norm, but I think it gives the wrong result. (the norm of c(1, 2, 3) is sqrt(1*1+2*2+3*3), but it returns 6..

10条回答
  •  既然无缘
    2021-02-01 14:05

    I was surprised that nobody had tried profiling the results for the above suggested methods, so I did that. I've used a random uniform function to generate a list and used that for repetition (Just a simple back of the envelop type of benchmark):

    > uut <- lapply(1:100000, function(x) {runif(1000, min=-10^10, max=10^10)})
    > norm_vec <- function(x) sqrt(sum(x^2))
    > norm_vec2 <- function(x){sqrt(crossprod(x))}
    > 
    > system.time(lapply(uut, norm_vec))
       user  system elapsed 
       0.58    0.00    0.58 
    > system.time(lapply(uut, norm_vec2))
       user  system elapsed 
       0.35    0.00    0.34 
    > system.time(lapply(uut, norm, type="2"))
       user  system elapsed 
       6.75    0.00    6.78 
    > system.time(lapply(lapply(uut, as.matrix), norm))
       user  system elapsed 
       2.70    0.00    2.73 
    

    It seems that taking the power and then sqrt manually is faster than the builtin norm for real values vectors at least. This is probably because norm internally does an SVD:

    > norm
    function (x, type = c("O", "I", "F", "M", "2")) 
    {
        if (identical("2", type)) {
            svd(x, nu = 0L, nv = 0L)$d[1L]
        }
        else .Internal(La_dlange(x, type))
    }
    

    and the SVD function internally converts the vector into a matrix, and does more complicated stuff:

    > svd
    function (x, nu = min(n, p), nv = min(n, p), LINPACK = FALSE) 
    {
        x <- as.matrix(x)
        ...
    

    EDIT (20 Oct 2019):

    There have been some comments to point out the correctness issue which the above test case doesn't bring out:

    > norm_vec(c(10^155))
    [1] Inf
    > norm(c(10^155), type="2")
    [1] 1e+155
    

    This happens because large numbers are considered as infinity in R:

    > 10^309
    [1] Inf
    

    So, it looks like:

    It seems that taking the power and then sqrt manually is faster than the builtin norm for real values vectors for small numbers.

    How small? So that the sum of squares doesn't overflow.

提交回复
热议问题