Python:模数运算符给出错误的结果

Python:模数运算符给出错误的结果,python,arrays,matrix,modulus,Python,Arrays,Matrix,Modulus,我是Python的新手,我正在尝试将Hill密码作为一个小项目来实现。我想我已经弄明白了逻辑,并且已经让加密部分工作了,但是,在解密部分,我面临着麻烦。特别是模算子。在下面的decrypt函数中,最后一行的第二行是出现问题的地方 import numpy as np import fractions as fr def decrypt(matrix, words): matrix=np.asmatrix(matrix) length = len(matrix) det_

我是Python的新手,我正在尝试将Hill密码作为一个小项目来实现。我想我已经弄明白了逻辑,并且已经让加密部分工作了,但是,在解密部分,我面临着麻烦。特别是模算子。在下面的decrypt函数中,最后一行的第二行是出现问题的地方

import numpy as np
import fractions as fr

def decrypt(matrix, words):
    matrix=np.asmatrix(matrix)
    length = len(matrix)
    det_matrix=int(round((np.linalg.det(matrix))%26))
    mult_inv=(abs(det_matrix*26)/fr.gcd(det_matrix,26))/26
    matrix_inv=(((np.linalg.inv(matrix)*np.linalg.det(matrix))%26)*mult_inv)%26
    words = words.lower()
    arr = np.array([ord(i) - ord('a') for i in words], dtype=int)
    decrypt_matrix=(np.asmatrix(matrix_inv)*(np.asmatrix(arr).transpose()))%26
    return decrypt_matrix
我对解密函数的输入是:

>>> matrix
[[6, 24, 1], [13, 16, 10], [20, 17, 15]]
>>> words
'poh'
计算完
det_矩阵
mult_inv
变量的值为25。因此,计算矩阵_inv的代码行将具有以下值(绝对正确):

数组
arr
将具有以下值:

>>> arr
array([15, 14,  7])
现在的问题是在执行表达式结果的模运算之前的下一行代码

matrix_inv*(np.asmatrix(arr).transpose())
是:

现在,如果我在上面的矩阵上执行模26,我应该得到如下输出

([[0.],[2.],[19.]]) 
但是,下面是我执行表达式时得到的结果

>>> (np.asmatrix(matrix_inv)*(np.asmatrix(arr).transpose()))%26
matrix([[ 26.],
     [  2.],
     [ 19.]])
我不明白为什么第一个元素计算不正确(260%26是0而不是26)!但是,其余两个元素已正确计算

非常感谢在这方面的任何帮助


p.S:我已经尝试在版本2.7.11和3.6.1上运行代码。两者都不起作用。

在Python3.5、Spyder
Python3.5.2 | Anaconda custom(64位)|(默认值,2016年7月5日,11:41:13)[MSC v.1900 64位(AMD64)]在win32上正常运行

matrix_inv = np.array([[  8.,   5.,  10.],
   [ 21.,   8.,  21.],
   [ 21.,  12.,   8.]])

matrix_inv
Out[182]: 
array([[  8.,   5.,  10.],
       [ 21.,   8.,  21.],
       [ 21.,  12.,   8.]])

arr = np.array([15, 14,  7])

arr
Out[184]: array([15, 14,  7])

(np.asmatrix(matrix_inv)*(np.asmatrix(arr).transpose()))%26
Out[185]: 
matrix([[  0.],
        [  2.],
        [ 19.]])
print(np.__version__)
1.11.1

问题是
det
是一个
numpy.float64
。您得到的可能是:

round(259.6 % 26) # -> round(25.600000000000023) -> 26.0
这项工作:

round(259.6) % 26  # 0
在解密结果中,您有:

dec = decrypt(matrix, words)
dec[0,0]      # 25.999999999989768
dec[0,0] % 26 # 25.999999999989768
它将仅显示为
26。


因为我对3x3矩阵的模逆感兴趣,所以我写了一些代码。。。也许这对你有用

import numpy as np
from itertools import product, cycle


def gcd_xy(a, b):
    '''
    extended euclidean algo: return (g, x, y): g = gcd(a, b); a*x + b*y = d.
    '''
    q, r = divmod(a, b)
    x, y, x1, y1 = 0, 1, 1, 0
    while r != 0:
        x1, y1, x, y = x, y, x1 - q*x, y1 - q*y
        b, (q, r) = r, divmod(b, r)
    return b, x, y


def mod_inv(e, n):
    '''
    return d == 1/e mod n or raise ValueError if e and n are not co-prime.
    '''
    g, d, _ = gcd_xy(e, n)
    if g != 1:
        msg = '{} has no inverse mod {}'.format(e, n)
        raise ValueError(msg)
    d %= n
    return d


def mod_inv_matrix(matrix, n):
    '''
    modular inverse of 3x3 matrix 
    '''

    inv = np.zeros((3, 3), dtype=int)

    det = round(np.linalg.det(matrix))
    det_inv = mod_inv(det, n)

    matrixT = matrix.T
    for (i, j), sign in zip(product(range(3), repeat=2), cycle((1, -1))):
        m = np.delete(np.delete(matrixT, i, axis=0), j, axis=1)
        inv[i, j] = sign * det_inv * round(np.linalg.det(m)) % n
    return inv


def hill_decrypt(matrix, words):

    matrix_inv = mod_inv_matrix(matrix, n=26)

    words = words.lower()
    arr = np.array([ord(i) - ord('a') for i in words], dtype=int)

    plain = (matrix_inv @ arr) % 26

    return plain

matrix = np.array([[6, 24, 1], [13, 16, 10], [20, 17, 15]], dtype=int)
words = 'poh'
dec = hill_decrypt(matrix, words)
print(dec)
对于模逆,也可以使用


我正在使用
2.7.11(v2.7.11:6D1B6A68F7752015年12月5日20:32:19)[MSC v.1500 32位(英特尔)]
我将升级版本并重试。谢谢也不适用于3.6.1
3.6.1(v3.6.1:69c0db5,2017年3月21日,18:41:36)[MSC v.1900 64位(AMD64)]
听起来像是可能的错误-必须让比我了解更多的人感兴趣才能挑出问题。到目前为止,我唯一尝试的是检查
(matrix@matrix_inv)%26=1
。不是…谢谢你!我要花点时间来消化。但是,当我提供4x4输入时,同样的逻辑(我已经写过的逻辑)可以工作,但不适用于这个3x3输入,这真的很奇怪!你不认为那只是偶然吗?(是的:我的答案并没有为一般的
n*n
矩阵提供解决方案)。我想是的。我想我会花更多的时间调查(并更好地理解)这个程序的奇怪行为。
dec = decrypt(matrix, words)
dec[0,0]      # 25.999999999989768
dec[0,0] % 26 # 25.999999999989768
import numpy as np
from itertools import product, cycle


def gcd_xy(a, b):
    '''
    extended euclidean algo: return (g, x, y): g = gcd(a, b); a*x + b*y = d.
    '''
    q, r = divmod(a, b)
    x, y, x1, y1 = 0, 1, 1, 0
    while r != 0:
        x1, y1, x, y = x, y, x1 - q*x, y1 - q*y
        b, (q, r) = r, divmod(b, r)
    return b, x, y


def mod_inv(e, n):
    '''
    return d == 1/e mod n or raise ValueError if e and n are not co-prime.
    '''
    g, d, _ = gcd_xy(e, n)
    if g != 1:
        msg = '{} has no inverse mod {}'.format(e, n)
        raise ValueError(msg)
    d %= n
    return d


def mod_inv_matrix(matrix, n):
    '''
    modular inverse of 3x3 matrix 
    '''

    inv = np.zeros((3, 3), dtype=int)

    det = round(np.linalg.det(matrix))
    det_inv = mod_inv(det, n)

    matrixT = matrix.T
    for (i, j), sign in zip(product(range(3), repeat=2), cycle((1, -1))):
        m = np.delete(np.delete(matrixT, i, axis=0), j, axis=1)
        inv[i, j] = sign * det_inv * round(np.linalg.det(m)) % n
    return inv


def hill_decrypt(matrix, words):

    matrix_inv = mod_inv_matrix(matrix, n=26)

    words = words.lower()
    arr = np.array([ord(i) - ord('a') for i in words], dtype=int)

    plain = (matrix_inv @ arr) % 26

    return plain

matrix = np.array([[6, 24, 1], [13, 16, 10], [20, 17, 15]], dtype=int)
words = 'poh'
dec = hill_decrypt(matrix, words)
print(dec)
import gmpy
gmpy.invert(7, 26)