Проверка делимости для (типа) больших чисел в python

я писал простую программу на python, которая кодирует строку в число, используя кодировка Геделя. Вот краткий обзор: вы берете первую букву строки, находите ее положение в алфавите (a - > 1, b -> 2,..., z - > 26) и поднимите первое простое число (2) до этой степени. Вы берете вторую букву в строке и второе простое число (3) и так далее. Вот код:

import string, math
alphabet = list(string.ascii_lowercase)

def primes(n):
    "Returns a list of primes up to n."

    primes = [2, 3]
    i = 5
    while i < n:
        l = math.ceil(math.sqrt(i))
        k = math.ceil(math.sqrt(i+2))
        for p in primes[:l]:
            if i % p == 0:
                break
        else:
            primes.append(i)
        for p in primes[:k]:
            if (i+2) % p == 0:
                break
        else:
            primes.append(i+2)
        i += 6
    return primes

def Encode(string):
    "Encodes a string using Godel's encoding."

    enc = 1
    p = primes(100)
    for i in range(len(string)):
        enc = enc*(p[i]**(alphabet.index(string[i])+1))
    return enc

def Decode(code):
    "Decodes a Godel's encoding into a string."

    dec = ""
    for i in primes(100):
        count = 0
        while code % i == 0:
            code /= i
            count += 1
        if count == 0: #If we've found a prime that doesn't divide code, 
                       #there are no more letters to be added.
            break
        else:
            dec += alphabet[count-1]
    return dec

функция primes () работает для моих намерений и целей и то же самое делает Encode (). Теперь Decode () - интересная часть. Он работает для кодировок длиной до ~15 цифр, но начинает делать некоторые мистические вещи, начиная с ~20 цифр. Так, например, он дает правильный вывод для кодирования "aaaaaaaaaaaaaa", но не для"python". Для больших чисел, похоже, выполняется while code % i == 0 цикл слишком много раз (176 для первой буквы "python", когда она должна быть только 16).

Это просто проблема с функцией mod в python? Звучит странно, как 20 цифры не так уж длинны для компьютера. Есть ли ошибка в моем коде? Спасибо за помощь. Я сам не программист, но я пытаюсь научиться делать такие вещи. Поэтому любая конструктивная критика приветствуется.

1 ответов


/= в Python 3 возвращает значение с плавающей запятой двойной точности. (Как и math.ceil, кстати.) Значения с плавающей запятой не имеют произвольной точности. Вы могли бы использовать //= вместо. Это всегда приводит к целому числу. (Это дает слово результата.)

(Я ранее говорил, что математика.сейл была твоей главной виновницей. Я не думаю, что это так, но, тем не менее, вы, вероятно, не должны использовать значение с плавающей запятой для индексирования в список. Если вам нужно запустить тот же код в Python 2, который потерпит неудачу. Вы можете вернуть его в целое число, используя int(math.ceil(...)), хотя вы могли бы рассмотреть возможность избежать расчетов с плавающей запятой вообще, так как вещи начнут ломаться для достаточно больших значений.)