Swift与Python的模运算差异

Swift与Python的模运算差异,python,swift,modulo,modular-arithmetic,Python,Swift,Modulo,Modular Arithmetic,我试图将模块化逆运算从Python移植到Swift,而我的模块化运算产生了不同的结果我想知道是否有人能指出为什么我会得到不同的结果?我正在使用BInt库 PYTHON代码: def inverse(x, p): """ Calculate the modular inverse of x ( mod p ) the modular inverse is a number such that: (inverse(x, p) * x) % p == 1 you could think o

我试图将模块化逆运算从Python移植到Swift,而我的模块化运算产生了不同的结果我想知道是否有人能指出为什么我会得到不同的结果?我正在使用BInt库

PYTHON代码:

def inverse(x, p):
"""
Calculate the modular inverse of x ( mod p )

the modular inverse is a number such that:

(inverse(x, p) * x) % p  ==  1 

you could think of this as: 1/x
"""
inv1 = 1
inv2 = 0
print "first x = %d" % x
print "first p = %d" % p
while p != 1 and p!=0:
    inv1, inv2 = inv2, inv1 - inv2 * (x / p)
    print "inv1 = %d" % inv1
    print "inv2 = %d" % inv2
    x, p = p, x % p
    print "x = %d" % x
    print "p = %d" % p

return inv2
func inverse(b: BInt, n: BInt) -> BInt {

    var inv1 = BInt(1)
    var inv2 = BInt(0)
    var p = n
    var x = b
    print("first x = \(x)")
    print("first p = \(p)")
    while p != 1 && p != 0 {
        var temp = inv2
        inv2 = inv1 - inv2 * (x/p)
        inv1 = temp
        print("inv1 = \(inv1)")
        print("inv2 = \(inv2)")
        temp = p
        p = x % p
        x = temp
        print("x = \(x)")
        print("p = \(p)")
    }
    return inv2
}
first x = -34499628904269660561674201530767158034393542375844615658184142552908072257357
first p = 115792089237316195423570985008687907853269984665640564039457584007908834671663
inv1 = 0
inv2 = 1
x = 115792089237316195423570985008687907853269984665640564039457584007908834671663
p = 81292460333046534861896783477920749818876442289795948381273441455000762414306
inv1 = 1
inv2 = -1
x = 81292460333046534861896783477920749818876442289795948381273441455000762414306
p = 34499628904269660561674201530767158034393542375844615658184142552908072257357
inv1 = -1
inv2 = 3
x = 34499628904269660561674201530767158034393542375844615658184142552908072257357
p = 12293202524507213738548380416386433750089357538106717064905156349184617899592
first x = -34499628904269660561674201530767158034393542375844615658184142552908072257357
first p = 115792089237316195423570985008687907853269984665640564039457584007908834671663
inv1 = 0
inv2 = 1
x = 115792089237316195423570985008687907853269984665640564039457584007908834671663
p = -34499628904269660561674201530767158034393542375844615658184142552908072257357
inv1 = 1
inv2 = 3
x = -34499628904269660561674201530767158034393542375844615658184142552908072257357
p = 12293202524507213738548380416386433750089357538106717064905156349184617899592
inv1 = 3
inv2 = 7
x = 12293202524507213738548380416386433750089357538106717064905156349184617899592
p = -9913223855255233084577440697994290534214827299631181528373829854538836458173
SWIFT代码:

def inverse(x, p):
"""
Calculate the modular inverse of x ( mod p )

the modular inverse is a number such that:

(inverse(x, p) * x) % p  ==  1 

you could think of this as: 1/x
"""
inv1 = 1
inv2 = 0
print "first x = %d" % x
print "first p = %d" % p
while p != 1 and p!=0:
    inv1, inv2 = inv2, inv1 - inv2 * (x / p)
    print "inv1 = %d" % inv1
    print "inv2 = %d" % inv2
    x, p = p, x % p
    print "x = %d" % x
    print "p = %d" % p

return inv2
func inverse(b: BInt, n: BInt) -> BInt {

    var inv1 = BInt(1)
    var inv2 = BInt(0)
    var p = n
    var x = b
    print("first x = \(x)")
    print("first p = \(p)")
    while p != 1 && p != 0 {
        var temp = inv2
        inv2 = inv1 - inv2 * (x/p)
        inv1 = temp
        print("inv1 = \(inv1)")
        print("inv2 = \(inv2)")
        temp = p
        p = x % p
        x = temp
        print("x = \(x)")
        print("p = \(p)")
    }
    return inv2
}
first x = -34499628904269660561674201530767158034393542375844615658184142552908072257357
first p = 115792089237316195423570985008687907853269984665640564039457584007908834671663
inv1 = 0
inv2 = 1
x = 115792089237316195423570985008687907853269984665640564039457584007908834671663
p = 81292460333046534861896783477920749818876442289795948381273441455000762414306
inv1 = 1
inv2 = -1
x = 81292460333046534861896783477920749818876442289795948381273441455000762414306
p = 34499628904269660561674201530767158034393542375844615658184142552908072257357
inv1 = -1
inv2 = 3
x = 34499628904269660561674201530767158034393542375844615658184142552908072257357
p = 12293202524507213738548380416386433750089357538106717064905156349184617899592
first x = -34499628904269660561674201530767158034393542375844615658184142552908072257357
first p = 115792089237316195423570985008687907853269984665640564039457584007908834671663
inv1 = 0
inv2 = 1
x = 115792089237316195423570985008687907853269984665640564039457584007908834671663
p = -34499628904269660561674201530767158034393542375844615658184142552908072257357
inv1 = 1
inv2 = 3
x = -34499628904269660561674201530767158034393542375844615658184142552908072257357
p = 12293202524507213738548380416386433750089357538106717064905156349184617899592
inv1 = 3
inv2 = 7
x = 12293202524507213738548380416386433750089357538106717064905156349184617899592
p = -9913223855255233084577440697994290534214827299631181528373829854538836458173
Python结果:

def inverse(x, p):
"""
Calculate the modular inverse of x ( mod p )

the modular inverse is a number such that:

(inverse(x, p) * x) % p  ==  1 

you could think of this as: 1/x
"""
inv1 = 1
inv2 = 0
print "first x = %d" % x
print "first p = %d" % p
while p != 1 and p!=0:
    inv1, inv2 = inv2, inv1 - inv2 * (x / p)
    print "inv1 = %d" % inv1
    print "inv2 = %d" % inv2
    x, p = p, x % p
    print "x = %d" % x
    print "p = %d" % p

return inv2
func inverse(b: BInt, n: BInt) -> BInt {

    var inv1 = BInt(1)
    var inv2 = BInt(0)
    var p = n
    var x = b
    print("first x = \(x)")
    print("first p = \(p)")
    while p != 1 && p != 0 {
        var temp = inv2
        inv2 = inv1 - inv2 * (x/p)
        inv1 = temp
        print("inv1 = \(inv1)")
        print("inv2 = \(inv2)")
        temp = p
        p = x % p
        x = temp
        print("x = \(x)")
        print("p = \(p)")
    }
    return inv2
}
first x = -34499628904269660561674201530767158034393542375844615658184142552908072257357
first p = 115792089237316195423570985008687907853269984665640564039457584007908834671663
inv1 = 0
inv2 = 1
x = 115792089237316195423570985008687907853269984665640564039457584007908834671663
p = 81292460333046534861896783477920749818876442289795948381273441455000762414306
inv1 = 1
inv2 = -1
x = 81292460333046534861896783477920749818876442289795948381273441455000762414306
p = 34499628904269660561674201530767158034393542375844615658184142552908072257357
inv1 = -1
inv2 = 3
x = 34499628904269660561674201530767158034393542375844615658184142552908072257357
p = 12293202524507213738548380416386433750089357538106717064905156349184617899592
first x = -34499628904269660561674201530767158034393542375844615658184142552908072257357
first p = 115792089237316195423570985008687907853269984665640564039457584007908834671663
inv1 = 0
inv2 = 1
x = 115792089237316195423570985008687907853269984665640564039457584007908834671663
p = -34499628904269660561674201530767158034393542375844615658184142552908072257357
inv1 = 1
inv2 = 3
x = -34499628904269660561674201530767158034393542375844615658184142552908072257357
p = 12293202524507213738548380416386433750089357538106717064905156349184617899592
inv1 = 3
inv2 = 7
x = 12293202524507213738548380416386433750089357538106717064905156349184617899592
p = -9913223855255233084577440697994290534214827299631181528373829854538836458173
Swift结果:

def inverse(x, p):
"""
Calculate the modular inverse of x ( mod p )

the modular inverse is a number such that:

(inverse(x, p) * x) % p  ==  1 

you could think of this as: 1/x
"""
inv1 = 1
inv2 = 0
print "first x = %d" % x
print "first p = %d" % p
while p != 1 and p!=0:
    inv1, inv2 = inv2, inv1 - inv2 * (x / p)
    print "inv1 = %d" % inv1
    print "inv2 = %d" % inv2
    x, p = p, x % p
    print "x = %d" % x
    print "p = %d" % p

return inv2
func inverse(b: BInt, n: BInt) -> BInt {

    var inv1 = BInt(1)
    var inv2 = BInt(0)
    var p = n
    var x = b
    print("first x = \(x)")
    print("first p = \(p)")
    while p != 1 && p != 0 {
        var temp = inv2
        inv2 = inv1 - inv2 * (x/p)
        inv1 = temp
        print("inv1 = \(inv1)")
        print("inv2 = \(inv2)")
        temp = p
        p = x % p
        x = temp
        print("x = \(x)")
        print("p = \(p)")
    }
    return inv2
}
first x = -34499628904269660561674201530767158034393542375844615658184142552908072257357
first p = 115792089237316195423570985008687907853269984665640564039457584007908834671663
inv1 = 0
inv2 = 1
x = 115792089237316195423570985008687907853269984665640564039457584007908834671663
p = 81292460333046534861896783477920749818876442289795948381273441455000762414306
inv1 = 1
inv2 = -1
x = 81292460333046534861896783477920749818876442289795948381273441455000762414306
p = 34499628904269660561674201530767158034393542375844615658184142552908072257357
inv1 = -1
inv2 = 3
x = 34499628904269660561674201530767158034393542375844615658184142552908072257357
p = 12293202524507213738548380416386433750089357538106717064905156349184617899592
first x = -34499628904269660561674201530767158034393542375844615658184142552908072257357
first p = 115792089237316195423570985008687907853269984665640564039457584007908834671663
inv1 = 0
inv2 = 1
x = 115792089237316195423570985008687907853269984665640564039457584007908834671663
p = -34499628904269660561674201530767158034393542375844615658184142552908072257357
inv1 = 1
inv2 = 3
x = -34499628904269660561674201530767158034393542375844615658184142552908072257357
p = 12293202524507213738548380416386433750089357538106717064905156349184617899592
inv1 = 3
inv2 = 7
x = 12293202524507213738548380416386433750089357538106717064905156349184617899592
p = -9913223855255233084577440697994290534214827299631181528373829854538836458173

也许您应该提到您在Swift中使用的大整数库,
BInt
不是标准库类型。快速实验:Swift中的
-2%5
是什么-2还是3?如果它是-2,这可能解释了这种差异(虽然确切地说这并不明显)。
-2%5=-2
在Swift:,但我不知道大整数库是如何计算的。根据PARI/GP,对于模数
1157920892373161954235709850086879078532699846656640564039457584007908834671663
,模数
1157920892373161955667675667439354237584461568184142552908072257357
的模逆是
3773201645528448156445462841640885215622248208227004528229572406827
,我在Swift实现中,在
x=temp
之后添加了
如果p<0{p+=x}
,那么viola的结果与Python相同。我不能说这是否解释了余数与模的差异,但我会做更多的测试用例,如果我们没有完全解决这个问题,我们似乎走上了正确的道路