Небольшое отклонение от точности с плавающей запятой (im), часть 1
Большинство математиков согласны с тем, что:
e πi + 1 = 0
Однако большинство реализаций с плавающей запятой не согласны. Насколько хорошо мы можем урегулировать этот спор?
Я очень хочу услышать о разных языках и реализациях, а также различные методы, чтобы сделать результат максимально приближенным к нулю. Будьте изобретательны!
Ответы
Ответ 1
Не то, чтобы большинство реализаций с плавающей запятой не соглашались, просто они не могут получить точность, необходимую для получения 100% -ного ответа. И правильный ответ в том, что они не могут.
PI - бесконечный ряд цифр, который никто не мог обозначить ничем иным, чем символическим представлением, а e ^ X одинаково, и таким образом единственный способ получить 100% -ную точность - пойти символически.
Ответ 2
Вот короткий список реализаций и языков, которые я пробовал. Он сортируется по близости к нулю:
- Схема:
(+ 1 (make-polar 1 (atan 0 -1)))
- ⇒
0.0+1.2246063538223773e-16i
(схема Chez, схема MIT)
- ⇒
0.0+1.22460635382238e-16i
(Guile)
- ⇒
0.0+1.22464679914735e-16i
(Курица с яйцом numbers
)
- ⇒
0.0+1.2246467991473532e-16i
(MzScheme, SISC, Gauche, Gambit)
- ⇒
0.0+1.2246467991473533e-16i
(SCM)
- Общий Lisp:
(1+ (exp (complex 0 pi)))
- ⇒
#C(0.0L0 -5.0165576136843360246L-20)
(CLISP)
- ⇒
#C(0.0d0 1.2246063538223773d-16)
(CMUCL)
- ⇒
#C(0.0d0 1.2246467991473532d-16)
(SBCL)
- Perl:
use Math::Complex; Math::Complex->emake(1, pi) + 1
- Python:
from cmath import exp, pi; exp(complex(0, pi)) + 1
- ⇒
1.2246467991473532e-16j
(CPython)
- Ruby:
require 'complex'; Complex::polar(1, Math::PI) + 1
- ⇒
Complex(0.0, 1.22464679914735e-16)
(MRI)
- ⇒
Complex(0.0, 1.2246467991473532e-16)
(JRuby)
- R:
complex(argument = pi) + 1
- ⇒
0+1.224606353822377e-16i
Ответ 3
Можно ли урегулировать этот спор?
Моя первая мысль - взглянуть на символический язык, например Maple. Я не думаю, что это считается плавающей точкой.
В самом деле, как представить я (или j для инженеров) на обычном языке программирования?
Возможно, лучшим примером является sin (π) = 0? (Или я снова пропустил этот пункт?)
Ответ 4
Я согласен с Райаном, вам нужно будет перейти в другую систему представления чисел. Решение выходит за рамки математики с плавающей запятой, потому что вам нужно, чтобы pi представлялся как бесконечно длинный десятичный знак, поэтому любая ограниченная схема точности просто не сработает (по крайней мере, не прибегая к использованию какого-либо фактора вымывания, чтобы составить потерянный точность).
Ответ 5
@Ryan Fox
На самом деле, как один представляет я (или j для инженеров) на обычном языке программирования?
Родные сложные типы данных далеки от неизвестности. У Fortran это было к середине шестидесятых годов, и OP демонстрирует множество других языков, которые поддерживают их в последующем.
И сложные номера могут быть добавлены на другие языки в виде библиотек (при перегрузке оператора они даже выглядят как родные типы в коде).
Но если вы не предоставите специальный случай для этой проблемы, "несогласие" - это просто выражение неточной машинной арифметики, нет? Он жалуется, что
float r = 2/3;
float s = 3*r;
float t = s - 2;
заканчивается на (t!= 0) (по крайней мере, если вы используете достаточно тупой компилятор)...
Ответ 6
Ваш вопрос кажется мне немного странным, поскольку вы, кажется, предполагаете, что математика Floating Point реализована языком. Это вообще неверно, так как математика FP выполняется с использованием процессора с плавающей запятой в аппаратном обеспечении. Но программное обеспечение или аппаратное обеспечение, плавающая точка всегда будет неточной. Это то, как работают float.
Если вам нужна более высокая точность, вам нужно использовать другое числовое представление. Точно так же, как если вы делаете целочисленную математику по числам, которые не вписываются в int или long. Некоторые языки имеют библиотеки для встроенных (я знаю, что у Java есть BigInteger и BigDecimal), но вам придется явно использовать эти библиотеки вместо родных типов, а производительность будет (иногда значительно) хуже, чем если бы вы использовали float.
Ответ 7
В самом деле, как представить я (или j для инженеров) на обычном языке программирования?
В языке, который не имеет нативного представления, он обычно добавляется с помощью ООП для создания класса Complex
для представления i
и j
, с перегрузкой оператора для правильной обработки операций с участием других Complex
номера и/или другие примитивы чисел, родные для языка.
Например: Complex.java, С++ < комплекs >
Ответ 8
Численный анализ учит нас, что вы не можете полагаться на точное значение небольших различий между большими числами.
Это не просто влияет на рассматриваемое уравнение здесь, но может привести к неустойчивости ко всему, от решения почти сингулярного множества одновременных уравнений, путем нахождения нулей полиномов, оценки log (~ 1) или exp (~ 0) (я даже видел специальные функции для оценки log (x + 1) и (exp (x) -1), чтобы обойти это).
Я бы посоветовал вам не думать с точки зрения обнуления разницы - вы не можете, а скорее выполнять соответствующие вычисления таким образом, чтобы обеспечить минимальную ошибку.
Прости, 43 года с тех пор, как я набросился на меня в uni, и даже если бы я мог вспомнить ссылки, я уверен, что сейчас там лучше. Я предлагаю this в качестве отправной точки.
Если это звучит немного покровительственно, я извиняюсь. Мой "Численный анализ 101" был частью моего курса "Химия", поскольку в те дни не было много CS. Я действительно не чувствую, что численный анализ места/важности имеет современный курс CS.
Ответ 9
Это ограничение наших текущих вычислительных архитектур с плавающей запятой. Арифметика с плавающей точкой - это всего лишь приближение числовых полюсов, таких как e или pi (или что-то сверх точности, которую позволяют ваши биты). Мне действительно нравятся эти цифры, потому что они бросают вызов классификации и, как представляется, имеют большую энтропию (?), Чем даже простые числа, которые являются каноническими рядами. Отношение нечетное числовое представление, иногда простые вещи, подобные этому, могут взорвать ум человека (я люблю его).
К счастью, целые языки и библиотеки могут быть посвящены точным тригонометрическим функциям, используя нотационные концепции (аналогичные тем, которые описаны Lasse V. Karlsen).
Рассмотрим библиотеку/язык, который описывает такие понятия, как e и pi, в форме, которую может понять машина. Есть ли у машины какое-либо представление о том, что такое идеальный круг? Вероятно, нет, но мы можем создать объект-круг, который удовлетворяет всем известным нам атрибутам (постоянный радиус, отношение радиуса к окружности равно 2 * pi * r = C). Объект, подобный pi, описывается только вышеупомянутым соотношением. r и C могут быть числовыми объектами, описываемыми любой точностью, которую вы хотите им дать. e можно определить "так как e - единственное вещественное число, такое, что значение производной (наклон касательной линии) функции f (x) = ex в точке x = 0 составляет ровно 1" из wikipedia.
Интересный вопрос.
Ответ 10
У меня были чаты кофе looooong, в которых мой лучший друг говорил об иррациональных числах и различии между другими числами. Ну, мы оба согласны в этой другой точке зрения:
Иррациональные числа - это отношения, как функции, каким образом, каким образом? Ну, подумайте о "если вы хотите идеальный круг, дайте мне идеальный пи", но круги отличаются друг от друга (4 стороны, 5, 6... 100, 200), но... Сколько еще сторон вы, скорее, похожий на круг. Если вы последовали за мной до сих пор, соединяя все эти идеи здесь, это формула pi:
Итак, pi - это функция, но никогда не заканчивается! из-за параметра ∞, но мне нравится думать, что вы можете иметь "экземпляр" pi, если вы измените параметр ∞ для очень большого Int, у вас будет очень большой экземпляр pi.
То же самое с e, дайте мне огромный параметр, я дам вам огромный e.
Объединяя все идеи:
Поскольку у нас есть ограничения в отношении памяти, язык и библиотеки предоставляют нам огромный экземпляр иррациональных чисел, в данном случае pi и e, в качестве конечного результата у вас будет длинный aproach, чтобы получить 0, как примеры, предоставленные @Chris Jester-Young