Добавление 1 к очень маленьким числам

У меня есть вопрос о добавлении числа 1 к очень маленьким числам. Прямо сейчас я пытаюсь построить дугу окружности в комплексной плоскости с центром вокруг действительного числа 1. Мой код выглядит так:

arc = 1 + rho .* exp(1i.*theta);

Значение rho — очень маленькое число, а theta работает от 0 до pi, поэтому всякий раз, когда 1 добавляется к действительной части arc, MATLAB просто округляет его до 1, поэтому, когда я набираю plot(real(arc),imag(arc)), все, что я вижу, это шип вместо полукруга вокруг 1. Кто-нибудь знает, как исправить это, чтобы MATLAB не округлял 1 + real (дуга) до 1, а вместо этого сохранял точность?

Спасибо


person user1824904    schedule 14.11.2012    source источник
comment
Можете ли вы предоставить точный код, демонстрирующий эту проблему? На самом деле нет никакого способа дать окончательное решение, если мы не сможем воспроизвести проблему.   -  person Dan Becker    schedule 15.11.2012
comment
Побитово, извините, если вас обидел мой минус! Но я не думаю, что я был единственным человеком, который не понял актуальности вашего ответа. Я проголосовал против (и добавил комментарий, объясняющий, почему), вы обновили более полное объяснение, и теперь все, кто читает это, лучше понимают вашу точку зрения. Похоже на пример сообщества, работающего на меня.   -  person Dan Becker    schedule 15.11.2012
comment
@DanBecker Нет проблем и никаких обид - моя вина, что я не пояснил, насколько ответ актуален.   -  person Bitwise    schedule 15.11.2012


Ответы (3)


rho=1e-6; theta=0:pi/100:pi; arc=1+rho*exp(1i.*theta); plot(arc); figure(); plot(arc-1);

Показывает, что проблема в сюжете, а не в потере точности. После rho<1e-13 ожидаются проблемы с точностью.

Два других возможных заблуждения:
- двойные числа имеют конечную точность. 16 десятичных цифр или 1 + 2 ^ -52 - это предел для двойных чисел.
- короткий формат против длинного формата - по умолчанию Matlab показывает только 6 или 7 цифр.

Также случается, что 6-7 цифр являются пределом 32-битного числа с плавающей запятой, что также может объяснить, что, возможно, функция построения графика в Octave 3.4.3 также реализована с числами с плавающей запятой.

Слева: 1+1e-6*exp, справа: (1+1e-6*exp)-1

person Aki Suihkonen    schedule 14.11.2012
comment
Левый для 1e-6, я полагаю? Во фримате нужно получить аналогичную картинку с 1е-15, но не раньше. - person arne.b; 15.11.2012
comment
Аки, код в вашем посте - это код, который вы использовали для создания двух графиков, которые вы показываете? Когда я запускаю этот код, оба графика выглядят нормально (R2012a в Windows 8). - person Dan Becker; 15.11.2012
comment
А, я вижу, что вы используете Octave. Итак, похоже, что вы продемонстрировали проблему в Octave, но у Matlab этой проблемы нет. - person Dan Becker; 15.11.2012
comment
@DanBecker Не совсем. С MATLAB я не получаю изображения, подобного тому, что слева, но полукруг начинает сужаться для rho между 1e-11 и 1e-12 (где он уже выглядит довольно остроконечным), поэтому график MATLAB также несколько необычен. (plot(arc-1) все еще нормально, как и оба графика для этих значений ро во фримате, так что я думаю, что Аки что-то здесь понял.) - person arne.b; 15.11.2012

Существует встроенное решение именно для этой проблемы:

exp1m()

log1p()

явно:

log(arc)=log1p(rho*exp(1i*theta))

чтобы получить то, что вам нужно.

Конечно, вам нужно работать в пространстве журнала, чтобы представить эту точность, но это типичный способ, которым это делается.

person Bitwise    schedule 14.11.2012
comment
Полезные функции, но не актуальные для этого вопроса (аргумент exp здесь не малое число). - person Dan Becker; 15.11.2012
comment
@DanBecker определяет eps=rhoexp(1itheta), а затем log(arc)=log1p(eps). Я добавил его в ответ, чтобы он был написан явно. - person Bitwise; 15.11.2012

В представлениях с плавающей запятой двойной точности наименьшее число строго больше 1 что может быть представлено, это 1 + 2^-52.

Это ограничение, налагаемое способом представления нецелых чисел на большинстве машин, которого можно избежать в программном обеспечении, но не так просто. См. этот вопрос о подходах для MATLAB.

person arne.b    schedule 14.11.2012
comment
@AkiSuihkonen Не в моей октаве ... вы имели в виду 1e-16 (что будет ‹2^-53)? - person arne.b; 15.11.2012
comment
Я имею в виду rho=1e-6, как в моем ответе. Участок (дуга) расположен в шахматном порядке, а участок (дуга-1) гладкий. Только после rho‹1e-14 1+exp(i*theta) не может поддерживать ожидаемую точность. Моя октава 3.4.3. - person Aki Suihkonen; 15.11.2012
comment
@AkiSuihkonen Хорошо, я только что проверил реальное значение дуги (1) и дуги (2) вручную, никогда не использовал график октавы. С freemat я получаю отличные полукруги до rho=1e-13. - person arne.b; 15.11.2012
comment
Хотя пост Аки интересен, я сильно подозреваю, что это настоящая проблема, и нет другого реального решения, кроме решения построить дугу вокруг более удобной точки (например, 0). - person Dan Becker; 15.11.2012