I have wrote a code to find roots using the false position method. It gives the correct answer but it always takes the maximum number of iterations possible. I noticed that my upper bound is never being changed, meaning my error will always remain high. Any ideas why?
fprintf('Be sure to mark all multiplication with a *\n\n\n');
str=input('Give an equation in x with right hand side=0: ', 's');
%User types in their equation
f=inline(str);
%Converts from string to function
xl=input('Choose the lower bound for the guess interval: ');
xh=input('Choose the upper bound for the guess interval: ');
%Input the upper and lower bounds to initial guess
while(f(xl)*f(xh)) > 0
fprintf('There is no root in this interval\n')
%Prompt user the interval is incorrect
xl=input('Choose the lower bound for the guess interval: ');
xh=input('Choose the upper bound for the guess interval: ');
%Input a new upper and lower bound for the initial guess
endwhile
if f(xl) == 0
fprintf('There is a root at the lower bound\n')
%Inform the user their lower bound is located on a root
elseif f(xh) == 0
fprintf('There is a root at the upper bound\n')
%Inform the user their upper bound is located on a root
endif
tol=input('What would you like your lowest error to be: ');
%User inputs their desired error value
for i=1:1000 %Limit total iterations to 1000
xm=((xl*f(xh)-xh*f(xl))/(f(xh)-f(xl))) %Define center value based on method
if f(xl)*f(xm) < 0
xh=xm
else
xl=xm
endif
%Check which half the root is located in
if abs((xh-xl)/2) < tol
break
endif
%Stop loop once error is acceptable
endfor
fprintf('The root: %f\nThe number of iterations: %d\n',xl,i);
%Display the root and number of iterations
Related
I'm currently learning about recursion, it's pretty hard to understand. I found a very common example for it:
function factorial(N)
local Value
if N == 0 then
Value = 1
else
Value = N * factorial(N - 1)
end
return Value
end
print(factorial(3))
N == 0 is the base case. But when i changed it into N == 1, the result is still remains the same. (it will print 6).
Is using the base case important? (will it break or something?)
What's the difference between using N == 0 (base case) and N == 1?
That's just a coincidence, since 1 * 1 = 1, so it ends up working either way.
But consider the edge-case where N = 0, if you check for N == 1, then you'd go into the else branch and calculate 0 * factorial(-1), which would lead to an endless loop.
The same would happen in both cases if you just called factorial(-1) directly, which is why you should either check for > 0 instead (effectively treating every negative value as 0 and returning 1, or add another if condition and raise an error when N is negative.
EDIT: As pointed out in another answer, your implementation is not tail-recursive, meaning it accumulates memory for every recursive functioncall until it finishes or runs out of memory.
You can make the function tail-recursive, which allows Lua to treat it pretty much like a normal loop that could run as long as it takes to calculate its result:
local function factorial(n, acc)
acc = acc or 1
if n <= 0 then
return acc
else
return factorial(n-1, acc*n)
end
return Value
end
print(factorial(3))
Note though, that in the case of factorial, it would take you way longer to run out of stack memory than to overflow Luas number data type at around 21!, so making it tail-recursive is really just a matter of training yourself to write better code.
As the above answer and comments have pointed out, it is essential to have a base-case in a recursive function; otherwise, one ends up with an infinite loop.
Also, in the case of your factorial function, it is probably more efficient to use a helper function to perform the recursion, so as to take advantage of Lua's tail-call optimizations. Since Lua conveniently allows for local functions, you can define a helper within the scope of your factorial function.
Note that this example is not meant to handle the factorials of negative numbers.
-- Requires: n is an integer greater than or equal to 0.
-- Effects : returns the factorial of n.
function fact(n)
-- Local function that will actually perform the recursion.
local function fact_helper(n, i)
-- This is the base case.
if (i == 1) then
return n
end
-- Take advantage of tail calls.
return fact_helper(n * i, i - 1)
end
-- Check for edge cases, such as fact(0) and fact(1).
if ((n == 0) or (n == 1)) then
return 1
end
return fact_helper(n, n - 1)
end
I created a function in Octave for which I, at this moment, only want one of the possible outputs displayed. The code:
function [pi, time, numiter] = PageRank(pi0,H,v,n,alpha,epsilon);
rowsumvector=ones(1,n)*H';
nonzerorows=find(rowsumvector);
zerorows=setdiff(1:n,nonzerorows); l=length(zerorows);
a=sparse(zerorows,ones(l,1),ones(l,1),n,1);
k=0;
residual=1;
pi=pi0;
tic;
while (residual >= epsilon)
prevpi=pi;
k=k+1;
pi=alpha*pi*H + (alpha*(pi*a)+1-alpha)*v;
residual = norm(pi-prevpi,1);
end
pi;
numiter=k
time=toc;
endfunction
Now I only want numiter returned, but it keeps giving me back pi as well, no matter whether I delete pi;, or not.
It returns it in the following format:
>> PageRank(pi0,H,v,length(H),0.9,epsilon)
numiter = 32
ans =
0.026867 0.157753 0.026867 0.133573 0.315385
To me it seems strange that the pi is not given with its variable, but merely as an ans.
Any suggestions?
I know the Octave documentation for this is not very extensive, but perhaps it gives enough hints to understand that how you think about output variables is wrong.
The call
PageRank(pi0,H,v,length(H),0.9,epsilon)
returns a single output argument, it is equivalent to
ans = PageRank(pi0,H,v,length(H),0.9,epsilon)
ans is always the implied output argument if none is explicitly given. ans will be assigned the value of pi, the first output argument of your function. The variable pi (nor time, nor numiter) in your workspace will be modified or assigned to. These are the names of local variables inside your function.
To obtain other output variables, do this:
[out1,out2,out3] = PageRank(pi0,H,v,length(H),0.9,epsilon)
Now, the variable out1 will be assigned the value that pi had inside your function. out2 will contain the value of time, and out3 the value of numiter,
If you don't want the first two output arguments, and only want the third one, do this:
[~,~,out3] = PageRank(pi0,H,v,length(H),0.9,epsilon)
The ~ indicates to Octave that you want to ignore that output argument.
I have the following code in Octave for implementing the composite trapezoid rule and for some reason the function only stalls whenever I execute it in Octave on f = #(x) x^2, a = 0, b = 4, TOL = 10^-6. Whenever I call trapezoid(f, a, b, TOL), nothing happens and I have to exit the Terminal in order to do anything else in Octave. Here is the code:
% INPUTS
%
% f : a function
% a : starting point
% b : endpoint
% TOL : tolerance
function root = trapezoid(f, a, b, TOL)
disp('test');
max_iterations = 10000;
disp(max_iterations);
count = 1;
disp(count);
initial = (b-a)*(f(b) + f(a))/2;
while count < max_iterations
disp(initial);
trap_0 = initial;
trap_1 = 0;
trap_1_midpoints = a:(0.5^count):b;
for i = 1:(length(trap_1_midpoints)-1)
trap_1 = trap_1 + (trap_1_midpoints(i+1) - trap_1_midpoints(i))*(f(trap_1_midpoints(i+1) + f(trap_1_midpoints(i))))/2;
endfor
if abs(trap_0 - trap_1) < TOL
root = trap_1;
return;
endif
intial = trap_1;
count = count + 1;
disp(count);
endwhile
disp(['Process ended after ' num2str(max_iterations), ' iterations.']);
I have tried your function in Matlab.
Your code is not stalling. It is rather that the size of trap_1_midpoints increases exponentionaly. With that the computation time of trap_1 increases also exponentionaly. This is what you experience as stalling.
I also found a possible bug in your code. I guess the line after the if clause should be initial = trap_1. Check the missing 'i'.
With that, your code still takes forever, but if you increase the tolerance (e.g. to a value of 1) your code return.
You could try to vectorize the for loop for speed up.
Edit: I think inside your for loop, a ) is missing after f(trap_1_midpoints(i+1).
After count=52 or so, the arithmetic sequence trap_1_midpoints is no longer representable in any meaningful fashion in floating point numbers. After count=1075 or similar, the step size is no longer representable as a positive floating point double number. That all is to say, the bound max_iterations = 10000 is ludicrous. As explained below, all computations after count=20 are meaningless.
The theoretical error for stepsize h is O(T·h^2). There is a numerical error accumulation in the summation of O(T/h) numbers that is of that size, i.e., O(mu/h) with mu=1ulp=2^(-52). Which in total means that the lowest error of the numerical integration can be expected around h=mu^(1/3), for double numbers thus h=1e-5 or in the algorithm count=17. This may vary with interval length and how smooth or wavy the function is.
One can expect the behavior that the error divides by four while halving the step size only for step sizes above this boundary 1e-5. This also means that abs(trap_0 - trap_1) is a reliable measure for the error of trap_0 (and abs(trap_0 - trap_1)/3 for trap_1) only inside this range of step sizes.
The error bound TOL=1e-6 should be met for about h=1e-3, which corresponds to count=10. If the recursion does not stop for count = 14 (which should give an error smaller than 1e-8) then the method is not accurately implemented.
I've got a little function that displays a formatted amount of some number value. The intention is to show a "commonsense" amount of significant figures depending on the size of the number. So for instance, 1,234 comes out as 1.2k while 12,345 comes out as 12k and 123,456 comes out as 123k.
So in other words, I want to show a single decimal when on the lower end of a given order of magnitude, but not for larger values where it would just be useless noise.
I need this function to scale all the way from 1 to a few billion. The current solution is just to branch it:
-- given `current`
local text = (
current > 9,999,999,999 and ('%dB') :format(current/1,000,000,000) or
current > 999,999,999 and ('%.1fB'):format(current/1,000,000,000) or
current > 9,999,999 and ('%dM') :format(current/1,000,000) or
current > 999,999 and ('%.1fM'):format(current/1,000,000) or
current > 9,999 and ('%dk') :format(current/1,000) or
current > 999 and ('%.1fk'):format(current/1,000) or
('%d'):format(current) -- show values < 1000 floored
)
textobject:SetText(text)
-- code formatted for readability
Which I feel is very ugly. Is there some elegant formula for rounding numbers in this fashion without just adding another (two) clauses for every factor of 1000 larger I need to support?
I didn't realize how simple this actually was until a friend gave me a solution (which checked the magnitude of the number based on its length). I converted that to use log to find the magnitude, and now have an elegant working answer:
local suf = {'k','M','B','T'}
local function clean_format(val)
if val == 0 then return '0' end -- *Edit*: Fix an error caused by attempting to get log10(0)
local m = math.min(#suf,math.floor(math.log10(val)/3)) -- find the magnitude, or use the max magnitude we 'understand'
local n = val / 1000 ^ m -- calculate the displayed value
local fmt = (m == 0 or n >= 10) and '%d%s' or '%.1f%s' -- and choose whether to apply a decimal place based on its size and magnitude
return fmt:format(n,suf[m] or '')
end
Scaling it up to support a greater factor of 1000 is as easy as putting the next entry in the suf array.
Note: for language-agnostic purposes, Lua arrays are 1-based, not zero based. The above solution would present an off-by-one error in many other languages.
Put your ranges and their suffixes inside a table.
local multipliers = {
{10^10, 'B', 10^9},
{10^9, 'B', 10^9, true},
{10^7, 'M', 10^6},
{10^6, 'M', 10^6, true},
{10^4, 'k', 10^3},
{10^3, 'k', 10^3, true},
{1, '', 1},
}
The optional true value at the 4th position of alternate variables is for the %.1f placeholder. The third index is for the divisor.
Now, iterate over this table (using ipairs) and format accordingly:
function MyFormatter( current )
for i, t in ipairs( multipliers ) do
if current >= t[1] then
local sHold = (t[4] and "%.1f" or "%d")..t[2]
return sHold:format( current/t[3] )
end
end
end
I am a newbie to Matlab/programming in general. I wish to write a program/script that uses recursive binary search to approximate the root of $2x - 3sin(x)+5=0$, such that the iteration terminates once the truncation error is definitely $< 0.5 \times 10 ^{-5}$ and print out the number of iterations as well as the estimate of the root.
Here is my attempt that seems to have broken my computer...
%Approximating the root of f(x) = 2*x - 3*sin(x) + 5 by binary search
%Define variables
low = input('Enter lower bound of range: ');
high = input('Enter upper bound of range: ');
mid = (low + high)/2;
%Define f_low & f_high
f_low = 2*low - 3*sin(low) + 5;
f_high = 2*high - 3*sin(high) + 5;
f_mid = 2*mid - 3*sin(mid) + 5;
%Check that the entered range contains the key
while (f_low * f_high) > 0 || low > high
disp('Invalid range')
low = input('Enter lower bound of range: ');
high = input('Enter upper bound of range: ');
end
%The new range
while abs(f_mid) > 0.5*10^(-5)
if f_mid < 0
low = mid;
elseif f_mid > 0
high = mid;
end
end
fprintf('mid = %.4f \n', mid)
I haven't even added in the number-of-iterations counting bit (which I am not quite sure how to do) and already I am stuck.
Thanks for any help.
Once you set high=mid or low=mid, is mid and f_mid recalculated? It looks like you will fail if f_low>0 and f_high<0. This is a valid condition, but you are choosing the wrong one to reset in this case. Also, your termination check is on the function value, not the difference between low and high. This may be what you want, or maybe you want to check both ways. For very flat functions you may not be able to get the function value that small.
You don't need f_mid, and is in fact misleading you. You just need to calculate the value at each step, and see which direction to go.
Plus, you are just changing low and high, but you do not evaluate again f_low or f_high. Matlab is not an algebra system (there are modules for symbolic computation, but that's a different story), so you did not define f_low and f_high to change with the change of low and high: you have to reevaluate them in your final loop.