I am trying to sum the odds numbers of a specific number (but excluding itself), for example: N = 5 then 1 3 = 4
a<-5
sum<-function(x){
k<-0
for (n in x) {
if(n %% 2 == 1)
k<-k 1
}
return(k)
}
sum(a)
# [1] 1
But the function is not working, because it counts the odds numbers instead of summing them.
Thanks in advance.
CodePudding user response:
We may use vectorized approach
a1 <- head(seq_len(a), -1)
sum(a1[a1%%2 == 1])
[1] 4
If we want a loop, perhaps
f1 <- function(x) {
s <- 0
k <- 1
while(k < x) {
if(k %% 2 == 1) {
s <- s k
}
k <- k 1
}
s
}
f1(5)
The issue in OP's code is
for(n in x)
where x
is just a single value and thus n
will be looped once - i.e. if our input is 5, then it will be only looped once and 'n' will be 5. Instead, it would be seq_len(x -1)
. The correct loop would be something like
f2<-function(x){
k<- 0
for (n in seq_len(x-1)) {
if(n %% 2 == 1) {
k <- k n
}
}
k
}
f2(5)
NOTE: sum
is a base R
function. So, it is better to name the custom function with a different name
CodePudding user response:
Mathematically, we can try the following code to calculate the sum
((N-1)/2)^2
CodePudding user response:
We could use logical statement to access the values:
a <- 5
a1 <- head(seq_len(a), -1)
sum(a1[c(TRUE, FALSE)])
output:
[1] 4
CodePudding user response:
Fun benchmarking. Does it surprise that Thomas solution is vastly quicker...?
count_odds_thomas <- function(x){
((x-1)/2)^2
}
count_odds_akrun <- function(x){
a1 <- head(seq_len(x), -1)
sum(a1[a1%%2 == 1])
}
microbenchmark::microbenchmark(
akrun = count_odds_akrun(10^6),
thomas = count_odds_thomas(10^6)
)
#> Unit: nanoseconds
#> expr min lq mean median uq max neval
#> akrun 21829246 25880187 30571479.45 29317004 32566502 82343305 100
#> thomas 616 991 35103.54 6574 8450 2928050 100
Moreover, Thomas solution works on really big numbers... (That's probably a matter of your machine too)
count_odds_thomas(10^10)
#> [1] 2.5e 19
count_odds_akrun(10^10)
#> Error: vector memory exhausted (limit reached?)