简体   繁体   English

在Python中检查(某种)大数的可除性

[英]Checking divisibility for (sort of) big numbers in python

I've been writing a simple program in python that encodes a string into a number using Gödel's encoding . 我一直在用python写一个简单的程序,使用Gödel的编码将字符串编码成数字。 Here's a quick overview: you take the first letter of the string, find its position in the alphabet (a -> 1, b -> 2, ..., z -> 26) and raise the first prime number (2) to this power. 快速概览:获取字符串的第一个字母,找到其在字母表中的位置(a-> 1,b-> 2,...,z-> 26),然后将第一个质数(2)增大为这种力量。 The you take the second letter in the string and the second prime (3) and so on. 您将字符串中的第二个字母和第二个质数(3)取为此类推。 Here's the code: 这是代码:

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

The primes() function works for my intends and purposes and so does Encode(). primes()函数可以满足我的意图和目的,Encode()也可以。 Now Decode() is the interesting part. 现在,Decode()是有趣的部分。 It works for encodings up to ~15 digits long but starts doing some mystical stuff starting at ~20 digits. 它适用于最长约15位数的编码,但从约20位数开始开始进行一些神秘的工作。 So for instance it gives the right output for the encoding of "aaaaaaaaaaaaaa" but not for "python". 因此,例如,它为“ aaaaaaaaaaaaaaaaaa”的编码提供了正确的输出,但没有为“ python”提供正确的输出。 For big numbers it seems to execute the while code % i == 0 loop too many times (176 for the first letter of "python" when it should be just 16). 对于大数,似乎执行while code % i == 0循环了太多次(“ python”的第一个字母为176,当它仅为16时)。

Is this just a problem with the mod function in python? 这仅仅是python中的mod函数的问题吗? Sounds strange as 20 digits isn't all that long for a computer. 听起来很奇怪,因为20位数字对于计算机来说还不够长。 Is there a mistake in my code? 我的代码有错误吗? Thanks for all the help. 感谢您的所有帮助。 I'm not a programmer myself but I'm trying to learn doing stuff like this. 我自己不是程序员,但我正在尝试学习做这样的事情。 Therefore any constructive criticism is welcome. 因此,欢迎任何建设性的批评。

/= in Python 3 returns a double-precision floating point value. 在Python 3中, /=返回双精度浮点值。 (As does math.ceil , btw.) Floating point values do not have arbitrary precision. (与math.ceil和btw一样。)浮点值没有任意精度。 You could use //= instead. 您可以使用//=代替。 That always results in an integer. 总是产生一个整数。 (It gives the floor of the result.) (它给出结果的下限。)

(I previously said that math.ceil was your main culprit. I don't think that's the case, but nonetheless, you probably shouldn't be using a floating point value to index into a list. If you need to run the same code in Python 2 that will fail. You can cast it back to an integer using int(math.ceil(...)) , although you might want to consider avoiding floating-point calculations altogether, since things will begin to break down for sufficiently large values.) (我之前说过math.ceil是您的主要罪魁祸首。我不认为是这种情况,但尽管如此,您可能不应该使用浮点值来索引到列表中。如果您需要运行相同的代码在Python 2中会失败。您可以使用int(math.ceil(...))将其int(math.ceil(...))转换为整数,尽管您可能要考虑完全避免使用浮点数计算,因为这样一来,事情就会开始分解大价值。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM