Почему 24.0000 не равно 24,0000 в MATLAB?

Предполагая, что вы позаботились о test_new, таблицах test_old (отфильтрованных с помощью as_of_date = '2019-03-10') во втором варианте.

1-й вариант, вы используете количество предложений select (X.item_id), где в качестве 2-го варианта count (отличный). Отличный, возможно, уменьшил количество предметов в более позднем варианте.

67
задан rayryeng - Reinstate Monica 18 August 2016 в 07:21
поделиться

5 ответов

Проблема, которую Вы имеете, касается, как числа с плавающей запятой представлены на компьютере. Более детальное обсуждение представлений с плавающей точкой появляется к концу моего ответа (Раздел "Floating-point representation"). TL; версия DR: потому что компьютеры имеют конечные объемы памяти, числа могут только быть представлены с конечной точностью. Таким образом точность чисел с плавающей запятой ограничена определенным числом десятичных разрядов (приблизительно 16 значащих цифр для значений двойной точности, значение по умолчанию, используемое в MATLAB).

Фактический по сравнению с отображенной точностью

Теперь обратиться к определенному примеру в вопросе... в то время как 24.0000 и 24.0000 отображены таким же образом, оказывается, что они на самом деле отличаются очень небольшими десятичными суммами в этом случае. Вы не видите его, потому что MATLAB только отображает 4 значащих цифры по умолчанию, сохраняя полный дисплей аккуратным и опрятным. Если Вы хотите видеть полную точность, необходимо или выйти format long управляйте или просмотрите шестнадцатеричное представление числа:

>> pi
ans =
    3.1416
>> format long
>> pi
ans =
   3.141592653589793
>> num2hex(pi)
ans =
400921fb54442d18

Инициализированные значения по сравнению с вычисленными значениями

С тех пор существует только конечное число значений, которые могут быть представлены для числа с плавающей запятой, для вычисления возможно привести к значению, которое падает между двумя из этих представлений. В таком случае результат должен быть округлен до одного из них. Это представляет небольшую ошибку машины точности. Это также означает, что инициализация значения непосредственно или некоторым вычислением может дать немного отличающиеся результаты. Например, значение 0.1 не имеет точного представления с плавающей точкой (т.е. оно немного округляется), и таким образом, Вы заканчиваете с парадоксальными результатами как это из-за способа, которым накапливаются ошибки округления:

>> a=sum([0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1]);  % Sum 10 0.1s
>> b=1;                                               % Initialize to 1
>> a == b
ans =
  logical
   0                % They are unequal!
>> num2hex(a)       % Let's check their hex representation to confirm
ans =
3fefffffffffffff
>> num2hex(b)
ans =
3ff0000000000000

Как правильно обработать сравнения с плавающей точкой

Так как значения с плавающей точкой могут отличаться очень небольшими количествами, любые сравнения должны быть сделаны путем проверки, что значения в некотором диапазоне (т.е. допуск) друг друга, в противоположность точно равному друг другу. Например:

a = 24;
b = 24.000001;
tolerance = 0.001;
if abs(a-b) < tolerance, disp('Equal!'); end

отобразится "Равный!".

Вы могли затем изменить свой код на что-то как:

points = points((abs(points(:,1)-vertex1(1)) > tolerance) | ...
                (abs(points(:,2)-vertex1(2)) > tolerance),:)

Представление с плавающей точкой

Хороший обзор чисел с плавающей запятой (и конкретно стандарт IEEE 754 для арифметики с плавающей точкой) - то, Что Каждый Программист Должен Знать Об Арифметике С плавающей точкой David Goldberg.

Двоичное число с плавающей запятой на самом деле представлено тремя целыми числами: знаковый бит s, мантисса (или коэффициент/часть) b, и экспонента e. Для двойной точности формат с плавающей точкой каждое число представлено на 64 бита, размеченные в памяти следующим образом:

enter image description here

Действительное значение может затем быть найдено со следующей формулой:

enter image description here

Этот формат допускает представления числа в диапазоне 10^-308 к 10^308. Для MATLAB можно получить эти пределы от realmin и realmax:

>> realmin
ans =
    2.225073858507201e-308
>> realmax
ans =
    1.797693134862316e+308

С тех пор существует конечное число битов, используемых для представления числа с плавающей запятой, существует только столько конечных чисел, которые могут быть представлены в вышеупомянутом данном диапазоне. Вычисления будут часто приводить к значению, которое точно не соответствует одному из этих конечных представлений, таким образом, значения должны быть округлены. Эти ошибки машины точности делают себя очевидными по-разному, как обсуждено в вышеупомянутых примерах.

Для лучше понимания этих ошибок округления, полезно посмотреть на относительную точность с плавающей точкой, обеспеченную функцией eps, который определяет количество расстояния от данного числа до следующего самого большого представления с плавающей точкой:

>> eps(1)
ans =
     2.220446049250313e-16
>> eps(1000)
ans =
     1.136868377216160e-13

Заметьте, что точность относительно размера данного представленного числа; большее число будет иметь большие расстояния между представлениями с плавающей точкой и будет таким образом иметь меньше цифр точности после десятичной точки. Это может быть важным фактором с некоторыми вычислениями. Рассмотрите следующий пример:

>> format long              % Display full precision
>> x = rand(1, 10);         % Get 10 random values between 0 and 1
>> a = mean(x)              % Take the mean
a =
   0.587307428244141
>> b = mean(x+10000)-10000  % Take the mean at a different scale, then shift back
b =
   0.587307428244458

Обратите внимание на это, когда мы сместим значения x от диапазона [0 1] к диапазону [10000 10001], вычислите среднее, затем вычтите среднее смещение для сравнения, мы получаем значение, которое отличается для последних 3 значащих цифр. Это иллюстрирует, как смещение или масштабирование данных могут изменить точность вычислений, выполненных на нем, который является чем-то, что должно составляться с определенными проблемами.

93
ответ дан Kamran Bigdely 24 November 2019 в 14:35
поделиться

Взгляд на эту статью: Опасности Плавающей точки. Хотя его примеры находятся в ФОРТРАНЕ, он имеет смысл для фактически любого современного языка программирования, включая MATLAB. Ваша проблема (и решение для него) описана в разделе "Safe Comparisons".

22
ответ дан Rorick 24 November 2019 в 14:35
поделиться

ввести

format long g

Эта команда покажет Полную стоимость числа. Это, вероятно, будет что-то как 24,00000021321! = 24.00000123124

13
ответ дан KitsuneYMG 24 November 2019 в 14:35
поделиться

Возможно, эти два числа действительно 24.0 и 24.000000001, но Вы не видите всех десятичных разрядов.

2
ответ дан Jimmy J 24 November 2019 в 14:35
поделиться

Проверьте функцию EPS Matlab.

Matlab использует математические операции с плавающей точкой до 16 цифр точности (только 5 отображены).

1
ответ дан Dmitri Chubarov 24 November 2019 в 14:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: