Проверка делимости для (типа) больших чисел в 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(...))
, хотя вы могли бы рассмотреть возможность избежать расчетов с плавающей запятой вообще, так как вещи начнут ломаться для достаточно больших значений.)