Высокая точность арифметики в Python и / или C / C ++? - PullRequest
1 голос
/ 23 января 2011

Аннотация: Какой пакет Python или библиотека C-Library - лучший вариант для арифметических операций с очень высокой точностью?

У меня есть некоторые функции, которые преобразуют дробные дни (0.0-0.99999..) в понятный человеку формат (часы, минуты, секунды, но что более важно: миллисекунды, микросекунды, наносекунды).

Преобразование выполняется этими функциями: (обратите внимание, что я еще не внедрил коррекцию часового пояса)

d = lambda x: decimal.Decimal(str(x))
cdef object fractional2hms(double fractional, double timezone):
    cdef object total, hms, ms_mult
    cdef int i
    hms = [0,0,0,0,0,0]
    ms_mult = (d(3600000000000), d(60000000000), d(1000000000), d(1000000), d(1000), d(1))
    # hms = [0,0,0,0,0]

    total = d(fractional) * d(86400000000000)
    for i in range(len(ms_mult)):
        hms[i] = (total - (total % ms_mult[i])) / ms_mult[i]
        total = d(total % ms_mult[i])

    return ([int(x) for x in hms])

А до дробного:

def to_fractional(self):
        output = (self.hour / d(24.0)) + (self.minute / d(1440.0))
        output += (self.second / d(86400.0)) + (self.millisecond / d(86400000.0))
        output += self.microsecond / d(86400000000.0)
        output += self.nanosecond * (d(8.64) * d(10)**d(-9))
        return output

Мои результаты обратного преобразования неверны, однако:

jdatetime.DayTime.fromfractional(d(0.567784356873)).to_fractional()
Decimal('0.56779150214342592592592592592592592592592592592592592592592592592592592592592592592592592592592592592592592592592')
# Difference in-out: Decimal('0.000007145270')

Когда я изменяю d() для возврата обычного числа Python:

# Difference in-out: 7.1452704258900823e-06 (same)

Поэтому мой вопрос: какой пакет Python или C-библиотека могут сделать это более точно?

Ответы [ 2 ]

4 голосов
/ 23 января 2011

Разница связана с ошибкой в ​​вашем коде, а не с проблемой точности. Линия

output += self.nanosecond * (d(8.64) * d(10)**d(-9))

должно быть что-то вроде

output += self.nanosecond / d(86400000000000)

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

d = decimal.Decimal

и использовать только целочисленные литералы (просто удалите часть .0).

2 голосов
/ 23 января 2011

CTRL-F "Библиотеки" там: Arbitrary-precision_arithmetic

EDIT: извлечение из библиотек ссылок только для c ++ и python (и удаление некоторых, которые не имеют плавающих чисел, но только целые числа)

python

1) mpmath


c ++

1) apfloat

2) базовый номер класса

3) bigfloat

4) Лидия

5) mapm

6) MIRACL

7) NTL

8) ttmath

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