Factoral function

Just starting out? Need help? Post your questions and find answers here.
PB&J Lover
Enthusiast
Enthusiast
Posts: 212
Joined: Fri Apr 22, 2005 2:07 pm
Location: U.S.A.
Contact:

Factoral function

Post by PB&J Lover »

I'm trying to perfect a factoral function.

Code: Select all

Procedure.q Factoral(n.l)
If n >= 0
   If n > 0
      Define answer.q = 1
        While n > 0
          answer = answer * n
          n - 1   
        Wend
        ProcedureReturn answer
   Else
        ProcedureReturn 1
   EndIf
Else   
   ProcedureReturn -1
EndIf
EndProcedure
When I use a number greater than 20 I get an incorrect result (granted it is a very large number). How can I correct this so that it gives me correct results? Is there a way to deal with very large numbers?

Thanks. :shock:
-- DB

Any intelligent fool can make things bigger, more complex, and more violent. It takes a touch of genius — and a lot of courage — to move in the opposite direction.

Albert Einstein
Pupil
Enthusiast
Enthusiast
Posts: 715
Joined: Fri Apr 25, 2003 3:56 pm

Post by Pupil »

If i remember correctly Rings once did a big number lib, which uses strings to hold the numbers. This ofcourse comes with a penalty in speed as the calculations more or less needs to mimic the way it's done manually with pen and paper..

Maybe it's part of PBOSL now?
Helle
Enthusiast
Enthusiast
Posts: 178
Joined: Wed Apr 12, 2006 7:59 pm
Location: Germany
Contact:

Post by Helle »

For Fun:

Code: Select all

Procedure Factoral(n.l)

M = 2 * n
Dim P(2 * n) 

P(M) = 1

For I = 1 To M/2
    For F = M To 1 Step -1
       P(F) = P(F) * I
    Next F

    For F = M To 1 Step -1
       P(F-1) = P(F-1) + Int(P(F)/10)
       P(F) = P(F)-10 * Int(P(F)/10)
    Next F

    For F = 1 To M
      If P(F) = 0
         S = F
      EndIf
    
      If P(F) > 0
         F = M
      EndIf
    Next F

    For F = S + 1 To M
        Fak$ = Fak$ + Str(P(F))
    Next F

    Debug Str(I) + "!" + "   =   " + Fak$
    Fak$ = ""

Next I

EndProcedure 

Factoral(100)
Helle
Enthusiast
Enthusiast
Posts: 178
Joined: Wed Apr 12, 2006 7:59 pm
Location: Germany
Contact:

Post by Helle »

Possible a DIM-error in PB or in my head( :) ), this is correct for bigger numbers:

Code: Select all

Global Fak1$

Procedure Factoral(n)

M = 3 * n
Dim P(3 * n) 

P(M) = 1

For I = 1 To M/2
    For F = M To 1 Step -1
       P(F) = P(F) * I
    Next F

    For F = M To 1 Step -1
       P(F-1) = P(F-1) + Int(P(F)/10)
       P(F) = P(F)-10 * Int(P(F)/10)
    Next F

    For F = 1 To M
      If P(F) = 0
         S = F
      EndIf
    
      If P(F) > 0
         F = M
      EndIf
    Next F

    For F = S + 1 To M
        Fak$ = Fak$ + Str(P(F))
    Next F

    If I = n
       Fak1$=Fak$
        Break  
    EndIf 
      
    Fak$ = ""

Next I
  
EndProcedure 

Factoral(1000)
Debug Fak1$
Gruss
Helle
PB&J Lover
Enthusiast
Enthusiast
Posts: 212
Joined: Fri Apr 22, 2005 2:07 pm
Location: U.S.A.
Contact:

Post by PB&J Lover »

This is great but what I'd like to know is, what is the largest number I could deal with in my original function. Is there a way get it do deal with larger (real) numbers and not output a string.

ps. Why did you declare a global variable and then reference it in the procedure. That's not a great practice. It is better if all the procedure variables are local and you use procedurereturn to pass the output back.

Thanks for the help though.

:D
-- DB

Any intelligent fool can make things bigger, more complex, and more violent. It takes a touch of genius — and a lot of courage — to move in the opposite direction.

Albert Einstein
Froggerprogger
Enthusiast
Enthusiast
Posts: 423
Joined: Fri Apr 25, 2003 5:22 pm
Contact:

Post by Froggerprogger »

@helle
great snippet !!

@PB&J Lover
the biggest number of a signed quad is
(2^63)-1 = 9.223.372.036.854.775.807
Therefore your code works up to
20! = 2.432.902.008.176.640.000, because
21! = 51.090.942.171.709.440.000 > (2^63)-1

Just for fun here's a lookuptable-version:

Code: Select all

Procedure.q Fac(n.l)
  Select n
    Case  0 : ProcedureReturn 1
    Case  1 : ProcedureReturn 1  
    Case  2 : ProcedureReturn 2
    Case  3 : ProcedureReturn 6
    Case  4 : ProcedureReturn 24
    Case  5 : ProcedureReturn 120
    Case  6 : ProcedureReturn 720
    Case  7 : ProcedureReturn 5040
    Case  8 : ProcedureReturn 40320
    Case  9 : ProcedureReturn 362880
    Case 10 : ProcedureReturn 3628800
    Case 11 : ProcedureReturn 39916800
    Case 12 : ProcedureReturn 479001600
    Case 13 : ProcedureReturn 6227020800
    Case 14 : ProcedureReturn 87178291200
    Case 15 : ProcedureReturn 1307674368000
    Case 16 : ProcedureReturn 20922789888000
    Case 17 : ProcedureReturn 355687428096000
    Case 18 : ProcedureReturn 6402373705728000
    Case 19 : ProcedureReturn 121645100408832000
    Case 20 : ProcedureReturn 2432902008176640000
    Default : ProcedureReturn -1
  EndSelect
EndProcedure
%1>>1+1*1/1-1!1|1&1<<$1=1
Post Reply