2015-02-15 1 views
0

Я написал следующее modulo exponentiation. Но я не уверен, что я потеряю точность при переходе от MPZ к длинному.Не теряйте точность при конвертации из MPZ в long?

def mypowmod(base, power, modulus): 
    base = gmpy.mpz(base) 
    power = gmpy.mpz(power) 
    modulus = gmpy.mpz(modulus) 
    result = pow(base, power, modulus) 
    return long(result) 
+0

Ваша функция лучше написана как 'mypowmod = pow'. –

+0

@DanD. что вы имеете в виду? – drdot

+0

Несвязанный: если результат имеет много цифр, и вы хотите получить десятичное представление (string), тогда не конвертируйте в 'long' и [оставить' gmpy2.mpz' as is - 'str (mpz)' is * much * быстрее, чем 'str (long)'] (http://stackoverflow.com/a/28480239/4279). – jfs

ответ

2

Отказ от ответственности: Я являюсь сторонником gmpy и gmpy2.

Длительный тип Python - произвольная точность. Конверсия в/из long и mpz всегда точна.

С long произвольная точность, встроенная функция pow() рассчитает правильный результат, не требуя использования gmpy или gmpy2. Однако использование типа mpz будет намного быстрее. Быстрый тест показывает, что он быстрее даже для количества всего 10 цифр.

$ python -m timeit -s "import gmpy;a=10;b=gmpy.mpz('1'*a);p=gmpy.mpz('2'*a)-7;m=gmpy.mpz('3'*a)+11" "pow(b,p,m)" 
1000000 loops, best of 3: 1.41 usec per loop 
$ python -m timeit -s "a=10;b=long('1'*a);p=long('2'*a)-7;m=long('3'*a)+11" "pow(b,p,m)" 
100000 loops, best of 3: 8.89 usec per loop 

gmpy не имеет функцию powmod(). Эта функция была введена в gmpy2. gmpy2.powmod автоматически преобразует аргументы в mpz и возвращает результат mpz. Ваша функция может быть записана в виде:

def mypowmod(base, power, modulus): 
    return long(gmpy2.powmod(base, power modulus) 

Даже в том числе преобразование между long и mpz, он по-прежнему намного быстрее, чем при использовании встроенного long типа.

python -m timeit -s "import gmpy2;a=10;b=long('1'*a);p=long('2'*a)-7;m=long('3'*a)+11" "long(gmpy2.powmod(b,p,m))" 
1000000 loops, best of 3: 1.72 usec per loop 
0

No.

Но использование gmpy.mpz типа в основном не нужен, как встроенный в long типа имеет все необходимые операции для выполнения этой функции. Код использует встроенный в pow функции, а не говорят, что gmpy.powmod функция так преобразования в gmpy.mpz является ненужным и, как функция pow возвращает long код становится:

def mypowmod(base, power, modulus): 
    result = pow(base, power, modulus) 
    return result 

Что лучше записать в виде:

mypowmod = pow 
+0

Если я не конвертирую вход в MPZ, как я могу обрабатывать целочисленный размер больше 2^63-1? Не могли бы вы привести простой пример на gmpy.powmod? – drdot

+0

Целые числа python не имеют фиксированного размера. они могут быть сколь угодно большими. – Eevee