Небольшое отступление от точности с плавающей запятой (im), часть 1

StackOverflow https://stackoverflow.com/questions/1053

Вопрос

Большинство математиков согласны с тем, что:

eни + 1 = 0

Однако большинство реализаций с плавающей запятой расходятся во мнениях.Насколько хорошо мы можем урегулировать этот спор?

Мне очень хотелось бы услышать о разных языках и реализациях, а также о различных методах, позволяющих сделать результат как можно ближе к нулю.Будьте изобретательны!

Это было полезно?

Решение

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

PI - это бесконечная последовательность цифр, которую никто не смог обозначить ничем иным, кроме символического представления, а e ^ X - это одно и то же, и, таким образом, единственный способ достичь 100% точности - перейти на символьный формат.

Другие советы

Вот краткий список реализаций и языков, которые я пробовал.Они отсортированы по близости к нулю:

  • Схема: (+ 1 (make-polar 1 (atan 0 -1)))
    • 0.0+1.2246063538223773e-16i (Схема Chez, Схема MIT)
    • 0.0+1.22460635382238e-16i (Коварство)
    • 0.0+1.22464679914735e-16i (Курица с numbers яйцо)
    • 0.0+1.2246467991473532e-16i (MzScheme, SISC, Gauche, Гамбит)
    • 0.0+1.2246467991473533e-16i (SCM)
  • Обычный шепелявый: (1+ (exp (complex 0 pi)))
    • #C(0.0L0 -5.0165576136843360246L-20) (КЛИСП)
    • #C(0.0d0 1.2246063538223773d-16) (CMUCL)
    • #C(0.0d0 1.2246467991473532d-16) (SBCL)
  • Perl: use Math::Complex; Math::Complex->emake(1, pi) + 1
    • 1.22464679914735e-16i
  • Питон: from cmath import exp, pi; exp(complex(0, pi)) + 1
    • 1.2246467991473532e-16j (CPython)
  • Рубин: require 'complex'; Complex::polar(1, Math::PI) + 1
    • Complex(0.0, 1.22464679914735e-16) (МРТ)
    • Complex(0.0, 1.2246467991473532e-16) (Джруби)
  • R: complex(argument = pi) + 1
    • 0+1.224606353822377e-16i

Возможно ли урегулировать этот спор?

Моя первая мысль - обратиться к символическому языку, например Кленовый.Хотя я не думаю, что это считается точкой с плавающей запятой.

На самом деле, как можно представить i (или j для инженеров) на обычном языке программирования?

Возможно, лучшим примером является sin (π) = 0?(Или я снова упустил главное?)

Я согласен с Райаном, вам нужно было бы перейти на другую систему представления чисел.Решение выходит за рамки математики с плавающей запятой, потому что вам нужно, чтобы число pi было представлено в виде бесконечно длинной десятичной дроби, поэтому любая схема ограниченной точности просто не будет работать (по крайней мере, без использования какого-либо коэффициента выдумки для восполнения потерянной точности).

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

Если вам нужна большая точность, вам нужно использовать другое числовое представление.Точно так же, как если бы вы выполняли целочисленную математику для чисел, которые не помещаются в int или long.В некоторых языках есть встроенные библиотеки для этого (я знаю, что в java есть BigInteger и BigDecimal), но вам пришлось бы явно использовать эти библиотеки вместо собственных типов, и производительность была бы (иногда значительно) хуже, чем если бы вы использовали значения с плавающей точкой.

@Райан Фокс

На самом деле, как можно представить i (или j для инженеров) на обычном языке программирования?

Собственные сложные типы данных далеко не неизвестны.В Fortran это появилось к середине шестидесятых, и OP демонстрирует множество других языков, которые поддерживают их в hist followup.

А комплексные числа могут быть добавлены в другие языки в виде библиотек (при перегрузке оператора они даже выглядят точно так же, как собственные типы в коде).

Но если вы не приведете особый случай для этой проблемы, "несогласие" - это просто выражение неточной машинной арифметики, не так ли?Это все равно что жаловаться на то, что

float r = 2/3;
float s = 3*r;
float t = s - 2;

заканчивается на (t ! = 0) (По крайней мере, если вы используете достаточно тупой компилятор)...

Я оооочень долго болтал за чашечкой кофе со своим лучшим другом, обсуждая иррациональные числа и разницу между другими числами.Что ж, мы оба согласны с этой разной точкой зрения:

Иррациональные числа - это отношения, как функции, в некотором смысле, каким образом?Ну, подумайте о "если вы хотите получить идеальный круг, дайте мне идеальное число пи", но круги отличаются от других цифр (4 стороны, 5, 6...100, 200), но...Сколько еще у вас сторон, это больше похоже на круг.Если вы следили за мной до сих пор, то соедините все эти идеи вот с формулой числа пи:enter image description here

Итак, pi - это функция, но такая, которая никогда не заканчивается!из-за параметра ∞, но мне нравится думать, что у вас может быть "экземпляр" pi, если вы измените параметр ∞ на очень большой Int, у вас будет очень большой экземпляр pi.

То же самое с e, дайте мне огромный параметр, я дам вам огромное e.

Сведение всех идей воедино:

Поскольку у нас ограниченная память, язык и библиотеки предоставляют нам огромный экземпляр иррациональных чисел, в данном случае pi и e, в качестве конечного результата вам придется долго искать 0, как в примерах, предоставленных @Chris Jester-Young

На самом деле, как можно представить i (или j для инженеров) на обычном языке программирования?

На языке, который не имеет собственного представления, оно обычно добавляется с помощью ООП для создания Complex класс для представления i и j, с перегрузкой оператора для надлежащего выполнения операций , связанных с другими Complex числа и / или другие числовые примитивы, присущие данному языку.

Например: Complex.java, C++ < сложный >

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

Это влияет не только на рассматриваемое здесь уравнение, но и может привести к нестабильности всего, от решения почти сингулярного набора одновременных уравнений, путем нахождения нулей многочленов, до оценки log (~ 1) или exp (~ 0) (я даже видел специальные функции для оценки log (x + 1) и (exp (x)-1), чтобы обойти это).

Я бы посоветовал вам думать не в терминах обнуления разницы - вы не можете, - а скорее выполнять соответствующие вычисления таким образом, чтобы обеспечить минимальную ошибку.

Прости, прошло 43 года с тех пор, как мне вдалбливали это в универе, и даже если бы я мог вспомнить ссылки, я уверен, что сейчас есть вещи получше.Я предлагаю это в качестве отправной точки.


Если это звучит немного покровительственно, я приношу свои извинения.Мой "Численный анализ 101" был частью курса химии, поскольку в те дни CS было не так уж много.На самом деле я не совсем понимаю, какое место / важность имеет численный анализ в современном курсе CS.

Это ограничение наших нынешних вычислительных архитектур с плавающей запятой.Арифметика с плавающей запятой - это лишь приближение числовых полюсов, таких как e или pi (или чего-либо, выходящего за рамки точности, допускаемой вашими битами).Мне действительно нравятся эти числа, потому что они не поддаются классификации и, по-видимому, обладают большей энтропией (?), чем даже простые числа, которые являются каноническим рядом.Числовое представление ratio не поддается описанию, иногда подобные простые вещи могут свести человека с ума (мне это нравится).

К счастью, целые языки и библиотеки могут быть посвящены прецизионным тригонометрическим функциям с использованием нотационных концепций (аналогичных тем, которые описаны Lasse V.Карлсен ).

Рассмотрим библиотеку / язык, который описывает такие понятия, как e и pi, в форме, понятной машине.Имеет ли машина какое-либо представление о том, что такое идеальный круг?Вероятно, нет, но мы можем создать объект - окружность, который удовлетворяет всем известным характеристикам, которые мы ему приписываем (постоянный радиус, отношение радиуса к окружности равно 2 * pi * r = C).Такой объект, как pi, описывается только вышеупомянутым соотношением.r & C могут быть числовыми объектами, описываемыми с любой точностью, которую вы хотите им придать.e может быть определено "как e - единственное действительное число, такое, что значение производной (наклона касательной линии) функции f (x) = ex в точке x = 0 равно ровно 1" из википедия.

Забавный вопрос.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top