1
range = min(x):0.0001:max(x);
N = numel(range);
x = sort(x);
hit = 0;
i=1;

for j = 1:(N-1)
    if range(j) <= x(i) && x(i) < range(j+1)
        hit = hit + 1;
        i = i+1;
        if x(i) == x(i-1)
            while x(i) == x(i-1)    % If there are more than one of the same
                hit = hit + 1;      % numbers in succession, this allows x and
                i = i+1;            % hit to carry on incrementing. 
            end %while
        end %if
    end %if
end %for
disp(hit)

This code compares 'range' and 'x'. It checks to see if 'x' is between values in 'range', if so the 'hit' counter gets incremented and so does the current value of 'x'.

Problem is, on some random values of x (as far as I can tell they are random), although they should satisfy the inequality in the 'IF' statement, the 'IF' statement gets ignored, the for loop continues and thus the final 'hit' value is wrong.

'x' is usually a 1D array about a million or so wide.

for this example, let

`x = [-2.1792 -2.1759 -2.1758 -2.1748 -2.1658 -2.1648 -2.1646 -2.1604 -2.1603 -2.1550]`

'hit' should equal '10' but instead outputs '2' since it decides to skip the 'IF' statement at 'j=35'.

To clarify. When 'j=35', range(j) = -2.1758 and i=3 meaning x(i)=-2.1758

I'm pretty sure that:

range(j) <= x(i) && x(i) < range(j+1)
-2.1758 <= -2.1758 && -2.1758 < -2.1757    %**edited, meant -2.1757 not -2.1759**

Is true.

I hope I'm just doing something silly here that I can't see. Sorry if it's a badly formatted question, it's my first here. Cheers in advance.

NathM
  • 13
  • 5
  • -2.1758 < -2.1759 is not true. Is that a logic error? Does your code work if the values are all positive? – Brian A. Henning Dec 20 '13 at 17:52
  • Sorry my bad, edited to -2.1757. so -2.1758 < -2.1757 is true. – NathM Dec 20 '13 at 18:09
  • Maybe it's the usual problem when comparing real numbers? http://stackoverflow.com/questions/8959452/matlab-double-comparison – Luis Mendo Dec 20 '13 at 18:37
  • Unfortunately not. Earlier on in the code, not shown here, I round all the values of the arrays to 4 decimal places and the 'range' array increments by 0.0001 so there shouldn't be any misrepresentation of numbers. – NathM Dec 20 '13 at 19:02
  • Could you state in words what you are actually trying to achieve? It seems that the outer `if` statement doesn't do anything useful - so really it is as though you are counting number of successive equal values of `x`. In which case `sum(diff(x)==0)` would give you the same answer. Maybe I'm missing something. – Floris Dec 20 '13 at 19:27

2 Answers2

0

A subsequent number x(i) could pass this test:

if range(j) <= x(i) && x(i) < range(j+1)

Without actually being equal to its neighbor:

    if x(i) == x(i-1)

It could be infinitesimally larger and thus you move to the next j and it is out of range. Your inner while needs the same condition as the outer if. And you can skip the if COND while COND and just do while COND since it will work the same.

Ben Jackson
  • 90,079
  • 9
  • 98
  • 150
  • I don't quite get what you mean sorry. Getting rid of the IF makes sense. I don't understand how you mean the subsequent values would pass? – NathM Dec 20 '13 at 18:11
  • Consider a sequence of numbers 1.00010, 1.00011, 1.00012. They all fall between 1.0001 and 1.0002 but they are not *equal* to each other. – Ben Jackson Dec 20 '13 at 18:47
  • Ah I see what you mean, thanks. Though, each number is precise up to 4 decimal places, and the array 'range' increments at 0.0001 meaning then that there can't be more than one number falling between the two. – NathM Dec 20 '13 at 19:12
  • Well as strange as this is then. I replaced both irrelevant IF statements and implemented the WHILE loop with the same condition as the first IF statement. It worked! Though I don't see why since the precision was the same for both arrays! Ah well. Thank you for the help never the less! – NathM Dec 20 '13 at 19:23
  • 1
    The problem is that .0001 cannot be precisely represented in double precision. See this output, for example: `fprintf('%.20f\n', 0:.0001:.01);` There will always be errors in floating point representation (except for integers in a limited range). And further, equivalent math operations may not produce identical floating point results, because each intermediate result is rounded to fit the representation. Just say no to `==` operators with floating point numbers – Peter Dec 20 '13 at 21:38
0

Would the following code not be simpler, faster, and give the same result?

x = sort(x)
hit = sum(diff(x)==0);
Floris
  • 45,857
  • 6
  • 70
  • 122
  • Not quite, the array of 'x' does not go up by 0.0001, only the 'range' array. Therefore, if the subsequent values in the 'x' array are greater than '0' apart, they shall not be counted. My current code may seem quite pointless at the moment I agree, but I am constructing an algorithm to do box counting...it'll hopefully be a much more sensical piece of code when I'm done! – NathM Dec 20 '13 at 19:52