Ошибка с плавающей точкой в MATLAB - линейно разнесенные векторы
ОС: Win 7 64bit. Matlab: 2014a, 2015a
Когда я создаю вектор следующим образом:
a = 0.2:0.2:1
Я получил:
a = 0.2000 0.4000 0.6000 0.8000 1.0000
что ожидается. Теперь, когда я хочу увидеть, существует ли 0,6 в моем векторе, я печатаю:
a == 0.6
и я получаю: 0 0 0 0 0
find(a == 0.6)
также вернуть Empty matrix: 1-by-0
Это неожиданно. Он может найти все остальные значения, но для 0.6 есть проблема. Я думаю, что хотя 0,6 создается, это на самом деле 0,600000000000000001 или что-то подобное, что является проблемой. Вы можете видеть, что это a > 0.6
и получит 0 0 1 1 1
,
1-Во-первых, почему это происходит?
2-во-вторых, можем ли мы увидеть полное значение числа в Matlab, если да, то какова функция или настройка для этого?
Я создал тот же вектор, используя linspace
, но это тоже не помогло. Я нашел решение для этого, набрав: a = roundn(a, -10)
, Тем не менее, я думаю, что такое решение даже не нужно вообще.
3-Есть ли лучший способ заказать Matlab для получения точных значений?
Спасибо за вашу помощь.
1 ответ
Сначала прочтите документацию MATLAB по значениям с плавающей запятой, обратив особое внимание на раздел об ошибках и точности с плавающей запятой: MATLAB Floating Point
Вы столкнулись с невероятно распространенной проблемой с точностью с плавающей точкой. Важно признать, что вы на самом деле не сравниваете:
>> a = 0.6;
>> b = 0.6;
>> a == b
ans = 1
Вместо этого вы эффективно сравниваете:
>> a = 0.6;
>> b = 0.2 + 0.2 + 0.2;
>> a == b
ans = 0
Причиной очевидной логической ошибки здесь является то, что арифметика на самом деле не равна. Ценности 0.6
а также 0.2
оба представлены в виде числа с плавающей запятой двойной точности для максимально возможного значения CLOSEST, разницы, известной как "ошибка с плавающей запятой".
Наблюдать за ошибкой просто:
>> a = 0.6;
>> b = 0.2 + 0.2 + 0.2;
>> a - b
ans = -1.110223024625157e-16
Самое простое решение - использовать round()
на вашем скаляре и векторе с одинаковой точностью, затем выполните сравнение:
>> a = 0.6;
>> b = [ 0.2 : 0.2 : 1 ];
>> roundn ( a , -10) == roundn ( b , -10 )
ans = 0 0 1 0 0