簡體   English   中英

Python 3 中大數字的精確數學

[英]Exact math with big numbers in Python 3

我正在嘗試使用 Python 實現一個類似於Shamir's Secret Sharing 的加密系統。 本質上,我有代碼可以生成一個點列表,這些點可用於在由這些點形成的梯度的 y 軸截距處找到密碼。 密碼是 ASCII 中的數字(每個 ASCII 字符使用兩位數字),因此對於較大的密碼來說,這是一個相當大的數字。 例如,密碼ThisIsAPassword將生成如下所示的點列表:

x    y
9556 66707086867915126140753213946756441607861037300900
4083 28502040182447127964404994111341362715565457349000
9684 67600608880657662915204624898507424633297513499300
9197 64201036847801292531159022293017356403707170463200

需要明確的是,這些點是在隨機選擇的斜率上生成的(這很好,因為重要的是 y 軸截距)。

在嘗試制作一個程序來解碼密碼時會出現問題。 使用普通數學,Python 無法准確找到密碼,因為數字的大小。 這是我的代碼:

def findYint(x,y):
    slope = (y[1] - y[0]) / (x[1] - x[0])
    yint = int(y[0] - slope * x[0])
    return yint

def asciiToString(num):
    chars = [num[i:i+3] for i in range(0, len(num), 3)]

    return ''.join(chr(int(i)) for i in chars)

def main():
    fi = open('pass.txt','r')
    x,y = [], []
    for i in fi:
        row = i.split()
        x.append(int(row[0]))
        y.append(int(row[1]))
    fi.close()
    yint = findYint(x,y)
    pword = asciiToString(str(yint))

    print(pword)

main()

輸出(使用密碼“ThisIsAPassword”):

͉)3 ǢΜĩũć»¢ǔ¼

通常,我的代碼將使用較短的密碼,例如“pass”或“word”,但較大的數字可能無法以將它們轉換為 ASCII 所需的精確精度進行計算。 使用精確數學或其他方法的任何解決方案?

另外這里是生成點的代碼,以防萬一它很重要:

import random

def encryptWord(word):
    numlist = []
    for i in range(len(word)):
        numlist.append(str(ord(word[i])).zfill(3))
    num = int("".join(numlist))
    return num

def createPoints(pwd, pts):
    yint = pwd
    gradient = pwd*random.randint(10,100)
    xvals = []
    yvals = []
    for i in range(pts):
        n = random.randint(1000,10000)
        xvals.append(n)
        yvals.append(((n) * gradient) + pwd)

    return xvals, yvals

def main():
    pword = input("Enter a password to encrypt: ")
    pword = encryptWord(pword)
    numpoints = int(input("How many points to generate? "))
    if numpoints < 2:
        numpoints = 2
    xpts, ypts = createPoints(pword, numpoints)

    fi = open("pass.txt","w")
    for i in range(len(xpts)):
        fi.write(str(xpts[i]))
        fi.write(' ')
        fi.write(str(ypts[i]))
        fi.write('\n')
    fi.close()
    print("Sent to file (pass.txt)")
main()

您可能知道,Python 的內置int類型可以處理任意大的整數,但精度有限float類型。 處理不是int的數字的代碼的唯一部分似乎是這個函數:

def findYint(x,y):
    slope = (y[1] - y[0]) / (x[1] - x[0])
    yint = int(y[0] - slope * x[0])
    return yint

這里的除法結果為float ,即使結果與int完全相同。 此外,我們不能在這里使用//運算符安全地進行整數除法,因為slope將在截斷發生之前乘以x[0]

因此,要么您需要做一些代數以僅使用int獲得相同的結果,要么您需要使用精確的非整數類型表示分數 (y 1 - y 0 ) / (x 1 - x 0 )而不是float 幸運的是,Python 的標准庫有一個名為Fraction的類,它可以執行您想要的操作:

from fractions import Fraction

def findYint(x,y):
    slope = Fraction(y[1] - y[0], x[1] - x[0])
    yint = int(y[0] - slope * x[0])
    return yint

應該只能使用基於整數的數學來做到這一點:

def findYint(x,y):
    return (y[0] * (x[1] - x[0]) - (y[1] - y[0]) * x[0])  // (x[1] - x[0])

這樣您就可以避免浮點算術及其具有的精度限制。

所有整數數學的分數和重寫都很好。

對於真正的大整數,您可能會發現自己需要https://pypi.org/project/gmpy/而不是內置的 int 類型。 我已經成功地用它來測試大素數。

或者,如果您確實想要帶小數點的數字,可以嘗試 decimal.Decimal("1") - 僅作為示例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM