# How to overcome precision issue when cf/lucee is not strongly typed?

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.

There is a video of the Lucee Team telling about the function with some explanations and details:

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.

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.

https://www.webopedia.com/TERM/F/floating_point_number.html

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,.

interesting !