如何解决计算有限域中的公式
我正在尝试将公式转换为该公式的有限域等效项。
现在我已经实现了它并且它可以正常工作,但是我需要在有限域中使用它,这意味着我引入了 p,假设 p = 183269
并取 {{1 }} 但是上面的公式究竟是如何变化的呢?正常计算完公式后,我是否只需mod p
?
示例:
我有多项式:mod p
我生成了 6 个随机点:f(x) = 1234 + 631x + 442x^2
(x,f(x) mod p)
现在,我想要的是使用上述公式重构 1234 给定任意 3 个点,但它给了我不正确的值。
这是我的代码:
1. (108,93338)
2. (413,146507)
3. (260,171647)
4. (819,98605)
5. (359,13237)
6. (894,118490)
我正在尝试实施 SSSS
编辑
正如 // x_input = [108,413,260]
var reconstructed float64 = 0.0
for _,k := range x_input {
var y float64 = float64(points[k])
var pr_x float64 = 1.0
for _,l := range x_input {
if l != k {
var aux_k float64 = float64(k)
var aux_l float64 = float64(l)
pr_x *= (aux_l / (aux_l - aux_k))
}
}
y *= pr_x
reconstructed += y
}
所指出的,我的代码和对有限域的理解有一些错误。我设法重写了我的公式,它看起来像这样:
@user58697
不幸的是,它仍然有一个或多个错误,因为它不会产生 reconstructed := 0
for _,k := range x_input {
y := points[k]
pr_x := 1
for _,l := range x_input {
if l != k {
inv := mod_inverse(l - k,p)
pr_x *= inv
}
}
y *= pr_x
reconstructed += y
}
return reconstructed % p
func mod_inverse(a,p int) int {
if a < 0 { // negative numbers are not allowed
a = a * -1
}
for i := 1; i < p; i++ {
if ((a % p) * (i % p)) % p == 1 {
return i
}
}
return p
}
解决方法
在我正常计算完公式后,我是否只是对 p 进行了修改?
没有。首先,您必须计算 x[m] - x[j]
模 p
的乘法逆。这是有效实施的棘手部分。其余的确实只是乘法和求和模 p
。
请记住,浮点运算不能在有限域中工作。在整数意义上,那里的一切都是精确的。
PS:为了解决对除法的担忧,这是除法在有限域中的工作方式:
y/x
实际上是 y * z
,其中 z
是 x
的乘法倒数,即 x * z = 1 mod p
。例如,让我们对 p
使用 7。乘法倒数,比如说 2 是 4:2 * 4 == 8 (== 1 mod 7)
。这意味着 3/2 mod 7
是 3 * 4 mod 7
,即 5
。
您应该记住,在两个数字相乘后始终对结果求模。如果 a*b*c
为 a<p,b<p,c<p
,p=183269
会导致 int 溢出。如果 p
较大(如 998244353
),a*b
只会导致溢出。对于这种情况,在将两个数字 a
和 b
相乘之前,您应该将它们转换为 int64
并将结果除以 p
,最后将其转换回 {{1} }.
这里还有一点:当模 int
时,a
并不总是等同于 -a
。实际上,在大多数情况下这是错误的。您应该改用 p
。
以下是可以产生正确结果的修改后的代码(我刚刚为这个问题学习了golang,所以请原谅我可能的代码不正确):
a = (a % p + p) % p
reconstructed := 0
for _,k := range x_input {
y := points[k]
pr_x := 1
for _,l := range x_input {
if l != k {
inv := mod_inverse(l - k,p)
// You forgot to multiply pr_x by l
// pr_x *= inv
pr_x = pr_x * inv % p * l % p
}
}
y = y * pr_x % p
reconstructed += y
}
return reconstructed % p
顺便说一句,func mod_inverse(a,p int) int {
if a < 0 { // negative numbers are not allowed
// The following line is wrong! (a % p) == (a % p + p) % p when a < 0,but not -a
// a = a * -1
a = ((a % p) + p) % p
}
for i := 1; i < p; i++ {
if ((a % p) * (i % p)) % p == 1 {
return i
}
}
// I suspect whether you should report an error here instead of returning p
return p
}
的时间复杂度是 mod_inverse
,在大多数情况下效率很低。您可以使用 Extended Euclidean Algorithm 在 O(p)
时间内计算 x
模 p
的乘法逆。此外,当 O(log p)
为素数时,x
模 p
的乘法逆只是 (x^(p-2)) % p
,您可以使用 Exponentiation by squaring 快速计算。这两种方法都有 p
复杂性,但后者更容易实现。
对不起,我的英语不好。随时指出我的错别字和错误。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。