MATLAB ismember () проблема - PullRequest
       8

MATLAB ismember () проблема

2 голосов
/ 30 июля 2009

Следующая команда возвращает 1:

ismember(-0.6, -1:.1:.9)

но следующая команда возвращает 0:

ismember(-0.1, -1:.1:.9)

, хотя -0,1 явно находится в -1: .1: .9.

Кто-нибудь знает, что происходит?

Ответы [ 4 ]

4 голосов
/ 30 июля 2009

Проблема в том, что когда вы начинаете с -1,0 и добавляете 0,1 несколько раз, вы получаете немного другое число, чем если вы укажете -0,1 напрямую. Это из-за накопления ошибок с плавающей точкой. Точно так же, как 1/3 нельзя представить точно в десятичном виде (оно становится 0,33333 ...), многие десятичные числа не могут быть представлены точно в двоичном виде. 0,1 при преобразовании в двоичный код на самом деле очень близко приближается к 0,1. Поскольку при выполнении арифметики с этим числом с плавающей запятой возникает небольшая ошибка, эта небольшая разница накапливается и становится все больше и больше.

С http://www.mathworks.com/matlabcentral/newsreader/view_thread/246492:

Ашвини Дешпанде писал:


У меня есть следующая матрица,

a = 0:0.1:1;

когда я попытался определить, присутствует ли в матрице значение 0.300 a, используя следующую процедуру,

>> [tf, loc]=ismember(0.3,a)

Я получил следующий результат:

tf =
     0
loc =
     0

Но это должно дать мне tf = 1 и loc =4.


На самом деле вы получаете правильный результат. Посмотрите, что происходит:

     v=0:.1:1;
     n=0.3;
     sprintf('%30.20f\n',v(4),n)
%{
     0.30000000000000004000 % <- result from vec
     0.29999999999999999000 % <- result from handwritten number
%}
     format hex;
     [v(4),n,v(4)-n].'
%{
     3fd3333333333334 % <- vec
     3fd3333333333333 % <- num
     3c90000000000000 % <- diff
%}
     format;

Также, просмотрите http://matlabwiki.mathworks.com/MATLAB_FAQ#Why_is_0.3-0.2-0.1_not_equal_to_zero_.28or_similar.29.3F

4 голосов
/ 30 июля 2009

Ошибка с плавающей точкой.

Число 0.1 действительно очень близко к значению в векторе, но не совсем. Некоторые числа не могут быть точно представлены в двоичном компьютере.

Что вы пытаетесь сделать точно, есть много методов пороговых значений, которые могут сработать здесь, если мы лучше знаем вашу ситуацию.

1 голос
/ 06 октября 2014

Простой способ обойти эту проблему - округлить массив перед сравнением. Для FKT 100 это даст вам массив, который квантован с точностью до 2 десятичных знаков.

круглый (FKT. * Данные) ./ ФКТ

1 голос
/ 30 июля 2009

То, что вы видите, является следствием представлений с плавающей запятой для чисел в том смысле, что число 0.1 не совсем точно представляется в виде значения с плавающей запятой. Оператор двоеточия , используемый для создания вектора, делает это путем последовательного добавления значения 0,1 и накапливает очень маленькие ошибки в процессе. Значение в векторе, которое вы считаете -0,1, на самом деле немного отличается от -0,1 из-за этих ошибок, а также отличается от значения -0,1, которое получается, когда вы объявляете его напрямую. Возьмите этот пример:

>> format long   % Changes display to show more decimal places
>> vec = -1:0.1:0.9;
>> vec(10)+0.1

ans =

    2.775557561562891e-017

Обратите внимание, что вы не получите 0 в качестве ответа, поскольку -0,1 в векторе очень немного отличается по абсолютной величине от 0,1, который вы добавляете к нему. Однако, если бы вы создали свой вектор без , используя оператор двоеточия, вы бы получили желаемый ответ:

>> vec = [-1 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0 ...
          0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9];
>> ismember(-0.1,vec)

ans =

     1

Короче говоря, явное объявление значения -0,1 дает очень немного другое число, чем генерация значения -0,1 путем последовательного добавления 0,1 к -1.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...