Implementing error function in Octave - octave

I am a complete beginner at programming and I'm having trouble with implementing the error function for my homework assignment. My erf(x) works fine for values of x from 0 to 2.0 but doesn't work for higher values as it should. The table for the proper values is here.
function y = erf (z)
konst = 2/(pi^0.5);
vsota=0;
n=0;
while n <= 500;
vsota = vsota + ((-1)^n)*(z^(2*n+1))/(factorial(n)*(2*n+1));
n=n+1;
end
y=konst*vsota;
end
Please help me stackoverflow, you're my only hope!

Maybe octave is having trouble evaluating factorial() of large numbers. I got good results using n <= 170 in Python.

Related

evaluating inverse in octave [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I am new to octave. I was asked to write a function [k,y,info]=ivs(a,b,fun,N) which computes the approximated values of the inverse of a given univariate function: fun:[a,b] -- >R; over N equidistant points over the interval [fun(a),fun(b)] (or [fun(b),fun(a)]).
y is the result
k - vector of aprroximated values of inverse function (evaluated over equidistant points)
y - vector of equidistant points
info - 0 if computation ended with success, not 0 otherwise
I wrote some code, it does not work, I get a lot of errors, but I cannot find out from them whats wrong. I expect to be a lot of mistakes in this code. I would like someone to point out whats wrong.
function [k,y,info]=ivs(a,b,fun,N)
if(a-b==0)
error('computation cannot take place, a=b');
else
if(fun(a)=fun(b))
error('we have a problem, interval is zero length')
end
if(fun(a)<fun(b))
x=linspace(fun(a), fun(b), N);
for l in 1:N
[j,FS,info,out]=fzero(#(j) fun(j)-x(l),[f(a),f(b)]);
y(i)=j;
if(info!=1)
error("Something went wrong with fzero()");
end
end
else
x=linspace(fun(b), fun(a), N);
for l in 1:N
[j,FS,info,out]=fzero(#(j) fun(j)-x(l),[f(a),f(b)]);
y(l)=j;
if(info!=1)
warning("Something went wrong with fzero()");
end
end
end
end
end
There are several mistakes in the typing, but also in the logic
you are declaring a k output but never creating it.
fun(a)=fun(b) is an assignment not a test.
for l in 1:N is NOT the correct way for a for.
you are using l for the cycle and than using i to index y.
in calling fzero the interval where to look for the solution is NOT [f(a),f(b)].
Amendig these problems, I guess your function was supposed to be:
function [k,y,info]=ltrigp(a,b,fun,N)
if(a-b==0)
error('computation cannot take place, a=b');
else
if(fun(a)==fun(b))
error('we have a problem, interval is zero length')
end
if(fun(a)<fun(b))
x=linspace(fun(a), fun(b), N);
for l = 1:N
[j,FS,info,out]=fzero(#(j) fun(j)-x(l),[a,b]);
y(l)=j;
k(l)=x(l);
if(info!=1)
error("Something went wrong with fzero()");
end
end
else
x=linspace(fun(b), fun(a), N);
for l = 1:N
[j,FS,info,out]=fzero(#(j) fun(j)-x(l),[a,b]);
y(l)=j;
k(l)=x(l);
if(info!=1)
warning("Something went wrong with fzero()");
end
end
end
end
end
and work like this:
a=1;
b=4;
N=10;
[k,y,info]=ltrigp(a,b,#exp,N)
k =
Columns 1 through 8:
2.7183 8.4827 14.2471 20.0116 25.7760 31.5404 37.3049 43.0693
Columns 9 and 10:
48.8337 54.5982
y =
Columns 1 through 8:
1.0000 2.1380 2.6566 2.9963 3.2494 3.4513 3.6191 3.7628
Columns 9 and 10:
3.8884 4.0000
info = 1

Writing a function m-file in MATLAB

I am a beginner to coding and I need to write a function.m file for use with Newton's Method. I am having trouble defining the function, where r is radius and p is density:
f(theta) = ((r^2)/2)*((2*pi*p)-(theta - sin(theta)*p))
where radius r = 30cm and density p = 0.82 grams per cm^3
So far, I have written:
function y = f1(theta)
r = 0.3;
p = 0.82;
y = (r^2)/2*(2*pi*p - (theta - sin(theta)*p));
Things I am having trouble with:
Problem defining r and p. Getting an error:
Undefined function or variable 'r'
Having trouble plotting the function.
Things I want to do:
Plot the function to see where the roots are.
Be able to evaluate the function for a given theta.
All help is appreciated. Thank you!
i tried your code without changing. i named the M-file as f1 and executed the function in command line it is working.
function y = f1(theta)
r = 0.3;
p = 0.82;
y = (r^2)/2*(2*pi*p - (theta - sin(theta)*p));
i am getting the output as below
f=f1(45)
f =
-1.7618
this tells that there is no problem in your function. see for some other reason. if you could give your whole code it would be better to diagnose.
This could be done using an anonymous function
r=0.3;
p=0.82;
f=#(theta) (r^2)/2*(2*pi*p-theta+p*sin(theta));
then to evaluate the function just use eg: f(1), and to plot it, for example:
angles=0:.01:pi;
plot(angles,f(angles))
If you don't want to use an anonymous function, then use
function funcVal=func(angles)
r=0.3;
p=0.82;
funcVal=(r^2)/2*(2*pi*p-angles+p*sin(angles));
end
and call it by
angles=0:.01:pi;
plot(angles,func(angles))

MATLAB Function Elements Range

Sorry for the noob question, but I am a beginner in MATLAB. I need to do the following task, but am stuck. "Write a function that takes three arguments x, a, b, where x is a matrix, and a and b are scalars. The function returns the number of elements in x that lie in the interval [a, b]." Here is what I have so far.
function y = count(x,a,b);
for value=a:b
length(value)
end
I need to call the function in the command prompt with the following line:
count(randn(20, 20), 0, 5)
However, I'm not getting anything close to the correct answer. Can anyone point me in the right direction? Thank you.
As Jonas suggested nnz and sum are faster options than numel(find(...)), with sum being the fastest, therefore:
function y = count(x,a,b);
y = sum(x(:)>a & x(:)<b);

Call function for all elements in an array

Let's say I have a function, like:
function [result] = Square( x )
result = x * x;
end
And I have an array like the following,
x = 0:0.1:1;
I want to have an y array, which stores the squares of x's using my Square function. Sure, one way would be the following,
y = zeros(1,10);
for i = 1:10
y(i) = Square(x(i));
end
However, I guess there should be a more elegant way of doing it. I tried some of my insights and made some search, however couldn't find any solution. Any suggestions?
For the example you give:
y = x.^2; % or
y = x.*x;
in which .* and .^ are the element-wise versions of * and ^. This is the simplest, fastest way there is.
More general:
y = arrayfun(#Square, x);
which can be elegant, but it's usually pretty slow compared to
y = zeros(size(x));
for ii = 1:numel(x)
y(ii) = Square(x(ii)); end
I'd actually advise to stay away from arrayfun until profiling has showed that it is faster than a plain loop. Which will be seldom, if ever.
In new Matlab versions (R2008 and up), the JIT accelerates loops so effectively that things like arrayfun might actually disappear in a future release.
As an aside: note that I've used ii instead of i as the loop variable. In Matlab, i and j are built-in names for the imaginary unit. If you use it as a variable name, you'll lose some performance due to the necessary name resolution required. Using anything other than i or j will prevent that.
You want arrayfun.
arrayfun(#Square, x)
See help arrayfun
(tested only in GNU Octave, I do not have MATLAB)
Have you considered the element-by-element operator .*?
See the documentation for arithmetic operators.
I am going to assume that you will not be doing something as simple as a square operation and what you are trying to do is not already vectorised in MATLAB.
It is better to call the function once, and do the loop in the function. As the number of elements increase, you will notice significant increase in operation time.
Let our functions be:
function result = getSquare(x)
result = x*x; % I did not use .* on purpose
end
function result = getSquareVec(x)
result = zeros(1,numel(x));
for idx = 1:numel(x)
result(:,idx) = x(idx)*x(idx);
end
end
And let's call them from a script:
y = 1:10000;
tic;
for idx = 1:numel(y)
res = getSquare(y(idx));
end
toc
tic;
res = getSquareVec(y);
toc
I ran the code a couple of times and turns out calling the function only once is at least twice as fast.
Elapsed time is 0.020524 seconds.
Elapsed time is 0.008560 seconds.
Elapsed time is 0.019019 seconds.
Elapsed time is 0.007661 seconds.
Elapsed time is 0.022532 seconds.
Elapsed time is 0.006731 seconds.
Elapsed time is 0.023051 seconds.
Elapsed time is 0.005951 seconds.

MatLab - nargout

I am learning MatLab on my own, and I have this assignment in my book which I don't quite understand. Basically I am writing a function that will calculate sine through the use of Taylor series. My code is as follows so far:
function y = sine_series(x,n);
%SINE_SERIES: computes sin(x) from series expansion
% x may be entered as a vector to allow for multiple calculations simultaneously
if n <= 0
error('Input must be positive')
end
j = length(x);
k = [1:n];
y = ones(j,1);
for i = 1:j
y(i) = sum((-1).^(k-1).*(x(i).^(2*k -1))./(factorial(2*k-1)));
end
The book is now asking me to include an optional output err which will calculate the difference between sin(x) and y. The book hints that I may use nargout to accomplish this, but there are no examples in the book on how to use this, and reading the MatLab help on the subject did not make my any wiser.
If anyone can please help me understand this, I would really appreciate it!
The call to nargout checks for the number of output arguments a function is called with. Depending on the size of nargout you can assign entries to the output argument varargout. For your code this would look like:
function [y varargout]= sine_series(x,n);
%SINE_SERIES: computes sin(x) from series expansion
% x may be entered as a vector to allow for multiple calculations simultaneously
if n <= 0
error('Input must be positive')
end
j = length(x);
k = [1:n];
y = ones(j,1);
for i = 1:j
y(i) = sum((-1).^(k-1).*(x(i).^(2*k -1))./(factorial(2*k-1)));
end
if nargout ==2
varargout{1} = sin(x)'-y;
end
Compare the output of
[y] = sine_series(rand(1,10),3)
and
[y err] = sine_series(rand(1,10),3)
to see the difference.