The following code in cfscript attempts to calculate probability of certain thing, please take a look at comment out original code as well.
<cfscript>
// function AttackerSuccessProbability(double q, int z) {
function AttackerSuccessProbability(q, z) {
// double p = 1.0 - q;
p = 1.0 - q;
// double lambda = z * (q / p);
lambda = z * (q / p);
// double sum = 1.0;
sum = 1.0;
// int i, k;
for (k = 0; k <= z; k++) {
// double poisson = exp(-lambda);
poisson = exp(-lambda);
for (i = 1; i <= k; i++)
poisson *= lambda / i;
// sum -= poisson * (1 - pow(q / p, z - k));
sum -= poisson * (1 - (q / p)^(z - k));
}
// return sum;
writeOutput(sum); writeOutput("<br>");
}
AttackerSuccessProbability(0.01,0);
AttackerSuccessProbability(0.01,1);
AttackerSuccessProbability(0.01,2);
AttackerSuccessProbability(0.01,3);
AttackerSuccessProbability(0.01,4);
AttackerSuccessProbability(0.01,5);
writeOutput("<br>");
AttackerSuccessProbability(0.03,0);
AttackerSuccessProbability(0.03,5);
AttackerSuccessProbability(0.03,10);
AttackerSuccessProbability(0.03,15);
AttackerSuccessProbability(0.03,20);
AttackerSuccessProbability(0.03,25);
</cfscript>
The above generates the following respective results:
1
0.020049659504
0.000501302822
0.000013032317
0.000000344131
0.000000009161
1
0.000002232864
0.000000000008
0
0
0
Expected respective results:
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
q=0.3 z=0
P=1.0000000
z=5
P=0.1773523
z=10
P=0.0416605
z=15
P=0.0101008
z=20
P=0.0024804
z=25 P=0.0006132
Question, is there a way to substitute the “double” type or another technique to achieve more accurate results with cf or lucee?
Thanks.
Give precisionEvaluate() a try.
HTH
– Denny
2 Likes
My Lucee 5.2.8.50 does not have this function, how can I try/use it? ACF 2018 failed, Lucee 5.x also failed.
andreas
September 18, 2019, 4:36am
4
There is a video of the Lucee Team telling about the function with some explanations and details:
Video about precisionEvaluate()
2 Likes
I corrected the syntax error of using precisionEvaluate function, now it ran, however, I received exact same results as without using this function. Probably the inability of defining a variable type such as double compromises calculation.
Thanks tho.
I highly doubt you’re having a precision error. Even your first one is off by a factor of 10. That’s not going to happen with datatype precision issues.
Consider the following java/groovy:
double asp(double q, double z) {
double p = 1.0 - q;
double lambda = z * (q / p);
double sum = 1.0;
for (int k = 0; k<= z; k++) {
double poisson = Math.exp(-lambda);
for (int i=1; i<=k; i++) poisson *= lambda/i;
sum -= poisson * (1 - Math.pow(q/p, z-k));
}
return sum
}
println asp(0.01,0);
println asp(0.01,1);
println asp(0.01,2);
println asp(0.01,3);
println asp(0.01,4);
println asp(0.01,5);
println asp(0.03,0);
println asp(0.03,5);
println asp(0.03,10);
println asp(0.03,15);
println asp(0.03,20);
println asp(0.03,25);
Which returns
1.0
0.020049659504318806
5.013028220883682E-4
1.3032317209471967E-5
3.441313628404327E-7
9.16142495488797E-9
1.0
2.23286394471924E-6
7.594443494968615E-12
4.114048166194166E-17
3.377117068551428E-17
5.670651046519856E-17
Which is what Lucee calculated.
Check your math.
Even better, notice that your CODE is off by a factor of 10.
You supplied the value 0.01 as q, but your expected results are for 0.1.
Can you output result such as the follwing
5.013028220883682E-4
into human readable format such as
0.020049659504318806
Thanks.
Sure
Change println asp(x,x); to printf(“%.20f\n”, asp(x,x));
0.01
1.00000000000000000000
0.02004965950431880600
0.00050130282208836820
0.00001303231720947197
0.00000034413136284043
0.00000000916142495489
.03
1.00000000000000000000
0.06044040671140482600
0.00453344350950214000
0.00035337426473033320
0.00002797576996010367
0.00000223286394471924
.1
1.00000000000000000000
0.20458727394278242000
0.05097789283933862000
0.01317224167889648200
0.00345524346648517360
0.00091368218792791220
But like I said, the problem isn’t with Lucee’s math. It’s that you provided the wrong arguments to your function. You want 0.1, not 0.01.
Any precision errors would be a loss of precision from the LEAST significant side, not the MOST significant side.
Using BigDecimal (i.e. precisionEvaluate) provides “infinite” precision… but even Lucee caps that at 20 decimal places.
2 Likes
You’re exactly right, I passed the parameter of 0.01 (wrong) instead of 0.1 (correct). Now, even without double type, we get almost good results.
Many thanks,.