2015-03-28 3 views
0

Я пытаюсь понять while заявление в MatLab, так это то, что я сделал:MatLab сравнение с плавающей точкой

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

и, как я ожидал, MatLab отображается число 0-20. Однако с этим:

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

MatLab отображает только цифры 0-1.9. Я ожидал увидеть цифры 0-2; что я делаю неправильно здесь?

+6

[Что каждый компьютерный ученый должен знать о арифметике с плавающей точкой] (http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) – rwong

+0

@beaker Хороший улов. Хотя у вас есть привилегии с правом голоса, так что идите и используйте их :-) –

ответ

1

Ваш код не является идиоматическим MATLAB.

Идиоматические MATLAB выглядит следующим образом:


% 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 
+0

Это все правда, но не объясняет, почему код OP не дает ожидаемого результата. –

+0

Надеюсь, мой ответ касается конкретного вопроса OP. –

1

причина, почему это не получится то же самое, что база-2 с плавающей точечные числа могут представлять 1 совершенно и точно. но они точно не представляют 0,1. очевидно, что значение 0,1 представляет собой младший биткий бит, например 0,10000000000000000001, так что когда 0,10000000000000000001 добавляется к себе 20 раз, он превышает 2.0 (что точно представлено), и поэтому тест в цикле while терпит неудачу в этой последней итерации где мы ожидаем, что он пройдет.

Смежные вопросы