How to print the calculating method of a function - r

The following problem is given: https://imgur.com/a/2OpPKfW
Write a function polyPrint, which prints the polynomial of Equation (1) in a nice way. For example,
if a corresponds to the vector c(2, 0, 1, -2, 5), then polyPrint(a) is supposed to print:
2 + x^2 + (-2)*x^3 + 5*x^4
Note how polyPrint is supposed to handle the cases where an element of a is either 0, 1 or negative!
At the moment I am using a loop and cat. Thats pretty rough because I need to do a lot of exeptions with ifelse statements for 1,0 and any negative.
Are there any other functions I could be using to streamline this process?
# Regular function
polyFunction <- function(x,a){
n <- seq(1, length(a))
sum(ax^(n-1))
}
# Printing the calculation method
a <- c(2,0,1,-2,5)
polyPrint <- function(a){
n <- seq(1, length(a))
for(i in n){
result <- c()
result <- c(result, cat(a[i],'x^', 1+i, '+ '))
}
}
polyPrint(a)
The expected output is a polynomial function that has this format:
p(x) = a0 + a1x + a2x^2 + ... + anxn
At the moment I am getting 2 *x^ 2 + 0 *x^ 3 + 1 *x^ 4 + -2 *x^ 5 + 5 *x^ 6 +
with the vector c(2, 0, 1, -2, 5)

I think you have an error in the way you are aggregating values and also the way you are taking in considerations special values (0,1, negative values).
Here an example of how you can do that (maybe not the best solution, but it does the job):
polyPrint <- function(a){
formule = NULL
for(i in 1:length(a))
{
if(a[i]==0){}
else{
if(i == 1) {formule = a[i]}
else{
if(a[i]<0){formule = paste0(formule, " + (",a[i],")x^",i)}
else{
if(a[i] == 1){formule = paste0(formule," + x^",i)}
else{formule = paste0(formule, " + ", a[i],"x^",i)}
}
}
}
}
print(formule)
}
And the result for a <- c(2,0,1,-2,5):
> polyPrint(a)
[1] "2 + x^3 + (-2)x^4 + 5x^5"

Related

Continuous function in R Programming

I'm trying to code the following continuous function in R Programming.
I was trying to create a function called fun1 that takes a single argument vecA. I want the function to return the values of f(x) evaluated at the values of vecA.
fun1(vecA) <- function(x){
x^2+2x+3
}
I don't know how I can continue it.
Ideally your function should be able to take vectorized input, in which case you should use ifelse or case_when.
For example:
f <- function(x) {
ifelse(x < 0, x^2 + 2*x + 3,
ifelse(x >= 2, x^2 + 4 * x - 7,
x + 3))
}
Or
f <- function(x) {
dplyr::case_when(x < 0 ~ x^2 + 2*x + 3,
x > 2 ~ x^2 + 4 * x - 7,
TRUE ~ x + 3)
}
both of which produce the same output. We can see what the function looks like by doing:
plot(f, xlim = c(-5, 5))
Created on 2022-09-25 with reprex v2.0.2
Try studying the patterns here:
fun1 <- function(x){
if (x < 0) {
x^2+2*x+3
} else if (x < 2) {
x + 3
} else {
# Your turn
}
}

Beginner in R - Writing loops and functions

I am new to R (I only started learning a few weeks ago) and I need some help with a question on my homework. I have asked my professor several times already and mostly that's resulted in me being more confused.
The question is as follows:
Recall that the Taylor expansion of log(1+x) is:
log(x+1) = sum((-1)^(i+1)*x^i/i)
How many terms do you need to get within 10^(−6) of the correct solution when x = 0.99?
My professor gave me some hints:
n should not be equal to length of x. n should be figured out from the loop. It is the iteration number of the last loop.
the condition of the while loop should depend on the difference between the approximated value and the true value of the function. Not on n any more.
in each iteration, you need to calculate (-1)^(i+1)*x^2/i and add it to the sum of the previous iterations so that you accumulate the sum. Check the example about factorial function in class.
You should include your while loop in a function. The function should have a single argument x.
I'm not asking for anyone to give me the answer, but I would appreciate any help or advice. Thank you!
Below is some code of what I've tried. It is incomplete still and I'm not sure what is missing:
taylorexp <- function(x){
i = 1
approximation = 1
while((log(1+x) - approximation) > 10^(-6)){
z=sum((-1)^(i+1)*x^i/i)
i=i+1
}
return(i)
}
taylorexp(0.99)
Here is an example with repeat
s <- 0
i <- 1
x <- 0.99
repeat{
if (abs(log(1 + x) - s) <= 1e-6) break
s <- s + (-1)**(i + 1) * x**i / i
i <- i + 1
}
or with while
s <- 0
i <- 1
x <- 0.99
while(abs(log(1 + x) - s) > 1e-6) {
s <- s + (-1)**(i + 1) * x**i / i
i <- i + 1
}
and we will get
> i
[1] 661
Update
You can wrap all the required information in a list as the output of function taylorexp, e.g.,
taylorexp <- function(x, tol) {
s <- 0
i <- 1
while (abs(log(1 + x) - s) > tol) {
s <- s + (-1)**(i + 1) * x**i / i
i <- i + 1
}
list(approx = s, err = log(1 + x) - s, n = i)
}
such that
> taylorexp(0.99,1e-6)
$approx
[1] 0.6881336
$err
[1] 9.911419e-07
$n
[1] 661
> taylorexp(0.99,1e-7)
$approx
[1] 0.6881345
$err
[1] 9.966883e-08
$n
[1] 863
Answer Update:
taylor = function(x,n){
out = 0
for(i in 1:n){
out = out + ((-1)^(i+1))*(x^i/i)
}
out
}
true_val = log(1 + 0.99)
true_val
approx_val = taylor(0.99, 10)
approx_val

N+1 loop in R- how to use first loop output in the next iteration of the loop

I want to create what I think is a loop in R, simplifying code that follows this pattern:
n1<-n + 10
n2<-n1 + 10
n3<-n2 + 10
etc...
However I'm not quite sure how to do this- I know it's not a 'for', 'while', or 'repeat' loop as those are based on true/false outputs whereas here I need the loop to run of outputs from earlier iterations of the loop. Then following on from this is it possible to create this simplified loop with a periodic change? e.g.
n1<-n + 10
n2<-n1 + 10
n3<-n2 + 10 +5
n4<-n3 + 10
n5<-n4 + 10
n6<-n5 + 10 +5
etc...
So every third iteration has an additional input. Feel free to redirect me if this has been asked before. I'm not sure the term 'loop' is right for this but I haven't known what else to search.
Any help would be much appreciated!
using purrr and solution #Limey
library(tidyverse)
map_dbl(1:50, ~ .x + 10 + ifelse(.x %% 3 == 0, 5, 0))
From OP's answer to my comment, I think
n <- 0
for (i in 1:50) n <- n + 10 + ifelse(i %% 3 == 0, 5, 0)
n
Giving n = 580, But #Chris deserves the accepted answer as he answered OP's original question in its literal sense.
or, to get a vector:
n <- c(10)
for (i in 2:50) n[i] <- n[i-1] + 10 + ifelse(i %% 3 == 0, 5, 0)
n
Possible answer:
n0 <- 1
for (i in 1:6) {
if (i %% 3 != 0) {
assign(paste0("n", i), get(paste0("n", i-1)) + 10)
} else {
assign(paste0("n", i), get(paste0("n", i-1)) + 10 + 5)
}
}

trying to reverse complicated function in R

myfnS <- function(S,T,pH,D,f,r,I0) {
f1 <- 0.78*sqrt(S/35)*exp(T/26)
f2 <- 42*exp(T/17)
alpha <- 0.106*((f1*f^2)/(f1^2 + f^2))*exp((pH - 8)/0.56) + 0.52*(1 + T/43)*(S/35)*((f2*f^2)/(f2^2 + f^2))*exp(-D/6) + 0.00049*f^2*exp(-(T/27 + D/16))
TLsph <- (20*log(r*1000, base = 10))
I <- I0 - TLsph - ((alpha)*r)
return(I)
}
I'm trying to plug in I, to get a value for r but I'm not sure how to do that.
values for other things remain fixed;
for example for (I=50, S=34, T=10.5, pH-8.1, D=0.0395, f=10.3, I0=192) - how do i find the value of r?
In R there's no way that I know of to run a function in reverse. However, you could use something similar to Newton's method to zero in on a value of r that gives you an I of 50.
First though, the function needs to be cleaned up. Using T as an argument is a problem since that's also short for TRUE, so I changed it to tt. I also added in * operators where implied before.
myfnS <- function(S,tt,pH,D,f,r,I0) {
f1 <- 0.78*sqrt(S/35)*exp(tt/26)
f2 <- 42*exp(tt/17)
alpha <- 0.106*((f1*f^2)/(f1^2 + f^2))*exp((pH - 8)/0.56) +
0.52*(1 + (tt)/43)*(S/35)*((f2*f^2)/(f2^2 + f^2))*exp(-D/6) +
0.00049*f^2*exp(-(tt/27 + D/16))
TLsph <- (20*log(r*1000, base = 10))
I <- I0 - TLsph - ((alpha)*r)
return(I) }
Then a way to iterate through values of r to get closer to an I of 50. As r goes up, I goes down. Once a value for r is found that gets within 1 of 50, r is returned. This threshold can be adjusted to get a more precise guess.
iterateR <- function(I=50, r=1){
if (abs(I - myfnS(r, S=34, tt=10.5, pH=8.1, D=0.0395, f=10.3, I0=192)) < 1) {
return(r)
}
else if(I - myfnS(r, S=34, tt=10.5, pH=8.1, D=0.0395, f=10.3, I0=192) > 1) {
iterateR(r=r-1)
}
else if(I - myfnS(r, S=34, tt=10.5, pH=8.1, D=0.0395, f=10.3, I0=192) < 1) {
iterateR(r=r+1)
}
}
iterateR(I=50, r=1)
#> 47
myfnS(r=47, S=34, tt=10.5, pH=8.1, D=0.0395, f=10.3, I0=192)
#> 50.8514607488626
An r of 47 gives an I of 50.85

Writing the results from a nested loop into another vector in R

I'm pretty new to R, and am struggling a bit with it. I have the following code:
repeat {
if (t > 1000)
break
else {
y1 <- rpois(50, 15)
y2 <- rpois(50, 15)
y <- c(y1, y2)
p_0y <- matrix(nrow = max(y) - min(y), ncol = 1)
i = min(y)
while (i <= max(y)) {
p_0y[i - min(y), ] = (length(which(y1 == i))/50)
i <- i + 1
}
p_y <- matrix(nrow = max(y) - min(y), ncol = 1)
j = min(y)
while (j <= max(y)) {
p_y[j - min(y), ] = (length(which(y == j))/100)
j <- j + 1
}
p_0yx <- p_0y[rowSums(p_0y == 0) == 0]
p_yx <- p_y[rowSums(p_0y == 0) == 0]
g = 0
logvect <- matrix(nrow = (length(p_yx)), ncol = 1)
while (g <= (length(p_yx))) {
logvect[g, ] = (p_0yx[g])/(p_yx[g])
g <- g + 1
}
p_0yx %*% (log2(logvect))
print(p_0yx %*% (log2(logvect)))
t <- t + 1
}
}
i am happy with everything up to the last line, but instead of printing the value of p_0yx%*%(log2(logvect)) to the screen i would like to store this as another vector. any ideas? i have tried doing it a similar way as in the nested loop but doesnt seem to work.
Thanks
The brief answer is to first declare a variable. Put it before everything you've posted here. I'm going to call it temp. It will hold all of the values.
temp <- numeric(1000)
Then, instead of your print line use
temp[t] <- p_0yx %*% log2(logvect)
As an aside, your code is doing some weird things. Look at the first index of p_0y. It is effectively an index to item 0, in that matrix. R starts indexing at 1. When you create the number of rows in that matrix you use max(y) - min(y). If the max is 10 and the min is 1 then there's only 9 rows. I'm betting you really wanted to add one. Also, your code is very un R-like with all of the unnecessary while loops. For example, your whole last loop (and the initialization of logvect) can be replaced with:
logvect = (p_0yx)/(p_yx)
But back to the errors.. and some more Rness... could the following code...
p_0y <- matrix(nrow = max(y) - min(y), ncol = 1)
i = min(y)
while (i <= max(y)) {
p_0y[i - min(y), ] = (length(which(y1 == i))/50)
i <- i + 1
}
maybe be replaced more correctly with?
p_0y <- numeric(max(y) - min(y) + 1)
p_0y[sort(unique(y1)) - min(y1) + 1] = table(y1)/50
p_0y <- matrix(p_0y, ncol = 1)
(similar rethinking of the rest of your code could eliminate the rest of the loops as well)

Resources