Using ColdFusion's PrecisionEvaluate() Function To Perform Big Integer Math

Posted October 27, 2010 at 9:56 AM by Ben Nadel

Tags: ColdFusion

Did you know that ColdFusion has a function named PrecisionEvaluate()? Neither did I. I randomly came across it the other day when I was looking up information about ColdFusion's integer division operator. PrecisionEvaluate() works exactly like the Evaluate() function except for that it uses BigInteger objects when performing mathematical operations.

Before we look at how the precisionEvaluate() function works, let's take a look at the normal behavior of big integer math in ColdFusion:

  • <!---
  • Create two numbers that are too large to be signed integers in
  • ColdFusion. These are strings now, so shouldn't pose a problem
  • until we try to do math with them.
  • --->
  • <cfset hugeNumberA = repeatString( "1", 32 ) />
  • <cfset hugeNumberB = repeatString( "2", 32 ) />
  •  
  • <!--- Perform huge integer math! Mwaa ha ha ha ha! --->
  • <cfoutput>
  •  
  • Number A: #hugeNumberA#<br />
  • Number B: #hugeNumberB#<br />
  •  
  • Sum: #(hugeNumberA + hugeNumberB)#<br />
  • Product: #(hugeNumberA * hugeNumberB)#
  •  
  • </cfoutput>

As you can see, I'm using signed integers larger than 31 bits (the largest integer that ColdFusion can properly model with precision). When we run the above code, forcing the huge number "strings" to become "numbers", we get the following output:

Number A: 11111111111111111111111111111111
Number B: 22222222222222222222222222222222

Sum: 3.33333333333E+031
Product: 2.46913580247E+062

As you can see, the mathematical outcomes of the large number operations can only be held to a loose precision.

Now, let's do the same exact thing; however, this time, we are going to perform the mathematical operations in the context of the precisionEvaluate() function:

  • <!---
  • Create two numbers that are too large to be signed integers in
  • ColdFusion. These are strings now, so shouldn't pose a problem
  • until we try to do math with them.
  • --->
  • <cfset hugeNumberA = repeatString( "1", 32 ) />
  • <cfset hugeNumberB = repeatString( "2", 32 ) />
  •  
  • <!---
  • This time, we are going to perform math on the two numbers using
  • precisionEvaluate() which uses BigInteger objects to perform the
  • mathetmatical operations.
  • --->
  • <cfoutput>
  •  
  • Number A: #hugeNumberA#<br />
  • Number B: #hugeNumberB#<br />
  •  
  • Sum: #precisionEvaluate( hugeNumberA + hugeNumberB )#<br />
  • Product: #precisionEvaluate( hugeNumberA * hugeNumberB )#
  •  
  • </cfoutput>

As you can see, all we've done is wrapped our mathematical operations in a call to the precisionEvaluate() function. When we run this code, we get the following output:

Number A: 11111111111111111111111111111111
Number B: 22222222222222222222222222222222

Sum: 33333333333333333333333333333333
Product: 246913580246913580.......5308641975308641975308642

NOTE: I have removed a few digits to prevent wrapping on the blog.

This time, both the sum and product operations were able to preserve full precision.

One thing you might notice in the above code is that the statement we passed to the precisionEvaluate() function is not quoted. The documentation on this function states that if you're just performing arithmetic expressions, using non-quoted values will result in faster execution. I have to assume that this is a compile-time optimization since one would think that performing the math first would negate the use of precisionEvaluate().

After the precisionEvaluate() function executes, it returns a big decimal value that represents the result of the last expression evaluated (remember, the evaluate() functions can execute multiple statements). This result can then be used to perform further large number arithmetic; or, it can be used in standard math and will be converted back to a normal numeric value automatically.

To get a sense of what actually comes back from precisionEvaluate(), let's loop over the methods that are available on the resultant object:

  • <!--- Get the big integer result. --->
  • <cfset bigResult = precisionEvaluate( 3 * 3 ) />
  •  
  • <!--- Get the methods available on this result. --->
  • <cfset methods = bigResult.getClass().getMethods() />
  •  
  • <cfoutput>
  •  
  • <!--- Output the result's class type. --->
  • Class: #bigResult.getClass().getName()#<br />
  • <br />
  •  
  • <!--- Loop over each method to output it's name. --->
  • <cfloop
  • index="method"
  • array="#methods#">
  •  
  • #method.getName()#<br />
  •  
  • </cfloop>
  •  
  • </cfoutput>

This time, we are executing really simple math; however, our precisionEvaluate() method will use BigInteger values regardless. After performing the big integer math, we are outputting the resultant class type and its methods (NOTE: I have removed some duplicate method names):

Class: java.math.BigDecimal

add
equals
toString
hashCode
abs
pow
min
max
compareTo
valueOf
intValue
longValue
floatValue
doubleValue
signum
round
ulp
scale
subtract
multiply
divide
divideAndRemainder
remainder
negate
toBigInteger
scaleByPowerOfTen
unscaledValue
precision
divideToIntegralValue
plus
setScale
movePointLeft
movePointRight
stripTrailingZeros
toEngineeringString
toPlainString
toBigIntegerExact
longValueExact
intValueExact
shortValueExact
byteValueExact
byteValue
shortValue

As you can see, the result is a BigDecimal instance and provides all of the native BigDecimal methods.

Of course, you don't have to use the result as if it were a special class; you can simply use the result in further math and ColdFusion will convert it back to a native numeric value:

  • #(precisionEvaluate( 3 * 3 ) + 1)#

... which gives us the expected:

10

The BigInteger class has a lot of useful functionality; but, it's nice to know that ColdFusion provides a way to perform large number mathematical operations without having to dip into the Java layer. Now that I know this function is here, I am sure I will be able to find a good use for it.




Reader Comments

Oct 27, 2010 at 10:15 AM // reply »
70 Comments

Wow. This looks to be the EASIEST way to do BigIntegers. Thanks!


Oct 27, 2010 at 10:15 AM // reply »
2 Comments

What an interesting find. ColdFusion was difficult for me when I was first starting to learn it, and anything math makes me uncomfortable, so I read this post expecting to be made exceptionally uncomfortable (but I've learned, the only way you learn is to let yourself sit in those uncomfortable feelings). Instead, I found it super interesting and oddly comfortable. Will I ever do anything that needs it? Maybe not, but I know I could if I needed to, now. Who knew CF (and especially math) could do that :)


Oct 27, 2010 at 10:21 AM // reply »
10,743 Comments

@WebManWalking,

Yeah, this is super easy. I could also see myself very easily becoming lazy about creating BigInteger instances :) For example, it's way easier to do this:

  • <cfset x = precisionEvaluate( 1 ) />

... than it is to do this:

  • <cfset x = createObject( "java", "java.math.BigInteger" ).init(
  • javaCast( "string", 1 )
  • ) />

Of course the result of precisionEvaluate() is a BigDecimal, not a BigInteger; but still, you know what I'm saying.

@JJ,

I am super flattered that I was able to write about this in a way that allowed you to keep your cool :) That's exactly the kind of feeling that I want to create with my explorations.


Oct 27, 2010 at 12:28 PM // reply »
34 Comments

did i know about PrecisionEvaluate()? why yes i did ;-)

http://bit.ly/9Pjgjm


Oct 27, 2010 at 2:50 PM // reply »
10,743 Comments

@Paul,

Ha ha, awesome :)


May 6, 2012 at 12:32 PM // reply »
10 Comments

I actually didn't know about PrecisionEvaluate() till today! Greg Moser introduced it to me. We were looking at some simple math that rocked our world!

Try this for fun:

cfdump var="#89.95 + 13.29 eq 103.24#" ==> false

cfdump var="#PrecisionEvaluate(89.95 + 13.29) eq 103.24#" ==> true

This is math issue. Supposedly, there is only finite set of floating point values that can be represented by computers.

So, you can really never accurately do equality comparisons on FP values.

Good Read:
http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
InVision App - Prototyping Made Beautiful With Prototyping Tools Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 16, 2012 at 8:18 PM
Best Of ColdFusion 10 Contest Entry - HTML Email Utility
Just found this, looks good! I'm trying to run it on local, it's the 64bit version and I'm experiencing horrible lag. On average the generate.cfm processes the content change in 60-90 seconds. I've ... read »
May 16, 2012 at 6:40 PM
Maintaining Sessions Across Multiple ColdFusion CFHttp Requests
I am trying to integrate this CFHTTPsession into an application that will log into zeekrewards.com to post ads and I am not having any luck. The code works perfectly for logging into other websites, ... read »
May 16, 2012 at 2:44 PM
Creating A Sometimes-Fixed-Position Element With jQuery
Thank you, very useful technique! Worked like a charm. ... read »
May 16, 2012 at 1:58 PM
Movies As A Religious Experience
Acting can, in a way, ruin the movie-goer's experience. I used to be able to get so caught up in movies and their plots, and totally engaged. But lately, I haven't been able to as much with a lot o ... read »
May 16, 2012 at 1:52 PM
The Science Of Optimal Post-Exercise Nutrition
children of this age eat very less vegetables so u can opt for salads they will like it also carrot ,cucumber,onion and as far as pulses are concerned u can boil them ,give him along with mashed rice ... read »
May 16, 2012 at 1:34 PM
Strange ColdFusion JRUN Stack Overflow Error
Hey, Recently I updated my jrun4 using the latest updater 7 and now i am having memory issues :(:(:( any help is appreciated ... read »
May 16, 2012 at 9:56 AM
ColdFusion 10 Beta, Apache Tomcat, And Symbolic Links On Mac OSX
Hi, Now that ColdFusion 10 is out I have stumbled over this as well and I cannot figure out the proper solution. We're running virtual hosts via Apache2; the ColdFusion-applications store their fil ... read »
May 15, 2012 at 6:03 PM
Movies As A Religious Experience
@Ben, I don't know whether you'd consider this a religious observation, but it seems to me, in a sense, movies multiply how many lives we get to have. Each movie is like a little extra life we get ... read »