When reading about numerical methods, then subtraction cancellation is often a topic.
Simple example of cancellation:
a = 1;
b = 1e-16;
a-(a+b) = 0
hence we loss all information of b.
However, i rarely read about how to check for this problem. Could we not use a simple function to subtract number, which also warns us of problems? Example:
function c = subtract(a,b)
c = a-b;
if abs(c) < 1e-14*a
disp('Warning: Low precision on subtraction');
end
end
There are probably some deficiencies of this simple function - it was just my first idea. Anyway, would something like this work? And why is it not done? (i.e. i have never seen/heard about such checks before).
Related
I'd like to declare first of all, that I'm a mathematician. This might be a stupid stupid question; but I've gone through all the matlab tutorials--they've gotten me nowhere. I imagine I could code this in C (it'd be exhausting); but I need matlab for this particular function. And I don't get exactly how to do it.
Here is the pasted Matlab code of where I'm running into trouble:
function y = TAU(z,n)
y=0;
for i =[1,n]
y(z) = log(beta(z+1,i) + y(z+1)) - beta(z,i);
end
end
(beta is an arbitrary "float" to "float" function with an index i.)
I'm having trouble declaring y as a function, in which we call the function at a different argument. I want to define y_n(z) with something something y_{n-1}(z+1). This is all done in a recursive process to create the function. I really feel like I'm missing something stupid.
As a default function it assigns y to be an array (or whatever you call the default index assignment). But I don't want an array. I want y to be assigned as a "function" class (i.e. takes "float" to "float"). And then I'm defining a sequence of y_n : "float" to "float". So that z to z+1 is a map on "float" to "float".
I don't know if I'm asking too much of matlab...
Help a poor mathematician who hasn't coded since the glory days of X-box mods.
...Please don't tell me I have to go back to Pari-GP/C drawing boards over something so stupid.
Please help!
EDIT: At rahnema1 & mimocha's request, I'll describe the math, and of what I am trying to do with my program. I can't see how to implement latex in here. So I'll write the latex code in a generator and upload a picture. I'm not so sure if there even is a work around to what I want to do.
As to the expected output. We'd want,
beta(z+1,i) + TAU(z+1,i) = exp(beta(z,i) + TAU(z,i+1))
And we want to grow i to a fixed value n. Again, I haven't programmed in forever, so I apologize if I'm speaking a little nonsensically.
EDIT2:
So, as #rahnema1 suggests; I should produce a reproducible example. In order to do this, I'll write the code for my beta function. It's surprisingly simple. This is for the case where the "multiplier" variable is set to log(2); but you don't need to worry about any of that.
function f = beta(z,n)
f=0;
for i = 0:n-1
f = exp(f)/(1+exp(log(2)*(n-i-z)));
end
end
This will work fine for z a float no greater than 4. Once you make z larger it'll start to overflow. So for example, if you put in,
beta(2,100)
1.4242
beta(3,100)
3.3235
beta(3,100) - exp(beta(2,100))/(1/4+1)
0
The significance of the 100, is simply how many iterations we perform; it converges fast so even setting this to 15 or so will still produce the same numerical accuracy. Now, the expected output I want for TAU is pretty straight forward,
TAU(z,1) = log(beta(z+1,1)) - beta(z,1)
TAU(z,2) = log(beta(z+1,2) + TAU(z+1,1)) - beta(z,2)
TAU(z,3) = log(beta(z+1,3) + TAU(z+1,2)) - beta(z,3)
...
TAU(z,n) = log(beta(z+1,n) + TAU(z+1,n-1)) -beta(z,n)
I hope this helps. I feel like there should be an easy way to program this sequence, and I must be missing something obvious; but maybe it's just not possible in Matlab.
At mimocha's suggestion, I'll look into tail-end recursion. I hope to god I don't have to go back to Pari-gp; but it looks like I may have to. Not looking forward to doing a deep dive on that language, lol.
Thanks, again!
Is this what you are looking for?
function out = tau(z,n)
% Ends recursion when n == 1
if n == 1
out = log(beta(z+1,1)) - beta(z,1);
return
end
out = log(beta(z+1,n) + tau(z+1,n-1)) - beta(z,n);
end
function f = beta(z,n)
f = 0;
for i = 0:n-1
f = exp(f) / (1 + exp(log(2)*(n-i-z)));
end
end
This is basically your code from the most recent edit, but I've added a simple catch in the tau function. I tried running your code and noticed that n gets decremented infinitely (no exit condition).
With the modification, the code runs successfully on my laptop for smaller integer values of n, where 1e5 > n >= 1; and for floating values of z, real and complex. So the code will unfortunately break for floating values of n, since I don't know what values to return for, say, tau(1,0) or tau(1,0.9). This should easily be fixable if you know the math though.
However, many of the values I get are NaNs or Infs. So I'm not sure if your original problem was Out of memory error (infinite recursion), or values blowing up to infinity / NaN (numerical stability issue).
Here is a quick 100x100 grid calculation I made with this code.
Then I tested on negative values of z, and found the imaginary part of the output to looks kinda cool.
Not to mention I'm slightly geeking out over the fact that pi is showing up in the imaginary part as well :)
tau(-0.3,2) == -1.45179335740446147085 +3.14159265358979311600i
I have been asked to obtain the first 15 triplets according to this series and this code ought to work. However, it does only produce a table (15*3) filled with zero rather than the 15 Pythagorean triplets? Any help will be welcome.
A = zeros(15, 3);
ii = 1;
for c = 5:120
c2=c^2;
for a=1:c-1
a2=a^2;
for b=a:c-1
if c2-(a2+b^2) == 0
A(ii,1) = a;
A(ii,2) = b;
A(ii,3) = c;
ii=ii+1;
if A(15, 1) ~= 0
flag = 1;
break
end
end
end
if flag == 1
break
end
end
if flag == 1
break
end
end
T1 = array2table(A);
disp(T1)
So, the code generated a correct table on application-restart before failing on all subsequent attempts. And, now I notice that the code runs successfully only for the first time after every relaunch of the application. (Resolved, thanks Dan Pollard.)
Also, interested in knowing if there is any way to not write an upper limit (120) into the code.
I don't think your if statement is ever satisfied. For example, for c=5, you'd expect a=3, b=4 to be a triplet. But you're only letting a and b go up to floor(sqrt(c-1)), which is 2.
Do you mean to let a and b go up to floor(sqrt(c2-1))?
Edit As the question has changed.
When you run the code, Matlab creates all the variables which you assign, and stores them in the workspace. This can be useful, but here it's hurting you as you have the variable flag which is stored as 1. This means that when the code runs, it checks if flag==1 after the first run through b, which it is, so the code ends. Resolve this by placing clear; at the beginning of your script.
There isn't a practical way to remove the upper limit on c. Matlab has the built-in variable Inf but at best Matlab won't let you use it in that context. Realistically you could just replace the 120 with a really large number, but this will take more time and more memory as the number gets bigger. Computers have a finite RAM to store matlab arrays in though, and there are infinitely many pythagorean triples, so doing the calculation without an upper limit will fail in some way.
I am using a while loop with an index t starting from 1 and increasing with each loop.
I'm having problems with this index in the following bit of code within the loop:
dt = 100000^(-1);
t = 1;
equi = false;
while equi==false
***some code that populates the arrays S(t) and I(t)***
t=t+1;
if (t>2/dt)
n = [S(t) I(t)];
np = [S(t-1/dt) I(t-1/dt)];
if sum((n-np).^2)<1e-5
equi=true;
end
end
First, the code in the "if" statement is accessed at t==200000 instead of at t==200001.
Second, the expression S(t-1/dt) results in the error message "Subscript indices must either be real positive integers or logicals", even though (t-1/dt) is whole and equals 1.0000e+005 .
I guess I can solve this using "round", but this worked before and suddenly doesn't work and I'd like to figure out why.
Thanks!
the expression S(t-1/dt) results in the error message "Subscript indices must either be real positive integers or logicals", even though (t-1/dt) is whole and equals 1.0000e+005
Is it really? ;)
mod(200000 - 1/dt, 1)
%ans = 1.455191522836685e-11
Your index is not an integer. This is one of the things to be aware of when working with floating point arithmetic. I suggest reading this excellent resource: "What every computer scientist should know about floating-point Arithmetic".
You can either use round as you did, or store 1/dt as a separate variable (many options exist).
Matlab is lying to you. You're running into floating point inaccuracies and Matlab does not have an honest printing policy. Try printing the numbers with full precision:
dt = 100000^(-1);
t = 200000;
fprintf('2/dt == %.12f\n',2/dt) % 199999.999999999971
fprintf('t - 1/dt == %.12f\n',t - 1/dt) % 100000.000000000015
While powers of 10 are very nice for us to type and read, 1e-5 (your dt) cannot be represented exactly as a floating point number. That's why your resulting calculations aren't coming out as even integers.
The statement
S(t-1/dt)
can be replaced by
S(uint32(t-1/dt))
And similarly for I.
Also you might want to save 1/dt hardcoded as 100000 as suggested above.
I reckon this will improve the comparison.
I have this function
f(a,b) = {
a*a/b if a < b,
b if a >= b
}
defined for values of a and b between 0 and 1 inclusive.
The function is continuous at all valid values of a and b in this range. (Really! try it yourself!) But I'm not sure how to evaluate it in Simulink. The problem is that I can't figure out how to restate it in a way that I could evaluate both "forks" of the function and take the min or max (e.g. min(a*a,b*b)/b) without having a divide-by-zero error at b=0, and I'd like to avoid getting into things like conditionally-executed subsystems.
Does anyone know how I might go about doing this?
You have some strange constraints. Since you insist on evaluating both forks and taking the min of the two, the only solution is to not divide by zero but by a small enough number to avoid an error (eps for instance).
or with if action blocks:
I think the simplest approach would be to use a MATLAB function block. You could code it up like this,
function retVal = myfunc(a, b)
if (a < b)
retVal = a*a/b;
else
retVal = b;
end
end
This will create a block with 2 inputs and one output. I'm not sure how you are ensuring that a,b \in [0,1], but this will work as long as that restriction is satisfied.
I am trying to calculate the profit/loss of a short call at various times in the future, but it isn't coming out correct. Compared to the time of expiration, the ones with time left have less profit above the strike price, but at some point below the strike they don't lose value as fast as the t=0 line. Below is the formula in pseudocode, what am I doing wrong?
profit(stockprice) = -1 * (black_scholes_price_of_call(stockPrice,optionStrike,daysTillExpiration) - premium);
Real matlab code:
function [ x ] = sell_call( current,strike,price,days)
if (days > 0)
Sigma = .25;
Rates = 0.05;
Settle = today;
Maturity = today + days;
RateSpec = intenvset('ValuationDate', Settle, 'StartDates', Settle, 'EndDates',...
Maturity, 'Rates', Rates, 'Compounding', -1);
StockSpec = stockspec(Sigma, current);
x = -1 * (optstockbybls(RateSpec, StockSpec, Settle, Maturity, 'call', strike) - price);
else
x = min(price,strike-current-price);
end
end
Your formula ain't right. I don't know why you need that leading -1 as a multiplier for, because when I distribute it out the "formula" is a simple one:
profit(stockprice) = premium - black_scholes_price_of_call(stockPrice,optionStrike,daysTillExpiration);
Pretty simple. So that means the problem is buried in that function for the price of the call, right?
When I compare your formula to what I see as the definition on Wikipedia, I don't see a correspondence at all. Your MATLAB code doesn't help, either. Dig into the functions and see where you went wrong.
Did you write those? How did you test them before you assembled them into this larger function. Test the smaller blocks before you assemble them into the bigger thing.
What baseline are you testing against? What known situation are you comparing your calculation to? There are lots of B-S calculators available. Maybe you can use one of those.
I'd assume that it's an error in your code rather than MATLAB. Or you've misunderstood the meaning of the parameters you're passing. Look at your stuff more carefully, re-read the documentation for that function, and get a good set of baseline cases.
I found the problem, it had to do with the RateSpec argument. When you pass in a interest rate, it affects the option pricing.