Login or Sign Up to become a member!
LessThanDot Sit Logo

LessThanDot

Data Management

Less Than Dot is a community of passionate IT professionals and enthusiasts dedicated to sharing technical knowledge, experience, and assistance. Inside you will find reference materials, interesting technical discussions, and expert tips and commentary. Once you register for an account you will have immediate access to the forums and all past articles and commentaries.

LTD Social Sitings

Lessthandot twitter Lessthandot Linkedin Lessthandot friendfeed Lessthandot facebook Lessthandot rss

Note: Watch for social icons on posts by your favorite authors to follow their postings on these and other social sites.

Your profile

    Search

    XML Feeds

    Google Ads

    « SQL Server Application and Multi-Server Management Private CTPSecuring your password for SQL Server 2005 and 2008 and more »
    comments

    This probably falls under the category of 'Why bother'. However, there has been some recent interest in calculating arbitrarily large fibonacci numbers. There is nothing particularly difficult about calculating these numbers until you reach the maximum number that a bigint (or decimal) can hold. With Fibonacci numbers, you reach this limit pretty fast. There's nothing particularly difficult about calculating this sequence, it merely involves adding 2 numbers together. But, since we run in to the data type limit, we need to start thinking outside the box.

    Obviously, we cannot store the numbers in any sort of number data type, so we need to use strings instead. Then, we need to create a way to add strings together as though they were numbers. This is the real challenge with calculating large numbers, but it's really not that difficult either. We'll simply write a function that adds 2 strings together as though they were numbers.

    Please understand that this is not production quality code. I'm not validating the inputs and I'm being careless about the data type conversions. Also note that I use the varchar(max) data type. This implies SQL2005 code. If you want to test this on SQL2000, then you'll need to replace varchar(max) with VarChar(8000). You won't be able to calculate as many numbers, but you'll still get quite a few.

    1. Create Function dbo.AddString(@String1 VarChar(8000), @String2 VarChar(8000))
    2. Returns VarChar(max)
    3. As
    4. Begin
    5.     Declare @CarryTheOne int
    6.     Declare @i Int
    7.     Declare @Output VarChar(max)
    8.     Declare @Digit1 Int
    9.     Declare @Digit2 int
    10.  
    11.     If Len(@String1) < Len(@String2)
    12.         select @String1 = Replace(Right(Space(Len(@String2)) + @String1, Len(@String2)), ' ', '0')
    13.     Else
    14.         select @String2 = Replace(Right(Space(Len(@String1)) + @String2, Len(@String1)), ' ', '0')
    15.  
    16.     set @CarryTheOne = 0
    17.     Set @i = 0
    18.     Set @Output = ''
    19.  
    20.     While @i < Len(@String1)
    21.         Begin
    22.             Set @Digit1 = SubString(@String1, Len(@String1) - @i, 1)
    23.             Set @Digit2 = SubString(@String2, Len(@String1) - @i, 1)
    24.            
    25.             Select @Output = Convert(VarChar(max), (@Digit1 + @Digit2 + @CarryTheOne) % 10) + @Output
    26.             If @Digit1 + @Digit2 + @CarryTheOne > 9
    27.                 Set @CarryTheOne = 1
    28.             Else
    29.                 Set @CarryTheOne = 0
    30.        
    31.             Set @i = @i + 1
    32.    
    33.         End
    34.    
    35.     If @CarryTheOne = 1
    36.         Set @Output = '1' + @Output
    37.    
    38.     Return @Output
    39. End

    The user defined function shown above allows us to add strings as though they were numbers. Now, how do we calculate the fibonacci series? Like this:

    1. Declare @Temp Table(Id Int Identity(1,1), FIB VarChar(max))
    2.  
    3. Insert Into @Temp(FIB) Values('0')
    4. Insert Into @Temp(FIB) Values('1')
    5.  
    6. Declare @i Int
    7. Select @i = Max(Id) From @Temp
    8.  
    9. While @i < 1000
    10.     Begin
    11.    
    12.         Insert Into @Temp(FIB)
    13.         Select dbo.AddString((Select Fib From @Temp Where Id = @i), (Select Fib From @Temp Where Id = @i-1))
    14.  
    15.         Set @i = @i + 1
    16.  
    17.     End
    18.  
    19. Select Fib From @Temp Order By Id

    That's all there is to it!

    About the Author

    George has been developing software professionally for 19 years, first for the department of defense, and then for various other companies. In 1998, George started his software company, Orbit Software, specializing in School Bus Transportation software. His specialty is refining SQL Server queries to deliver optimal performance.
    Social SitingsTwitterLTD RSS Feed
    Instapaper

    4 comments

    Comment from: Christiaan Baes (chrissie1) [Member]
    Christiaan Baes (chrissie1) Perhaps it would e intersting to hear how high people can make it go on their machine. in a reasonable amount of time.
    12/02/08 @ 14:53
    Comment from: Mike Hadlow [Visitor] · http://mikehadlow.blogspot.com
    *****
    Mike Hadlow Nice article, I did the same with 'when' and recursion:

    http://mikehadlow.blogspot.com/2007/11/t-sql-fibonacci-and-power-of.html
    12/03/08 @ 08:25
    Comment from: George Mastros (gmmastros) [Member]
    George Mastros (gmmastros) Mike,

    Thanks for the comment, but I think you missed the point of my blog. Your code limits you to the max number an int allows. It's easily converted to bigint, but you are still limited to calculating the first 88 fibonacci numbers. This code, because it uses string arithmetic, has no such limit.
    12/03/08 @ 08:40
    Comment from: Erik [Member] Email
    *****
    Erik I made my own addstring function just because I could and it was fun:

    CREATE FUNCTION dbo.AddStringErik(@String1 VARCHAR(8000), @String2 VARCHAR(8000))
    RETURNS VARCHAR(MAX)
    AS
    BEGIN
    DECLARE
    @i int,
    @v int,
    @OUTPUT VARCHAR(MAX)
    SET @v = 0
    SET @OUTPUT = ''
    SELECT @i = (Max(a) + 8) / 9 * 9 FROM (SELECT Len(@String1) UNION ALL SELECT Len(@String2)) X (a)
    SET @String1 = REPLICATE('0', @i - Len(@String1)) + @String1
    SET @String2 = REPLICATE('0', @i - Len(@String2)) + @String2
    SET @i = @i - 8
    WHILE @i >= 1 BEGIN
    SET @v = Convert(int, Substring(@String1, @i, 9)) + Convert(int, Substring(@String2, @i, 9)) + @v / 1000000000
    SET @OUTPUT = Right(Replicate('0', 8) + Right(@v, 9), 9) + @OUTPUT
    SET @i = @i - 9
    END
    RETURN @OUTPUT
    END
    12/05/08 @ 12:04

    Leave a comment


    Your email address will not be revealed on this site.

    Your URL will be displayed.
    (Line breaks become <br />)
    (Name, email & website)
    (Allow users to contact you through a message form (your email will not be revealed.)