我正在尝试在python中复制一些C代码。
这是C代码。
#include <math.h>
double AttackerSuccessProbability(double q, int z)
{
double p = 1.0 - q;
double lambda = z * (q / p);
double sum = 1.0;
int i, k;
for (k = 0; k <= z; k++)
{
double poisson = exp(-lambda);
for (i = 1; i <= k; i++)
poisson *= lambda / i;
sum -= poisson * (1 - pow(q / p, z - k));
}
return sum;
}
C代码只是对此等式进行建模,取自Bitcoin's whitepaper
这是我在python中的尝试。
def BitcoinAttackerSuccessProbablity(q, z):
# probablity of honest finding the next node is 1 - probablity the attacker will find the next
p = 1 - q
# lambda is equal to the number of blocks times by the division of attacker and honest finding the next block
lam = z * (q / p)
sum = 1.0
i = 1
k = 0
while k <= z:
poisson = math.exp(-1 * lam)
while i <= k:
poisson = poisson * (lam / i)
i = i + 1
sum = sum - (poisson * (1 - ((q / p) ** (z - k))))
k = k + 1
print(sum)
for x in range(0,11):
BitcoinAttackerSuccessProbablity(0.1, x)
C代码的结果是。 (q和z是输入,而P是输出。)
q=0.1
z=0 P=1.0000000
z=1 P=0.2045873
z=2 P=0.0509779
z=3 P=0.0131722
z=4 P=0.0034552
z=5 P=0.0009137
z=6 P=0.0002428
z=7 P=0.0000647
z=8 P=0.0000173
z=9 P=0.0000046
z=10 P=0.0000012
我试图通过转换C代码在python中准确地复制这些结果。我的前3个结果(z = 0,-3)是正确的,但是,其余结果是不正确的。当我将while循环更改为C中的等效循环时,只有前两个结果正确。
我的Python代码的结果
1.0
0.20458727394278242
0.05097789283933862
-0.057596282822218514
-0.1508215598462347
-0.22737700216279746
-0.28610012088884856
-0.3272432217416562
-0.3519591169464781
-0.36186779773540745
-0.35878211836275675
我认为在语言之间处理循环的方法很简单。
非常感谢任何帮助
编辑:
这是第一次尝试
def BitcoinAttackerSuccessProbablity(q, z):
# probablity of honest finding the next node is 1 - probablity the attacker will find the next
p = 1 - q
#lambda is equal to the number of blocks times by the division of attacker and honest finding the next block
lam = z * (q/p)
sum = 1.0
for k in range(0, z):
poisson = math.exp(-1*lam)
for i in range(1, k):
poisson = poisson * (lam/i)
sum = sum - (poisson * (1 - ((q/p)**(z-k))))
print(sum)
答案 0 :(得分:2)
您不会在i
循环之前将while i <= k
重新初始化为零。
在Python中编写这个更惯用(更简短!)的方法是使用generator expression和sum()
函数来执行求和,以及使用{{1}函数而不是计算循环中的阶乘。使用这种方法,代码成为原始数学公式的非常直接的翻译:
math.factorial()
请注意,范围设置为def BitcoinAttackerSuccessProbablity(q, z):
# probablity of honest finding the next node is 1 - probablity the attacker
# will find the next
p = 1 - q
# lambda is equal to the number of blocks times by the division of attacker
# and honest finding the next block
lam = z * (q / p)
return 1 - sum(
(lam ** k) * math.exp(-lam) / math.factorial(k)
* (1 - (q / p) ** (z - k))
for k in range(0, z+1)
)
而不是range(0, z+1)
,因为Python范围不包含停止值。