0

I am trying to understand the while statement in MatLab so this is what I did:

i=0;
while i<=20
  disp(i)
  i=i+1;
end

and as I expected, MatLab displayed numbers 0-20. However with this one:

j=0;
while j<=2
  disp(j)
  j=j+0.1;
end

MatLab only displays numbers 0-1.9. I expected to see numbers 0-2; what am I doing wrong here?

user172675
  • 69
  • 1
  • 6
  • 6
    [What Every Computer Scientist Should Know About Floating-Point Arithmetic](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) – rwong Mar 28 '15 at 05:19
  • @beaker Good catch. Although you've got close vote privileges, so go and use them :-) – Philip Kendall Mar 28 '15 at 19:21

2 Answers2

1

Your code is not idiomatic MATLAB.

Idiomatic MATLAB looks like this:


% This is technically the same as your code, 
% so it should have suffered from exactly the same problem. 
% But thanks to rearrangement of calculation, 
% MATLAB will calculate the number of iterations is with a division,
% which gives ((20 - 0) / 0.1 + 1) == 201
% Because the result value of 201 is a "small" integer, 
% the IEEE floating-point rounding logic will cause the result's  
% representation to be exactly 201, and not some plus/minus epsilon.
%
% I have to emphasize this is not always the case; sometimes
% division can give not-exactly-integer results as well.
%
% This "almost, but not quite always" correct behavior led most 
% beginning MATLAB users into thinking that MATLAB is less susceptible 
% to the intricacies of finite-precision floating point arithmetics, 
% but OP's code example shows that MATLAB users must exercise 
% the same level of care as programmers of C.
%
for j = 0:0.1:20, 
    disp(j); 
end

% Integer index range is accurate up to `(2^53) - 1`
% beware of off-by-one.
idx = (0:200) * 0.1; 
for j = idx, 
    disp(j); 
end

% If you only care about the start, stop, 
% and the number of generated values.
% Beware of off-by-one.
idx = linspace(0, 20, 201); 
for j = idx, 
    disp(j); 
end
rwong
  • 6,062
  • 1
  • 23
  • 51
1

the reason why it doesn't turn out the same is that base-2 floating-point numbers can represent 1 perfectly and precisely. but they do not represent 0.1 precisely. evidently the 0.1 value is represented a teeny-weeny bit high, like 0.10000000000000000001 so that when 0.10000000000000000001 is added to itself 20 times, it exceeds 2.0 (which is precisely represented) and therefore the test in the while loop fails in that last iteration where we would be expecting it to pass.