How to compare two double values in matlab? - matlab

I want to compare two double values. I know the value of MinimumValue, which is 3.5261e+04. This MinimumValue I got from an array e. My code has to print first statement 'recognized face' because both value are same. But my code is displaying second statement 'unrecognized face'.
What is the mistake in my code?
MinimumValue = min(e)
theta = 3.5261e+04;
if (MinimumValue <= theta)
fprintf('recognized face\n');
else
fprintf('unrecognized face\n');
end

There are two approaches:
Replace if MinimumValue<=theta with if MinimumValue == theta. This is the easier but probably poorer approach for your problem.
Chances are, MinimumValue is different from theta by a very small amount. If you are doing some calculations by hand to determine that theta = 3.5261e+04, and believe there are more decimal places, you should use format long to determine the actual value of theta to 15 significant figures. After that, you can use if abs(MinimumValue - theta) <= eps (edit: As patrick has noted in the comment below, you should compare to some user-defined tolerance or eps instead of realmin('double').

Related

Compute all the local extremepoints of a function using fminunc

So I want to compute the lokal extremas for the function
I used this link to help me out. Here is what I've done:
options = optimset('Display','off');
[min1,fval1]=fminunc(#(x)(sin(x(1)+x(2))+3*(x(1)-x(2)/2)^2)*exp(-(x(1)^2+x(2)^2)),[0;-1],options
[min2,fval2]=fminunc(#(x)(sin(x(1)+x(2))+3*(x(1)-x(2)/2)^2)*exp(-(x(1)^2+x(2)^2)),[1.18;2.3],options)
[max1,fval3]=fminunc(#(x)-(sin(x(1)+x(2))+3*(x(1)-x(2)/2)^2)*exp(-(x(1)^2+x(2)^2)),[1;0],options)
[max2,fval4]=fminunc(#(x)-(sin(x(1)+x(2))+3*(x(1)-x(2)/2)^2)*exp(-(x(1)^2+x(2)^2)),[2.3;1.18],options)
format long g
The points p1, p2, p3 and p4 were obtained from WolframAlpha.
The output in the command window is this:
min1 =
-0.3032
-0.5316
fval1 =
-0.50675
min2 =
1.1773
2.2344
fval2 =
-0.00043457
max1 =
0.91017
-0.29929
fval3 =
-1.5746
max2 =
-0.80798
0.61241
fval4 =
-1.2629
Questions:
For min2 I have fval2 = -0.00043457, which is correct. But I want it to say fval2 = -0.0004, how can I do this?
For max1 and max2, I just made the entire function negative and then applied fminunc. This gave me correct (x,y)-koordinates of the respective maxima but the value at these points are given with opposite signs. How can I make Matlab give me fval3 and fval4 as positive?
If you want to round fval2 to 4 decimal places, use round(fval2,4). If you don't want to round and simply want to display fval2 till 4 decimal places, use sprintf i.e. sprintf('%.4f',fval2).
Note that you are getting that many digits in the first place since you've changed the format. To reset it to default, enter format or format short.
You are meant to negate your objective function and calculate minimas of the negated function. These minimas are actually maximas of the original function but fval3 and fval4 are internally calculated by putting them in the negated function and hence you get the negative sign. Simply negate them again or evaluate your original function on the maximas.
Results from your Matlab script and Wolfrom are identical for p1 and p2 as they are minimums. (Once again see the Wolfram page)
For maximums, I found the problem. Your code is ok. Only the initial guesses should be better determined for p3 and p4. Use your own code but with these guesses for 3rd and 4th function:
h=#(x) -(sin(x(1)+x(2))+3*(x(1)-x(2)/2)^2)*exp(-(x(1)^2+x(2)^2));
[max1,fval3]=fminunc(h,[-1;1]);
[max2,fval4]=fminunc(h,[1;-0.3]);
However, I recommend you another method for finding local extermas: Find where the derivative of the function with respect to x and y is zero.
Q1: Use round() function to round it.
Q2: The answers Matlab displayed for this script are exactly identical to the Wolfram.
max1 =
-0.807979637093575
0.612410258594483
max2 =
0.910173217929548
-0.299286619005528
Q3: Use x=fminunc(...); instead of [x,fval]=fminunc(...); to omit fval.

angle() of a real number

I'm a bit confused about the angle() function in Matlab, in particular when applied to an array of real numbers.
The angle() function should give me the phase of a complex number. Example: y = a + bi, ==> phase = arctan(b/a). Indeed, the following works:
for t=1:1000
comp(t) = exp(1i*(t/10));
end
phase_good_comp1 = unwrap(angle(comp)); %this gives me the right answer
b = imag(comp);
a = real(comp);
phase_good_comp2 = atan(b./a); %this gives me the right answer too, but
wrapped (not sure if there is a way to unwrap this, but unwrap() does not
work)
figure(1)
plot(phase_good_comp1)
hold on
plot(phase_good_comp2,'--r')
legend('good phase1', 'good phase2')
title('complex number')
Here's the plot for the complex numbers --
Note that I can use either the angle() function, or the explicit definition of phase, as I have shown above. Both yield good results (I can't unwrap the latter, but that's not my issue).
Now if I apply the same logic to an array of real numbers, I should get a constant phase everywhere, since no imaginary part exists, so arctan(b/a) = arctan(0) = 0. This works if I use the explicit definition of phase, but I get a weird result if I use angle():
for t=1:1000
ree(t) = cos((t/10));
end
phase_bad_re = unwrap(angle(ree)); %this gives me an unreasonable (?) answer
b = imag(ree);
a = real(ree);
phase_good_re = atan(b./a); %this gives me the right answer
figure(1)
plot(phase_bad_re)
hold on
plot(phase_good_re,'--r')
legend('bad phase', 'good phase')
title('real number')
Here's the plot for the real numbers --
Why the oscillation when I use angle()???
The Matlab documentation tells you how to compute this:
The angle function can be expressed as angle(z) = imag(log(z)) = atan2(imag(z),real(z)).
https://www.mathworks.com/help/matlab/ref/angle.html
Note that they define it with atan2 instead of atan.
Now your data is in the range of cosine, which includes both positive and negative numbers. The angle on the positive numbers should be 0 and the angle on the negative numbers should be an odd-integer multiple of pi in general. Using the specific definition that they've chosen to get a unique answer, it is pi. That's what you got. (Actually, for the positive numbers, any even-integer multiple of pi will do, but 0 is the "natural" choice and the one that you get from atan2.)
If you're not clear why the negative numbers don't have angle = 0, plot it out in the complex plane and keep in mind that the radial part of the complex number is positive by definition. That is z = r * exp(i*theta) for positive r and theta given by this angle you're computing.
Since sign of cosine function is periodically changed, angle() is also oscillated.
Please, try this.
a=angle(1);
b=angle(-1);
Phase of 1+i*0 is 0, while phase of -1+i*0 is 3.14.
But, in case of atan, b/a is always 0, so that the result of atan() is all 0.

Calculate the percentage in Matlab

I want to calculate the percentage of accuracy. I have the code below. But it give unexpected output like this "The accuracy is 2.843137e+01x37".
While expected result is "The accuracy is 28.43%"
y %Amount of correct data
j %Amount of all data
a = 'The accuracy is %dx%d.';
percent = '%.0f%%';
format short
acc = 100 * double(y/j);
sprintf (a,acc)
How to fix it?
Any help would be so much appreciated.
Thank you.
You almost have what you expected, just put it together the right way.
The correct format specifier for 28.43% is %.2f%%. This gives you two digits after the decimal point and adds the %-sign at the end. You have that defined in the variable percent, except that .0 should be .2 for two digits as you have written in the expected result. If you look closely, you'll realize that percent is never used.
Let's come to the conclusion. Change the format specifier to the following:
a = 'The accuracy is %.2f%%';
That's all you need to do. The line defining percent can be omitted as well as format short unless you need this for something later on.
Something important regarding the cast to double: What you currently have just casts the result. If necessary, do the cast individually to y and/or j before the division. Probably you don't need any casting in your case.
The whole code with an assumption for y and j is:
y = 28.43137; %// Amount of correct data
j = 100; %// Amount of all data
a = 'The accuracy is %.2f%%';
acc = 100 * (y/j); %// no cast
% acc = 100 * (double(y)/double(j)); %// with cast
sprintf(a,acc);
Output:
ans =
The accuracy is 28.43%
Try,
a = 'The accuracy is %f.';
acc = 100 * double(y/j);
sprintf (a,acc)

Wrong value while summing floats in matlab

while (tempsumf ~= sum)
iter = iter + 1;
tempsumf = tempsumf + fitness(iter, 1);
if (tempsumf > sel1)
break;
end
end
I have an array(fitness) of floats here (mostly with exponent -6/-5) which i am summing up in tempsumf ... now when the loop goes to the second iteration, i get the value 5.000 which is utterly wrong. I can figure out the issue.
This is probably due to floating point precision. You shouldn't do equality or inequality tests on double precision numbers. Instead of while (tempsumf ~= sum), use while (abs(tempsumf - sum))>1e-6) or whatever threshold you deem appropriate.
See the MATLAB wiki entry on this topic for more information.
Second possible cause of the error: you are overwriting the built-in function sum with your variable sum. Don't do that! Call your variable my_sum or something similar.

Matlab, graphing functions

I have a homework problem, I think I did it correctly but need to make sure 100%. Can anyone check for me, before I hand it in?
Thank you.
Question:
Plot the function given by f (x) = 2 sin(2x) − 3 cos(x/2) over the in-
terval [0, 2π] using steps of length .001 (How?). Use the commands max and min to estimate the maximum and minimum points. Include the maximum and minimum points as tick marks on the x-axis and the maximum and minimum values as tick marks on the y-axis.
My code:
x=linspace(0,2*pi,6280);
f=#(x)...
2.*sin(2.*x)-3.*cos(x./2);
%f = #(x)2.*sin(2.*x)-3.*cos(x./2)
g=#(x)...
-1*(2.*sin(2.*x)-3.*cos(x./2));
%g = #(x)-1*(2.*sin(2.*x)-3.*cos(x./2))
[x3,y5]=fminbnd(g,0,2*pi);
%x3 = 4.0968
%y3 = -3.2647
[x2,y4]=fminbnd(f,0,2*pi);
%x2 =2.1864
%y2 = -3.2647
y2=max(f(x));
y3=min(f(x));
plot(x,f(x));
set(gca,'XTick',[x2 x3]);
set(gca,'YTick',[y2 y3]);
(*after I paste this code here, it appeared not as nice as I had it in my program, don't know why)
To create a vector with certain step do
x=0:0.001:2*pi;
Why do you have g(x) function and why are you using fminbind? Use MIN and MAX, return index of those values and find related x values.
[ymin, minindex] = min(f(x));
xmin = x(minindex);
For general case if you have multiple min/max values, index will contain only the first occurrence. Instead you can do:
minindex = find(y==ymin);
Or for real values to avoid precision error:
minindex = find(abs(y-ymin)<=eps);
Also your last statement returns error Values must be monotonically increasing. To avoid it sort your tick values.
set(gca,'XTick',sort([xmin xmax]));
set(gca,'YTick',sort([ymin ymax]));