Novick Software
SQL Server Consulting • Design • Programming • Tuning

  andy novick is a sql server mvp

 

 

SQL Server T-SQL User-Defined Function of the Week

Exploring the size of a bigint

Volume 1 Number 9   January 13, 2003

Sign up for this newsletter at:
http://www.novicksoftware.com/UdfOfWeek/UDFofWeekSignup.htm

This week's issue plays around with factorials to get a better 
feeling for the bigint data type.  The idea came from a
presentation that I did last week for the New England SQL Server
Users Group in Waltham, MA.  If you want to see the slides from 
the presentation or download the sample script you'll find it at
http://www.NovickSoftware.com/Presentations.htm

Just in case you haven't taken any math classes recently,
remember that N factorial is the product of all the integers up 
to and including N.  So 5 factorial is 1 * 2 * 3 * 4 * 5 or 120.

I had originally coded a UDF to return a table of factorials as
a way to illustrate the Multistatement Table Valued User-defined
Function.  Here's the original coding of that UDF:

/------------- Copy From Below this line ----------------------\
CREATE FUNCTION dbo.udf_FactorialsTAB (
        @N int
        )
    RETURNS @Factorials TABLE (Number INT, Factorial INT)
AS BEGIN
    DECLARE @I INT, @F INT
    SELECT @I = 1, @F = 1
    WHILE @I < = @N  BEGIN
        SET @F = @I * @F
        INSERT INTO @Factorials VALUES (@I, @F)
        SET @I = @I + 1
    END -- WHILE
    RETURN
END
GO
\------------ Stop copying above this line --------------------/

It works fine but shows the limitation of the int data type
pretty quickly.   First let's use it:

/------------- Copy From Below this line ----------------------\
SELECT * from udf_FactorialsTAB (12)
GO
\------------ Stop copying above this line --------------------/
(Results)
Number      Factorial   
----------- ----------- 
          1           1 
          2           2 
          3           6 
          4          24 
          5         120 
          6         720 
          7        5040 
          8       40320 
          9      362880 
         10     3628800 
         11    39916800 
         12   479001600 

It works up to 12 but 13 factorial goes beyond the capacity
of the int data type.  Let's try it:
/------------- Copy From Below this line ----------------------\
SELECT * from udf_FactorialsTAB (13)
GO
\------------ Stop copying above this line --------------------/
(Results)
Server: Msg 8115, Level 16, State 2, Procedure udf_FactorialsTAB,
 Line 9
Arithmetic overflow error converting expression to data type int.

So an INT is only able to calculate 12 factorial.

Now let's rewrite the function using the bigint data type for 
holding the factorial.  I've also changed the function name so 
that it fits into the _Num_ group of functions where I might
find it the next time I go looking for it.  Here's the 
CREATE FUNCTION script:
/------------- Copy From Below this line ----------------------\
CREATE FUNCTION dbo.udf_Num_FactorialTAB (
        @N bigint
        )
    RETURNS @Factorials TABLE (Number int, Factorial bigint)
/* Returns a table with the series of numbers and factorials */
AS BEGIN
    DECLARE @I int, @F bigint
    SELECT @I = 1, @F = CONVERT(bigint, 1)
    WHILE @I < = @N  BEGIN
        SET @F = CONVERT(bigint, @I) * @F
        INSERT INTO @Factorials (Number, Factorial) VALUES (@I, @F)
        SET @I = @I + 1
    END -- WHILE
    RETURN
END

GRANT EXEC on dbo.udf_Num_FactorialTAB TO PUBLIC
GO
\------------ Stop copying above this line --------------------/

I've tried it out so I know it works up to 20 factorial:
/------------- Copy From Below this line ----------------------\
SELECT * from udf_Num_FactorialTAB (20)
GO
\------------ Stop copying above this line --------------------/
(Results)
Number      Factorial            
----------- -------------------- 
          1                    1 
          2                    2 
          3                    6 
          4                   24 
          5                  120 
          6                  720 
          7                 5040 
          8                40320 
          9               362880 
         10              3628800 
         11             39916800 
         12            479001600 
         13           6227020800 
         14          87178291200 
         15        1307674368000 
         16       20922789888000 
         17      355687428096000 
         18     6402373705728000 
         19   121645100408832000 
         20  2432902008176640000
         
So we're able to go up to 20 factorial.  A pretty big number.
Of course, the numeric(38,0) or float data types will both 
hold larger numbers when needed.

In udf_NUM_FactorialTAB I used a loop to calculate the
factorials.  Factorial is a formula that also lends it self 
recursion.  I'll leave that for another issue.

+--------------------------------------------------------------+
Do you have a great UDF that you'd like to share?  Or maybe you
have a T-SQL problem that you think could be solved by a UDF
but you don't know how? Send them to:

UDF@NovickSoftware.com 

and they might be published in this newsletter.  I try and 
respond to every request that I get.  

Thanks,  
Andrew Novick
+--------------------------------------------------------------+


RSS as HTML

Personal Blog

 
New Tips:

Use dsinit to set the SQL Server instance for Windows Azure dev storage

Upcoming
Presentations:

Code Camp 14
Oct 2, 2010
Data Dude
SQL Azure


Full Schedule