How to resolve floating point numbers in if condition?
Show older comments
I want to find max(cor). And when I do this:
for k = 1 : length(theFiles) % files are alreaady defined in code
p=0;
t=0;
for q=.1:20
if(arr(p)<1)
if(arr(p)>0.85)
cor(t)=arr(p); %cor(t) already defined in code
t=t+1;
end
end
p=p+1;
end %end of q loop
[val1,idx1] = max(cor) ;
idx2 = find(abs(arr-val1)<10^-3) ;
end % end of k loop
Again, it shows idx2 for some of the inputs when printed, but for some it shows blank. such as:
idx2 is
I don't know whether it is relevent information or not, but the file for which the output above is shown(That is blank idx2), has the minimum of all the val1 of other files, such as, the values of val1 for other files are as follows:
9.554158e-01
9.634148e-01
9.750799e-01
9.841079e-01
9.753829e-01
9.764703e-01
Where the value for blank idx2, the val1 is:
9.243360e-01
How do I fix it?
15 Comments
KSSV
on 5 Jul 2021
If you want to find the maximum use max. Why you want to comapre again with
idx2 = find(abs(arr-val1)<10^-3) ;
Walter Roberson
on 5 Jul 2021
for q=.1:20
Why do you use that? The resulting q values would be 0.1 1.1 2.1 up to 19.1 for a total of 20 iterations. But you do not use the value of q so it is just counting, so why confuse the readers?
Also you initialize p to 0 and try to use arr(p) but indexing at 0 is not permitted.
Why not skip using q and instead use for p=1:20 ?
Tawsif Mostafiz
on 5 Jul 2021
Edited: Tawsif Mostafiz
on 5 Jul 2021
KSSV
on 5 Jul 2021
[val,idx] = max(cor) ;
arr(idx)
Tawsif Mostafiz
on 5 Jul 2021
Edited: Tawsif Mostafiz
on 5 Jul 2021
dpb
on 5 Jul 2021
" want to find the first instance, that is the index or location of when the value of max(cor) appears in the index arr(p). "
That would be
mx=max(cor) ; % the maximum and first location in cor array
ixa=find(arr==mx,1); % first place that max is, if it exists, in arr array
Ignoring the 0 indexing issue as the above wouldn't run at all with an error when it tries to reference arr(0) the first pass through the loop so I'll presume have fixed that by starting with p=1; t=1; instead of 0.
Several possible problems with your code above is as Walter pointed out that the loop over q only executes 20 times so if the location of the maximum in cor() is past that location as the comment notes that the array cor is defined outside the loop and you're just storing some new values into first portion of it if it has more than 20 elements, then the failure to find that location would be expected.
Alternatively, it's possible there are no values that satisfy the range condition of 0.85 < arr < 1 in which case cor() will not have been set with anything in this loop and would be whatever is left over from the definition outside the loop or empty if not initialized.
We simply don't have enough information with the partial code snippet to know precisely what is happening with any particular data set.
BUT -- if you use max() to find a value in an array, then find will match that value in another array exactly if that value is obtained by direct transfer from the other array--there will be no floating point rounding in that operation, so there's no need for the comparison with tolerance (for which, if were needed, use ismembertol instead).
So, first of all, need to know if it is intended to only be looking at the first 20 elements of the arr array, and if so, then limit all the code to that portion.
There aren't any loops needed at all here other than the outermost one over a set of files; the rest is done simply with logical or linear indexing operations.
Tawsif Mostafiz
on 5 Jul 2021
Edited: Tawsif Mostafiz
on 5 Jul 2021
dpb
on 5 Jul 2021
Attach the data as a .mat file; it's too cumbersome and hard to read such a large amount of text...
for s=1:length(arr)
fprintf("arr is %d\n",arr(s));
end
you don't need loops in MATLAB; to look at an array at command line just use
>> disp(arr)
0.1249
0.1018
0.1424
0.1875
0.1537
0.2113
>>
or just the variable name itself--
> arr
arr =
0.1249
0.1018
0.1424
0.1875
0.1537
0.2113
>>
The only difference there is whether the variable name is echo'ed first or not.
Only you want a particular formatting other than the default format currently in place in the command window do you need fprintf() or the like and even then there's no need for a loop--
>> fprintf('%0.6f\n',arr)
0.124898
0.101809
0.142425
0.187521
0.153704
0.211286
>>
As for the thing about number of elements, you haven't answered the question of what the length of the input vector arr is that you are wanting to iterate over; your original code had a loop over 20 iterations but that doesn't say anything about what arr size actually is other than it must have had at least 20 elements -- but, as noted, the way your code was written if it were larger, then you would have a potential problem.
Also, the way your initial code was written, the indexing variables p and t were indexed after the conditional was satisfied and so, if you just changed the initial condition on those to be 1 instead of 0 and kept the same code otherwise, then those will end up being one larger than the actual size of the number of elements found. This could be the cause of not finding an element.
Without the actual data and all for a precise case that you think doesn't work, we still don't have sufficient to (easily) debug what's going on.
Easiest would be for you to put together one small test case that is complete in and by itself that illustrates the input and the precise code that you ran and the results that you get and then what you think you should have gotten.
Tawsif Mostafiz
on 5 Jul 2021
Edited: Tawsif Mostafiz
on 5 Jul 2021
Walter Roberson
on 5 Jul 2021
Note that Windows will not permit you to save any file under the MATLAB installation folder. You should be sure to save to a folder that you have write access to.
dpb
on 5 Jul 2021
AGAIN, UNLESS WE HAVE THE ACTUAL ARRAY arr DATA, WE CAN'T DEBUG WHAT WE DON'T HAVE ACCESS TO!!!
Attach a .mat file that contains the arr array.
But, the above CANNOT have run as is to produce the given output --
clc;
clear all;
...
for q=1:43
arr(p)=abs(c); %c is derived in original code, thre are 43 values of c.
if(arr(p)<1)
if(arr(p)>0.85)
array(t)=white1;
cor(t)=arr(p);
t=t+1;
end
end
p=p+1;
end %end of q loop
because c is undefined. And, even if it were, then arr(p)=abs(c) would fail on an addressing error if c were a vector of 43 elements because it would try to put the whole array on the RHS into one array element on the LHS and you would get an error about number of elements must match.
Unless and until you produce a working code and the data that goes with it, there's nothing else to be done.
BUT, as I pointed out before, if the point is to just select the elements of arr that are between the two limits then all you need is the code I gave before in place of the double loop construct.
Also, the above does have the problem I outlined above that the t and p variables are incremented after the loop condition is satisfied and so end up as one greater than the number of elements that actually satisfy the condition. This doesn't matter for p but leaves t one too large for cor that contains values from the past loop -- and it is not reinitialized inside the outer loop over the number of files so it does still contain the previous data and will be as large as the largest number of elements found in any file but only have the number found in the current file that match; the rest will be from some previous file.
for q=1:43
arr(p)=abs(c); %c is derived in original code, thre are 43 values of c.
if(arr(p)<1)
if(arr(p)>0.85)
array(t)=white1;
cor(t)=arr(p);
t=t+1;
end
end
p=p+1;
end %end of q loop
should be replaced with
arr=abs(c); % presuming _c_ really is defined somewhere and abs() operation is really wanted
MN=0.85; MX=1; % define the bounds as variables
ix=iswithin(arr,MN,MX); % logical addressing vector of those satisfy conditional
cor=arr(ix); % keep only those wanted
array=repmat(white1,size(cor)); % secondary array of same size of constant???
Then you can find() the max value and location in the reduced array.
The above will eliminate the issue of not reinitializing the array and the counter and is much simpler than the double-loop. logical addressing and vector operations are "the MATLAB way".
iswithin is a utility function
function flg=iswithin(x,lo,hi)
% returns T for values within range of input
% SYNTAX:
% [log] = iswithin(x,lo,hi)
% returns T for x between lo and hi values, exclusive
flg= (x>lo) & (x<hi);
>>
Tawsif Mostafiz
on 6 Jul 2021
Edited: Tawsif Mostafiz
on 6 Jul 2021
dpb
on 6 Jul 2021
What's mx?
It should be the single maximum value you're looking for--if it's a vector, then something is wrong before here.
Tawsif Mostafiz
on 6 Jul 2021
Edited: Tawsif Mostafiz
on 6 Jul 2021
>> load work mx arr
>> whos arr mx
Name Size Bytes Class Attributes
arr 1x41 328 double
mx 0x0 0 double
>> ixa=find(arr==mx,1)
Error using ==
Matrix dimensions must agree.
>>
mx is empty so you haven't solved all the problems of including the case where there may not be any values within the bounds selected.
>> MN=0.85;MX=1;
>> cor=arr((arr>MN) & (arr<(MX)));
>> whos cor
Name Size Bytes Class Attributes
cor 1x0 0 double
>> isempty(cor)
ans =
logical
1
>> ixa=find(arr==mx,1)
Error using ==
Matrix dimensions must agree.
>>
So, == also fails if both are empty.
With the data for this particular sample, there are no values that satisfy the condition; you need to code for that possibility.
That's where a try...catch...end block could be useful
try
ixa=find(arr==mx,1);
catch ME
ixa=0;
end
You'll have to then also ensure you don't try to use the zero-valued index later on, of course....or have some other way of handling the case.
ADDENDUM:
But, at least with the data we can prove what happened...see how easy that was??? :)
Answers (0)
Categories
Find more on Logical in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!