Как реализованы математические библиотеки с бесконечной точностью?

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

  •  05-07-2019
  •  | 
  •  

Вопрос

Итак, я знаю о точности с плавающей запятой (и о том, что такие вещи, как 1.1, не могут быть точно выражены в двоичном формате) и все такое, но мне интересно:как же тогда библиотеки, связанные с математикой, реализуют бесконечную точность?Другими словами, как бы вы точно представили, например, 1.1 в двоичном формате?Просто краткое описание было бы здорово, я сам могу разобраться в точных деталях.Спасибо.:)

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

Решение

Нет библиотек с бесконечной точностью, но есть библиотеки произвольной точности. Подробнее о том, как они реализованы, читайте в документации : -)

Для точного представления 1.1 в двоичном виде нельзя использовать плавающую точку, как вы правильно указали. Это можно представить, если вы сохраняете интегральную часть (1) как целое число, а дробная часть (.1) - как другое целое число, а затем вам необходимо создать логику для работы с этими структурами. Кроме того, он может быть сохранен в виде дроби (11/10), причем знаменатель и числитель хранятся в виде целых чисел.

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

Если вы действительно имеете в виду бесконечную точность, есть два варианта:

  • Используйте какую-то форму отложенных вычислений.Затем вы можете запросить число с максимально возможной точностью "после" выполнения вычисления (поскольку оно ленивое, на самом деле оно выполняется только тогда).Недостатком является то, что это очень неэффективно.Вы можете сделать это на таком языке, как Haskell, используя специальную систему счисления, где представления перекрываются, напримероснование 2 с цифрами -1, 0, 1.Обычное представление непригодно, потому что, скажем, при 1 вам нужна бесконечная точность, чтобы выбрать между выводом 0 и 0.999...и 1 за 1.000...

  • Выполняйте вычисления символически.Точно представлять целые числа, рациональные числа, корни и т.д.Это необходимо, если вы хотите определить равенство, но также довольно неэффективно и ограничено особыми случаями.

Математические библиотеки с точностью бесконечной не реализованы. Это не может быть сделано. Число 1/3 не может быть представлено в конечном числе битов, кроме как дробь. Трансцендентные числа, такие как пи и е, не могут быть полностью представлены каким-либо образом.

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

Существуют определенные геометрические алгоритмы, которые зависят от точной арифметики, поэтому, если вы заглянете в библиотеку CGAL, вы найдете множество точных числовых типов, которые "закрываются" при различных операциях.То есть, нет никакого способа использовать поддерживаемые операции для получения результата, который не может быть представлен точно.

Несколько примеров:

  • Целые числа закрываются при сложении и умножении.

  • Рациональные числа также замыкаются при делении, за исключением особого случая для нуля.Может быть представлен в виде пары целых чисел.Смотрите также функции рационального числа в GMP.например, 1.1 = 11/10, может быть представлено в виде (11, 10).

  • Тип числа, который также закрывается под квадратный корень.

Вы также можете представлять числа в десятичной системе счисления и выполнять десятичную арифметику.Базовое представление является двоичным в том смысле, что каждая цифра представлена двоичным кодом.Каждая цифра - будь то слева или справа от десятичной точки - обрабатывается как целое число.Затем арифметика выполняется `вручную", цифра за цифрой.

Одним из примеров библиотеки, основанной на десятичной системе счисления, является BCMath в PHP.

Хотя Pax совершенно прав, когда мы говорим о числах с плавающей запятой и числах, я считаю, что есть решение, но оно очень неэффективно.
Вы можете использовать строку для представления вашего числа, строки не теряют точность.
Всякий раз, когда у вас есть номер, такой как «0,0001» + "0,1" Вы перебираете обе строки и конвертируете только текущую позицию в int.
Шаг 1:
0 + 0 = 0 - > преобразовать в строку и присвоить данным [0].
Шаг 2:
0 + 1 = 1 - > преобразовать в строку и присвоить данным [1].
Шаг 3:
iter > "0,1" .lenght () - > остановка.

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