Ошибка плавающей точки Matlab [дубликат]

попробуйте это, он должен вернуть ip-адрес сервера

$host= gethostname();
$ip = gethostbyname($host);
56
задан rayryeng 18 August 2016 в 07:21
поделиться

6 ответов

Проблема, с которой вы сталкиваетесь, связана с тем, как числа с плавающей запятой представлены на компьютере. Более подробное обсуждение представлений с плавающей запятой появляется к концу моего ответа (раздел «Плавающее представление»). Версия 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 для арифметики с плавающей запятой ) Что должен знать каждый компьютерный ученый Арифметика с плавающей запятой Дэвида Голдберга

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

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

Этот формат допускает числовые представления в диапазоне от 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 значащих цифр. Это иллюстрирует, как смещение или масштабирование данных могут изменять точность выполненных на нем вычислений, что должно быть связано с определенными проблемами.

79
ответ дан Kamran Bigdely 17 August 2018 в 10:06
поделиться
  • 1
    почему я не вижу эту маленькую десятичную сумму? – Kamran Bigdely 26 March 2009 в 17:18
  • 2
    вы можете увидеть это, если вы просмотрите переменную в матричном представлении. Щелкните правой кнопкой мыши на переменной - & gt; & quot; Просмотр выбора & quot; или что-то? У меня здесь нет MATLAB, поэтому я не могу проверить. – atsjoo 26 March 2009 в 17:20
  • 3
    Вы также можете увидеть небольшие различия, набрав & quot; format long & quot; в командной строке. – gnovice 26 March 2009 в 17:23
  • 4
    вы правы: формат длинных точек = 12.000000000000000 15.000000000000000 33.000000000000000 23.999999999999996 33.000000000000000 24.000000000000000 – Kamran Bigdely 26 March 2009 в 21:02
  • 5
    "формат hex" иногда может помочь даже больше, чем формат здесь. – Sam Roberts 5 October 2009 в 16:25

Попробуйте написать

0.1 + 0.1 + 0.1 == 0.3.

Внимание: вы можете быть удивлены результатом!

7
ответ дан Andrey Rubshtein 17 August 2018 в 10:06
поделиться
  • 1
    Я попробовал, и он возвращает 0. Но я не вижу, что он должен делать, с проблемой выше. Можете ли вы объяснить мне это? – Max 16 September 2015 в 08:46
  • 2
    Это связано с тем, что в 0.1 возникает ошибка с плавающей запятой, и когда вы добавляете три таких термина вместе, ошибки не обязательно сводятся к 0. Эта же проблема приводит к тому, что (плавающий) 24 не будет точно равен (другому плавному) 24 , – Derek 4 March 2016 в 12:14

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

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

1
ответ дан Dmitri Chubarov 17 August 2018 в 10:06
поделиться

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

1
ответ дан Jimmy J 17 August 2018 в 10:06
поделиться

type

format long g

Эта команда покажет FULL значение этого числа. Вероятно, это будет что-то вроде 24.00000021321! = 24.00000123124

12
ответ дан KitsuneYMG 17 August 2018 в 10:06
поделиться

Посмотрите на эту статью: Опасности плавающей точки . Хотя его примеры в FORTRAN имеют смысл практически для любого современного языка программирования, включая MATLAB. Ваша проблема (и решение для нее) описана в разделе «Безопасные сравнения».

20
ответ дан Rorick 17 August 2018 в 10:06
поделиться
Другие вопросы по тегам:

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