Matlab not accepting whole number as index - matlab

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.

Related

Matrix Multiplication Simplification not giving same results in code

I want to evaluate the expression xTAx -2yTAx+yTAy in Matlab.
If my calculations are correct, this should be equivalent to solving(x-y)TA(x-y)
My main problem right now is that I am not getting the same results from the above two expressions. I'm wondering if it's a precision error or a conceptual error.
I tried a very simple example with some random values to check my math was right. The mini example I used is as follows
A = [1,2,0;2,1,2;0,2,1];
x = [1;2;3];
y = [4;4;4];
(transpose(x)*A*x)-(2*transpose(y)*A*x)+(transpose(y)*A*(y))
transpose(x-y)*A*(x-y)
Both give 46.
I then tried a more realistic example of values for what I'm doing and it failed. For example
A = [2.66666666666667,-0.333333333333333,0,-0.333333333333333,-0.333333333333333,0,0,0,0;
-0.333333333333333,2.66666666666667,-0.333333333333333,-0.333333333333333,-0.333333333333333,-0.333333333333333,0,0,0;
0,-0.333333333333333,2.66666666666667,0,-0.333333333333333,-0.333333333333333,0,0,0;
-0.333333333333333,-0.333333333333333,0,2.66666666666667,-0.333333333333333,0,-0.333333333333333,-0.333333333333333,0;
-0.333333333333333,-0.333333333333333,-0.333333333333333,-0.333333333333333,2.66666666666667,-0.333333333333333,-0.333333333333333,-0.333333333333333 -0.333333333333333;
0,-0.333333333333333,-0.333333333333333,0,-0.333333333333333,2.66666666666667,0,-0.333333333333333,-0.333333333333333;
0,0,0,-0.333333333333333,-0.333333333333333,0,2.66666666666667,-0.333333333333333,0;
0,0,0,-0.333333333333333,-0.333333333333333,-0.333333333333333,-0.333333333333333,2.66666666666667,-0.333333333333333;
0,0,0,0,-0.333333333333333,-0.333333333333333,0,-0.333333333333333,2.66666666666667];
x =[1.21585420370805;
1.00388159497757e-16;
-0.405284734569351;
1.36809776609658e-16;
-1.04796659533634e-17;
-7.52459042423650e-17;
-0.607927101854027;
-8.49163704356314e-17;
0.303963550927013];
v =[0.0319067068305797,0.00786616506360615,0.0709811622828447,0.0719615328671117;
1.26150800194897e-17,5.77584497721720e-18,7.89740111567879e-18,7.14396333930938e-18;
-0.158358815125228,-0.876275686098803,0.0539216716399594,0.0450616819309899;
7.90937837037453e-18,3.24196519177793e-18,3.99402664932776e-18,4.17486202509670e-18;
5.35533279761622e-18,-8.91723780863019e-19,-1.56128480212603e-18,1.84423677629470e-19;
-2.18478057810330e-17,-6.63779320738873e-18,-3.21099714760257e-18,-3.93612240449303e-18;
-0.0213963226092681,-0.0168256143048771,-0.0175695110350900,-0.0128155908603601;
-4.06029341772399e-18,-5.65705978843172e-18,-1.80182480882056e-18,-1.59281757789645e-18;
0.221482525259710,-0.0576644539359728,0.0163934384910353,0.0197432976432437];
u = [1.37058079022968;
1.79302486419321;
69.4330887239959;
-52.3949662214410];
y = v*u;
Gives 0 for the first expression and 7.1387e-28 for the second. Is this a precision error thing? Which version is better/ more accurate to use and why? Thank you!
I have not checked your simplification, but floating-point math in general is inexact. Even doing the same operations in a different order can give you different results. With the deviations you are seeing I would believe they could reasonably come from inexactness in floating-point math and it is up to you to decide whether the deviations are acceptable for your purpose.
To determine which version is more accurate you would have to compute reference values to compare to, which might prove difficult.

Logical indexing and double precision numbers

I am trying to solve a non-linear system of equations using the Newton-Raphson iterative method, and in order to explore the parameter space of my variables, it is useful to store the previous solutions and use them as my first initial guess so that I stay in the basin of attraction.
I currently save my solutions in a structure array that I store in a .mat file, in about this way:
load('solutions.mat','sol');
str = struct('a',Param1,'b',Param2,'solution',SolutionVector);
sol=[sol;str];
save('solutions.mat','sol');
Now, I do another run, in which I need the above solution for different parameters NewParam1 and NewParam2. If Param1 = NewParam1-deltaParam1, and Param2 = NewParam2 - deltaParam2, then
load('solutions.mat','sol');
index = [sol.a]== NewParam1 - deltaParam1 & [sol.b]== NewParam2 - deltaParam2;
% logical index to find solution from first block
SolutionVector = sol(index).solution;
I sometimes get an error message saying that no such solution exists. The problem lies in the double precisions of my parameters, since 2-1 ~= 1 can happen in Matlab, but I can't seem to find an alternative way to achieve the same result. I have tried changing the numerical parameters to strings in the saving process, but then I ran into problems with logical indexing with strings.
Ideally, I would like to avoid multiplying my parameters by a power of 10 to make them integers as this will make the code quite messy to understand due to the number of parameters. Other than that, any help will be greatly appreciated. Thanks!
You should never use == when comparing double precision numbers in MATLAB. The reason is, as you state in the the question, that some numbers can't be represented precisely using binary numbers the same way 1/3 can't be written precisely using decimal numbers.
What you should do is something like this:
index = abs([sol.a] - (NewParam1 - deltaParam1)) < 1e-10 & ...
abs([sol.b] - (NewParam2 - deltaParam2)) < 1e-10;
I actually recommend not using eps, as it's so small that it might actually fail in some situations. You can however use a smaller number than 1e-10 if you need a very high level of accuracy (but how often do we work with numbers less than 1e-10)?

MATLAB - replace zeros in matrix with small number

I have a matrix with some elements going to zero. This is a problem for me in consequent operations (taking log, etc). Is there a way to quickly replace zero elements in a matrix with a input of my choice. Quickly - meaning, without a loop.
The direct answer is:
M(M == 0) = realmin;
which does exactly what you ask for, replacing zeros with a small number. See that this does an implicit search for the zeros in a vectorized way. No loops are required. (This is a MATLAB way, avoiding those explicit and slow loops.)
Or, you could use max, since negative numbers are never an issue. So
M = max(M,realmin);
will also work. Again, this is a vectorized solution. I'm not positive which one is faster without a careful test, but either will surely be acceptable.
Note that I've used realmin here instead of eps, since it is as small as you can realistically get in a double precision number. But use whatever small number makes sense to you.
log10(realmin)
ans =
 -307.6527
Compare that to eps.
log10(eps)
ans =
-15.6536
Sure--where A is your matrix,
A(A==0) = my_small_number;
Assume your matrix is called A
A(A==0) = eps;

in matlab exit the entire loop and more

I am using this function to get a column vector in which every element is supposed to be 1,
but after n gets large, sometimes some element is not 1, this is due to the method constraint, I want to find out how large is n and return the value. the problem are: 1.it seems that 1 is stored as 1.0000, don't know how to convert it, and how to compare(location in comments) 2. don't know how to exit a loop completely. thank you.
function x = findn(n)
for m = 1:n
[a,b]=Hilbert(m);
m1 = GaussNaive(a,b);
m2 = size(m1,1);
% m1 is a n*1 matrix (a column vector) which every element is supposed
% to be 1, but when n gets large, some element is not 1.
for i = 1:m2
if (m1(i) ~= 1)
% this compare isn't really working, since 1 is stored as 1.0000 for whatever
% for whatever reason and they are not equal or not not equal.
% I doubt whether it really compared.
x = m;
break;
% it just exit the inner for loop, not entirely
end
end
end
In Matlab all numeric variables are, by default, double precision floating-point numbers. (Actually strings and logicals can look like f-p numbers too but forget that for the moment.) So, unless you take steps that your code doesn't show, you are working with f-p numbers. The sort of steps you can take include declaring your variables to have specific types, such as int32 or uint16, and taking care over the arithmetic operations you perform on them. Matlab's attraction to double-precision floating-point is very strong and it's easy to operate on ints (for example) and end up with floating-point numbers again. Start reading about those types in the documentation.
The reasons for avoiding (in-)equality tests on f-p numbers are explained on an almost daily basis here on SO, I won't repeat them, have a look around. The straightforward way to modify your code would be to replace the test with
if (m1(i) ~= 1)
with
if ((abs(m1(i)-1)>tol)
where tol is some small number such that any number larger than 1+tol (or smaller than 1-tol) is to be considered not equal to 1 for your purposes.
Unfortunately, as far as I know, Matlab lacks a statement to break from an inner loop to outside a containing loop. However, in this case, you can probably replace the break with a return which will return control to the function which called your function, or to the command-line if you invoked it from there.

Matlab if loop not working

%function [flag] =verify(area)
[FileName,PathName,FilterIndex]= uigetfile('*.tif','Select the signature file');
display(PathName)
m=[PathName,FileName];
area=nor_area(m);
%display(area)
%area=0.8707;
class(area)
flag=0;
extract=xlsread('D:\Project\Image_processing\important\best.xlsx', 'CW4:CW17');
c=numel(extract);
display(c)
l=extract(1);
class(l)
display(l)
for k = 1:c
%x=extract(k);
if (l==area && flag==0)
% display(extract(k));
flag=1;
display(flag)
end
end
display(flag)
The above is my code for verification, i am not able to compare "l==area", even if the values are same am not able to enter inside the loop. If i try passing the value assume l=0.9999 and the area that i obtain to be the same , if i sent l value explicitly it works..!! but if i try using some function and pass the same value it wont work. I have tried checking the type by using class, both returns double.
Can anyone please help me out with this and if this approach is not good, suggest any alternative that may be used.
It is not generally a good idea to compare floats like you are doing (with the == operator) since floats, unlike integer values are subject to round off. See here and here for a discussion on comparing floats in MATLAB.
Essentially you have to check that two floats are 'close enough' rather than exactly equal, which is what == checks for. MATLAB has a built in function eps for determining the floating point precision on your machine, so use that function when comparing floats. See its documentation for more information.
In most cases it is not wise to compare floating point numbers by a == b. Use abs(a-b)<epsilon where epsilonis some small tolerance like 1e-10 instead.