Как реализованы математические библиотеки с бесконечной точностью? - PullRequest
3 голосов
/ 17 июня 2009

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

Ответы [ 6 ]

4 голосов
/ 17 июня 2009

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

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

3 голосов
/ 17 июня 2009

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

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

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

1 голос
/ 17 июня 2009

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

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

1 голос
/ 17 июня 2009

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

Некоторые примеры:

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

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

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

1 голос
/ 17 июня 2009

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

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

0 голосов
/ 17 июня 2009

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

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