Problem during a while loop

Hi everyone,
I am having some troubles regarding the use of a basic "while" loop... It may seem easy at a first look but it is actually a tricky problem. For summing up, I did a basic function which can be used with the workspace attached :
function [test] = test( ped_form2, ped )
taille_form2=size(ped_form2);
l_fm2=taille_form2(1,1);
j=1;
test=zeros(l_fm2,8);
while ped<1
col=2;
while ped~=ped_form2(1,col)
col=col+1;
end
for i=1:l_fm2
test(i,j)=ped_form2(i,col);
end
j=j+1;
ped=ped+0.05;
end
end
The aim of the second while loop is to return the "col" variable when "ped" equals to the right cell of the first line in "ped_form2". Two lines after, the "col" variable is re-used to copy paste the column from "ped_form2" to the variable "test". After that, the "ped" value is incremented by 0.05 and so on until 1.
My problem is that from 0.15 (starting point of "ped" from the workspace) to 0.40, the function works perfectly fine. I checked several times with the step-by-step mode from Matlab but, for an unknown reason, when ped=0.40, it stops running with this error :
??? Index exceeds matrix dimensions.
Error in ==> test at 13
while ped~=ped_form2(1,col)
Actually, I found that the variable "col" keeps incrementing whereas ped equals to ped_form2, sort of missing the right cell with the good value.
Does someone have any kind of solution or idea to resolve this problem?
This would help me a lot, I have been trying to solve this for 2 hours.
Regards,
Bastien C.

2 Comments

A few points on glancing at this:
  • Never name a variable the same as a function. It doesn't seem to be causing you a problem here, but it is not good practice at all!
  • You keep talking about "right cell" of ped_form2 yet I don't see any cell arrays involved in this. If ped_form2 were a cell array then your ped_form2(1,col) access would return a cell which would obviously not be comparable to a double (ped).
  • There is almost certainly a better way to find the col value that you want from ped_form2, but without you giving an example of its structure it is difficult to work out exactly what is contained in it.
  • Testing absolute equality (or equivalently inequality) between double types is dangerous. A ~= test will pass even if the difference between the two values is e.g. 1e-16 which, for doubles, in most cases, is a difference that would be considered to just be error coming from the inexactness of the storage. Unless you are 100% certain that the values you are testing against on both sides of the operator are absolutely specified, i.e. stored to 100% accuracy, you should always test to within a tolerance.
Adam
Adam on 19 Mar 2015
Edited: Adam on 19 Mar 2015
Ah, sorry, I just noticed the attached .mat file so I will take a quick look at that and comment further afterwards in place of my 3rd point above...

Sign in to comment.

 Accepted Answer

col = find( ped_form2(1,:) >= ped, 1 )
should work in-place of your internal while loop if I understand it correctly. I haven't tested that everything else in the function works with that in, but it is a better way to achieve your aim for that part of the code.

2 Comments

Thank you both of you for your answer!
I appreciate the tips for writing well-structured functions. Adam and dpb, you were perfectly right: the difference between the two values was about 1e-17 and screwed my condition. I tried both of your line of code (which is much better) and it works like a charm.
Again, thank you!
Regards,
NB: the above is not terribly robust; if the rounding is such that the actual value is just slightly less instead of greater for the target, col will return the index of one higher than that of the nearest match. That's the point of the tolerance test on the difference in the form I used; it's insensitive to the direction of the error.
You can recast it for find as well to avoid the loop.

Sign in to comment.

More Answers (1)

" I found that the variable "col" keeps incrementing whereas ped equals to ped_form2, sort of missing the right cell with the good value."
Classical case of trying to use exact comparisons for floating point values; you'll have to use a tolerance to match "nearly equal".
Something otoo...
while abs(ped-ped_form2(1,col))>2*eps*ped
would use twice the spacing in floating point values around the value of ped as the error tolerance; "salt to suit" your needs.

1 Comment

Thank you both of you for your answer!
I appreciate the tips for writing well-structured functions. Adam and dpb, you were perfectly right: the difference between the two values was about 1e-17 and screwed my condition. I tried both of your line of code (which is much better) and it works like a charm.
Again, thank you!
Regards,

Sign in to comment.

Asked:

on 19 Mar 2015

Commented:

dpb
on 19 Mar 2015

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!