# For loop with decimal increment not seen as integer or logical value

26 views (last 30 days)
Commented: Walter Roberson on 23 Jan 2020 at 4:32
Goal:
1. Have for loop repeatedly create matrices of random integers
2. Create new matrix where columns = variance for each row of random integer matrices
3. Compare variance to increment ranging from 0:0.01:4 (0-4 in increments of 0.01) and retain each matrix of 0s and 1s generated this way
The following code produces the desired results when the increment = 1 (not 0.01)
T = 10;
W = zeros(3,10);
for trial = 1:T
mtest = randi([1,5],3,4)
W(:,trial) = var(mtest,0,2);
end
minc = zeros(3,10,5);
for mindex = 0:1:4
minc(:,:,mindex+1) = W >= mindex
end
Problem 1: The same code does not work when the increment is set to 0.01:
linc = zeros(3,10,401);
for lindex = 0:0.01:4
linc(:,:,lindex+1) = W >= lindex
end
Error = Index in position 3 is invalid. Array indices must be positive integers or logical values.
Problem 2: After much reading, I think the problem is that "lindex+1" produces indices of 1.01, 1.02...etc. Yet both of the below solutions produce the same error.
Solution 1: Add 1 to remove 0 from index; multiply by 100 such that index should proceed as 100, 101, 102...etc.
linc = zeros(3,10,401);
for lindex = 0:0.01:4
linc(:,:,(lindex+1)*100) = W >= lindex
end
Solution 2: Start index at 0.01 instead of 0 and multiply by 100 such that index should proceed as 100, 101, 102...etc.
linc = zeros(3,10,401);
for lindex = 0.01:0.01:4
linc(:,:,lindex*100) = W >= lindex
end
Why does the code work if increment = 1 but not 0.01? How can I fix this? Thank you in advance, this is a wonderful community.

Sindar on 23 Jan 2020 at 4:09
It's not clear to me why your solutions aren't working, but the method KSSV suggests is easier and more reliable. In fact, I find it can often be worthwhile to iterate over a set of indices even when you don't plan to use your variable as an index. It just makes things a bit cleaner and easier to test (e.g., looping only over some of the data)
Thank you...this makes sense. Thank you for your suggestion. I think the hardest part of my learning curve as a new coder is "coding etiquette", as my computer science friend calls it. So I truly am grateful for any tips like both of you have given me.
I should add for anyone else who comes across this thread...this link posted in another thread by Image Analyst also really helped me. At least, I was able to identify how my index was a non-integer after reading this. There's a section toward the end that addresses this exact error message.

KSSV on 23 Jan 2020 at 4:01
Edited: KSSV on 23 Jan 2020 at 4:02
lindex = 0:0.01:4 ;
linc = zeros(3,10,401);
for i = 1:length(lindex)
linc(:,:,i) = W >= lindex(i) ;
end
Please note that, your indices should not be zero, or fractions or negative. In your original code in problem 1, you have used fractions, zero as indices, therefore you gor errors.

Thank you so much. It worked perfectly. I'm still overcoming the learning curve with programming, so I want to make sure I understand where I went wrong. Am I correct that your solution worked because "1:length(lindex)" set the index to automatically start at 1?
I'm surprised that neither of my solutions worked, as I checked my math in Excel and it should have set the index to start at 100. I'm confused as to why that didn't work, given that my original code worked when the increment was set to 1. Perhaps it's best practice to specify the index outside the for loop, as you did, and then begin the for loop with "i = length(index)" to avoid these kinds of errors?
KSSV on 23 Jan 2020 at 4:22
When the step size was 1, you had all integers as indices and there was no error. When the step size was 0.001, you have fractions and indices cannot be fractions.
Walter Roberson on 23 Jan 2020 at 4:32
If you take values constructed with the : operator with increment 0.01 and you multiply the values by 100, then roughly 1/10th of the results will not be integers.
MATLAB does not represent numbers in decimal: it represents them in binary. In binary, 1/100 requires an infinite repeating number to represent exactly, for precisely the same reason that in decimal, 1/7 needs an infinite repeating number to exactly represent. Therefore any finite binary truncation of a multiple of 1/100 will not exactly represent the fraction, and when you multiply the inexact representation by 100 you will not always get out an integer.