我有static func createOrUpdate(dictionary:NSDictionary) -> Promise<Media> {
// Query and update from any thread
return Promise { fulfill, reject in
executeInBackground {
// c("BG media \(dictionary)")
let realm:RLMRealm = RLMRealm.defaultRealm()
realm.beginWriteTransaction()
let media = Media.createOrUpdateInRealm(realm, withJSONDictionary:dictionary as [NSObject : AnyObject])
// media.type = type
c("BG media \(media)")
let mediaId = media.localIdentifier
do {
try realm.commitWriteTransaction()
executeInForeground({
let mediaIdFG = mediaId.copy() as! String
let newMedia = Media.findOneByLocalIdentifier(mediaIdFG)
c("FG \(mediaIdFG) newMedia \(newMedia)")
fulfill(newMedia)
})
} catch {
reject( Constants.createError("Realm Something went wrong!") )
}
}
} // return promise
} // func createOrUpdate
形式的等式,其中a,b,c,d是大约1000位的已知数字,我需要求解n1。
我试过了:
a+b*n1=c+d*n2
,但这种方法对于这么大的数字来说太慢了。在这种情况下有没有更好的方法?
答案 0 :(得分:1)
您希望horizontal
和x
找到x = a (mod b)
。那么,x = c (mod d)
和n1 = (x - a) / b
。
如果n2 = (x - c) / d
和b
是互质的,则Chinese Remainder Theorem保证d
的存在 - 并且可以使用扩展欧几里得算法找到解决方案。
如果x
和b
不是互质(即d
},那么(注意gcd(b, d) != 1
),我们可以减去a = c (mod gcd(b, d))
从两边开始,按a % gcd(b, d)
划分,以减少上述问题。
以下是使用此方法查找gcd(b, d)
和n1
的代码:
n2
这里有一些测试代码可以运行1000个1000位输入的随机试验:
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def modinv(a, m):
return egcd(a, m)[1] % m
def solve(a, b, c, d):
gcd = egcd(b, d)[0]
if gcd != 1:
if a % gcd != c % gcd:
raise ValueError('no solution')
a, c = a - a % gcd, c - c % gcd
a //= gcd
b //= gcd
c //= gcd
d //= gcd
x = a * d * modinv(d, b) + c * b * modinv(b, d)
return (x - a) // b, (x - c) // d
(注意,递增限制必须增加,因为实现Extended Euclidean算法的import sys
sys.setrecursionlimit(10000)
import random
digit = '0123456789'
def rn(k):
return int(''.join(random.choice(digit) for _ in xrange(k)), 10)
k = 1000
for _ in xrange(1000):
a, b, c, d, = rn(k), rn(k), rn(k), rn(k)
print a, b, c, d
try:
n1, n2 = solve(a, b, c, d)
except ValueError, exn:
print 'no solution'
print
continue
if a + b * n1 != c + d * n2:
raise AssertionError('failed!')
print 'found solution:', n1, n2
print
函数是递归的,并且在1000位数字上运行它可能需要非常深的堆栈。
另请注意,这会在返回解决方案时检查结果。但是当一个!= c(mod gcd(b,d))并且引发了异常信号没有结果时,就不会进行检查。因此,当解决方案做存在时,您需要仔细考虑是否无法找到结果。
这在我的机器上大约7-8秒内运行(1000次试验),因此它的表现相当不错。