我在测试中使用以下代码:
package main
import "fmt"
import "math/big"
func main() {
input := "3333333333333333333.......tested with 100'000x3 , tested with 1'000'0000x3, tested with 10'000'000x3"
bi := big.NewInt(0)
if _, ok := bi.SetString(input, 10); ok {
fmt.Printf("number = %v\n", bi)
testval := new(big.Int)
testval.SetString("3", 10)
resultat, isGanzzahl := myDiv(bi, testval)
fmt.Printf("isGanzzahl = %v, resultat = %v\n", isGanzzahl, resultat)
} else {
fmt.Printf("error parsing line %#v\n", input)
}
}
func myDiv(minuend *big.Int, subtrahend *big.Int) (*big.Int, bool) {
zerotest := big.NewInt(0)
modulus := new(big.Int)
modulus = modulus.Mod(minuend, subtrahend)
if zerotest.Cmp(modulus) == 0 {
res := big.NewInt(0)
res.Quo(minuend, subtrahend)
return res, true
} else {
return big.NewInt(0), false
}
}
我正在寻找一种让这种情况发生得更快的方法。如果我想在多线程中执行此操作,如何使用go-routines?是否有更快的方法进行更大数字的划分?
由于这仅用于测试,我计划使用100'000'000 -1,000'000'000位数的数字(这将是1GB的RAM使用)。但是10亿个数字不起作用,因为它需要数年才能完成。
如果是N / M会怎么样?其中N = 10亿位,M = 1000万位。这甚至可以在强大的家用电脑上使用吗?
如何将这项工作分发到多台小型计算机(例如AWS),我将如何看待?或者我需要做些什么?
答案 0 :(得分:3)
如果您的号码长度超过100000位,则需要使用快速傅里叶变换进行乘法和除法:https://en.wikipedia.org/wiki/Multiplication_algorithm#Fourier_transform_methods。基本思想是将数字视为多项式,x为10的幂(如果你想要二元系统,则为2的幂)。使用快速傅里叶变换乘以多项式,然后传播进位以从多项式获得数字。即如果我们需要将19乘以19并且我们使用x = 10 1 ,我们将得到(1 * x + 9)*(1 * x + 9)= x 2 + 18 * x + 81.现在我们传播进位将多项式转换回数:x 2 + 18 * x + 81 = x 2 +(18 + 8) * x + 1 = x 2 + 26 * x + 1 =(1 + 2)* x 2 + 6 * x + 1 = 3 * x 2 + 6 * x + 1 = 361.诀窍是多项式可以使用快速傅里叶变换有效地相乘(O(N * log(N)时间)。乘积多项式的系数大于数字,所以你需要仔细选择x,以避免整数溢出或精度问题。
不太可能有golang库,因此您需要自己编写。以下是一些可用作起点的短FFT实现:
http://codeforces.com/contest/632/submission/16449753 http://codeforces.com/contest/632/submission/16445979 http://codeforces.com/contest/632/submission/16449040 http://codeforces.com/contest/632/submission/16448169
如果你决定使用FFT模数素数,请参阅这篇文章,以便选择模数:http://petr-mitrichev.blogspot.com/2015/04/this-week-in-competitive-programming.html