Results 1 to 36 of 36

Thread: Factorial / Combination ??????????

  1. #1
    ashky
    Guest

    Question Factorial / Combination ??????????

    Why isn't there and math function in VB for finding the factorial of a number ??????

    Actually i need to find the following value:

    mCn , i.e, m choose n, and the formula for that is

    VB Code:
    1. mCn = m! / (m-n)! n!

    m factorial / (m-n) factorial * n factorial

    n and m always >=1 , How can this be done ???????

    Any ideas/codes/comments highly appreciated....,

    ashky.

  2. #2
    Frenzied Member HarryW's Avatar
    Join Date
    Jan 2000
    Location
    Heiho no michi
    Posts
    1,827
    Well, to help you, here's a factorial function using a dynamic programming approach. It can also be done recursively but it's a little less efficient, not that efficiency is very important when you're using VB.

    VB Code:
    1. Function Fact(x As Double) As Double
    2.     Dim i As Double
    3.     i = 1
    4.  
    5.     For i = 1 To x
    6.         i = i * x
    7.     Next x
    8.  
    9.     Fact = i
    10. End Function

    It uses Double datatypes for input and output because a standard 32-bit integer will only be large enough for values of around 12!. Doubles allow you to represent much larger values but only to a limited precision of around 15 significant figures.

    You can use that function to calculate your mCn value with a function like this:

    VB Code:
    1. Function mCn(m As Double, n as Double) As Double
    2.     mCn = Fact(m) / ( Fact (m - n) * Fact(n) )
    3. End Function
    That uses Doubles again but you will probably want to convert that back to an integer value if the range of your data will allow it. Some precision will be lost using Doubles, so you probably won't get an exact integer back, just one that's very close.
    Harry.

    "From one thing, know ten thousand things."

  3. #3
    Frenzied Member
    Join Date
    Jul 1999
    Location
    Huntingdon Valley, PA 19006
    Posts
    1,151
    To calculate N! / (N - R)! * R!, do not calculate 3 factorial values. Note the following.

    Number of possible poker hands with 52-card deck is the following.

    52! / 47! * 5! = 52*51*50*49*48 / 5*4*3*2*1

    The above is easier than calculating the three factorials. Using Doubles, you will probably get a correct integer result for the above, no matter how you do it.

    For other combination problems, it might be better to do something like the following.

    (52/5)*(51/4)*(50/3)*(49/2)*(48/1).

    If you round to an integer, you are likely to get the correct integer result for many nCm calculations. If you get tricky, you can get correct integer results for many of these problems, using just a little extra code and a little extra time.
    Live long & prosper.

    The Dinosaur from prehistoric era prior to computers.

    Eschew obfuscation!
    If a billion people believe a foolish idea, it is still a foolish idea!
    VB.net 2010 Express
    64Bit & 32Bit Windows 7 & Windows XP. I run 4 operating systems on a single PC.

  4. #4
    ashky
    Guest

    Question hai ????????

    Harry wrote:

    VB Code:
    1. Function Fact(x As Double) As Double
    2.                     Dim i As Double

    why can't we use ???????


    VB Code:
    1. Function Fact(x As Long) As Long
    2.                     Dim i As Long

    Pls comment on this .........,

    ashky.

    P.S: Thank you Harry and Guv for ur replies ....,

  5. #5
    Junior Member
    Join Date
    Jan 2002
    Location
    Netherlands
    Posts
    17
    A long can not have a decimal value assigned, a double can. If you don't want to use a double, you can always use the following :

    dim x as variant

    x=cdec(Somevalue)

    cdec is a 28 digit decimal value, but doesn't have the discomfort of scientific values (1+E1) and can only be assigned to variant values.

  6. #6
    wossname
    Guest
    This is a crime: dim x as variant

    Have you any idea how slow variants are?

    Anyway Harry's loop looks a bit odd to me. I've changed it a bit.
    VB Code:
    1. Function Fact(byval x As Long) As Double
    2.     Dim i As Double, j as Long
    3.     i=1
    4.     For j = 2 To x 'you don't need to start at 1, theres no point really
    5.         i = i * x
    6.     Next j
    7.  
    8.     Fact = i
    9. End Function

    I've not tested it but it looks about right to me.

    Plus I changed x to long (and added j as another long), factorials get bloody large very quickly and would easily cause an overflow way before we get into double territory! We may not even need to use longs, integer might be adequate for x and j.

  7. #7
    Frenzied Member
    Join Date
    Jul 1999
    Location
    Huntingdon Valley, PA 19006
    Posts
    1,151
    Robbert: Could you explain about not being able to assign a decimal value to a Long, but assigning to a Double is Okay. As far as I know the following code would display the same values in the Text Boxes.
    VB Code:
    1. Dim X As Long
    2. Dim Y As Double
    3.  
    4. X = 53698
    5. Y = 53698
    6.  
    7. TboxA.Text = Cstr(X)
    8. TboxB.Text = Cstr(Y)
    Internally, the values are binary rather than decimal, requiring conversion of decimal input to binary and later conversion back to decimal for output. In some instances, the conversions will result in the display of non integers (or extremely large integers) different from the input data.
    Live long & prosper.

    The Dinosaur from prehistoric era prior to computers.

    Eschew obfuscation!
    If a billion people believe a foolish idea, it is still a foolish idea!
    VB.net 2010 Express
    64Bit & 32Bit Windows 7 & Windows XP. I run 4 operating systems on a single PC.

  8. #8
    ashky
    Guest

    Question Factorial

    Hai,

    Thank you everyone for the replies, in the follwoing site link there were two functions to calculate the Factorial of a number. But they give an overflow error if the number is > 12. I am required to compute the factorial of numbers upto 99.

    Is there any other way to tackle this problem.....,

    How about using a variant datatype ?????
    VB Code:
    1. Function FactorialTheBoringWay(intNumber As Long) As Long
    2.    Dim i As Integer
    3.    Dim lngResult As Long
    4.    lngResult = 1
    5.    For i = 2 To intNumber
    6.       lngResult = lngResult * i
    7.    Next i
    8.    Factorial = lngResult
    9. End Function
    10.  
    11. Function FactorialRecursively(intNumber As Long) As Long
    12.    If intNumber = 1 Then
    13.       FactorialRecursively = 1
    14.    Else
    15.       FactorialRecursively = intNumber * FactorialRecursively(intNumber - 1)
    16.    End If
    17. End Function

    In addition to the above i need to compute this value, but the factorial is give me an overflow error ??????
    VB Code:
    1. Function mCn(m As Long, n as Long) As Long
    2.     mCn = Fact(m) / ( Fact (m - n) * Fact(n) )
    3. End Function
    Help me out by giving any ideas/comments/codes....,

    Thanks in advance....,

    ashky.

  9. #9
    Hyperactive Member thinktank2's Avatar
    Join Date
    Nov 2001
    Location
    Arctic
    Posts
    272
    99! is toooooo big

    99! = 9332621544394415268169923885626670049071596826438162146859296389521759999322991560894146397615651828 62536979208272237582511852109168640000000000000000000000

    No other data type than variant can be used.

    VB Code:
    1. Function mCn(m As Long, n As Long) As Variant
    2.     If n = 0 Or n = m Then
    3.         mCn = 1
    4.     ElseIf n > m Then
    5.         'go F@%*#! Error !!
    6.     Else
    7.         mCn = Factorial(m) / (Factorial(m - n) * Factorial(n))
    8.     End If
    9. End Function
    10.  
    11.  
    12. Function Factorial(intNumber As Long) As Variant
    13.    Dim i As Integer
    14.    Dim Result As Variant
    15.    Result = 1
    16.    For i = 2 To intNumber
    17.       Result = Result * i
    18.    Next i
    19.    Factorial = Result
    20. End Function

  10. #10
    transcendental analytic kedaman's Avatar
    Join Date
    Mar 2000
    Location
    0x002F2EA8
    Posts
    7,221

    Factorials grows more than exponentially

    In fact to calculate mCn you won't need factorials, most important you are limited to the hardware meaning CPU power.

    Guv Posted two approaches the first which is simplification of the the expression with factorials and the second which can handle larger values on n*m but is limited to floating point calculation.


    52! / 47! * 5! = 52*51*50*49*48 / 5*4*3*2*1

    (52/5)*(51/4)*(50/3)*(49/2)*(48/1).

    something like:
    Code:
    X=1
    for M=M-N to M
    X*=C/N //or X*=C and Y*=N and finally X/=Y for the first alternative
    M--
    next
    Use
    writing software in C++ is like driving rivets into steel beam with a toothpick.
    writing haskell makes your life easier:
    reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
    To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.

  11. #11
    Junior Member
    Join Date
    Jan 2002
    Location
    Netherlands
    Posts
    17
    Originally posted by Guv
    Robbert: Could you explain about not being able to assign a decimal value to a Long, but assigning to a Double is Okay. As far as I know the following code would display the same values in the Text Boxes.
    VB Code:
    1. Dim X As Long
    2. Dim Y As Double
    3.  
    4. X = 53698
    5. Y = 53698
    6.  
    7. TboxA.Text = Cstr(X)
    8. TboxB.Text = Cstr(Y)
    Internally, the values are binary rather than decimal, requiring conversion of decimal input to binary and later conversion back to decimal for output. In some instances, the conversions will result in the display of non integers (or extremely large integers) different from the input data.
    This works fine if the values are hole numbers, but try the same code with these numbers :

    x= 53698.23412334456
    y= 53698.23412334456

    The long value will only show the hole number, the double value will show everything.

  12. #12
    Frenzied Member HarryW's Avatar
    Join Date
    Jan 2000
    Location
    Heiho no michi
    Posts
    1,827
    Ashky, as I said previously, 32-bit integers overflow past 12!. This is because they have one 32-bit pattern for every single integer in the range -2,147,483,648 to +-2,147,483,647. They use a 2's complement binary representation, which is easily found on the net if you're intereted in the details.

    Doubles, on the other hand, are a little different. Doubles are 64-bit which gives them a much larger number of discrete values to begin with. They also represent numbers differently to integer variables. The data is stored in something a lot like standard form, but using a binary numbering system rather than decimal.

    What this means is that Doubles have a much greater range of values that they can represent, but with the drawback that they can lack precision. You may want to store the number 1234567890123456.1234567890 but in all likelihood this number will get rounded after it has been converted to binary, and will come out as a (slightly) different number when converted back into decimal.

    So, in short, doubles let you use much larger numbers than integers but lack some precision. If you want to store really huge numbers accurately, you really need to implement a new datatype that can fulfil your needs. Commonly people do this with string representations of numbers, and write their own functions to handle operations on these string-numbers, like addition and multiplication. There are probably a lot of these kinds of datatypes already written that you can just borrow and use in your app.

    Other than that you could use a language with a more scientific or mathematical bias that already handles this. Python, for instance, handles arbitrarily long numbers of any type (including complex numbers).



    wossname: You're right, my code was a bit messed up, oops. I didn't check it properly.


    Guv: I see that all these calculations aren't necessary, but how would you do it your way? Do you simplify the expression at run-time or does the expression reduce to something much simpler already? Either way, it's a neat approach.
    Harry.

    "From one thing, know ten thousand things."

  13. #13
    wossname
    Guest
    Originally posted by HarryW
    wossname: You're right, my code was a bit messed up, oops. I didn't check it properly.
    You were drunk right? Thats what my code looks like when I'm pissed too!

    I am curently developing a modified version of the BASIC syntax in a VB add-in, I'm calling it "VB for Alcoholics". It lets you gibber away to your hearts content, ignoring every single command you issue, replacing it with normal, sober and intelligent nothingness.

    You start and finish with an empty project, safe in the knowledge that in your drunken stupor, you haven't accidentally erased the server's tape drive or bitblitted a rude picture of the bosses wife to every monitor in the office.

    hehehe, j/k

  14. #14
    Frenzied Member
    Join Date
    Jul 1999
    Location
    Huntingdon Valley, PA 19006
    Posts
    1,151
    ThinkTank2: My HP calculator gave 9.332 621 544 39 E155, which agrees with the first 12 digits of your result. I did not count digits in your result, but assume it is correct. How did you obtain it?

    Ashky: If you use a Double instead of a Long, your code looks as though it should work.

    I do not understand the Kedaman code, but it is likely to work. He seldom makes mistakes in code or math, but often uses esoteric methods which confuse me. Something like the following should work for mCn (I did not test it, so caveat emptor).
    VB Code:
    1. Function mCn(m as Integer, n As Integer) As Double
    2. Dim Result As Double
    3. Dim J As Integer
    4.  
    5. If n > m Then
    6.     MsgBox(“n must not be greater than m”)
    7.     mCn = 0
    8.     Exit Function
    9.    End If
    10.  
    11. Result = m
    12.  
    13. For J = 2 to n
    14.     Result = Result * (m - J + 1) / J
    15.    Next J
    16.  
    17. mCn = Result
    18.  
    19. End Function
    Others: I do not understand the insistence on a Variant being the only way to go in VB. A Double will surely allow calculation of factorials a little beyond 175!. I personally avoid Variants. I generally know what my data looks like and choose the Data Type accordingly. There might be some reason for using a Variant to hold large decimal values, but I seldom need anything that cannot be stored in a Double.

    VB cannot hold more than 12! In a Long variable. A VB Double provides about 15 decimal digits of precision, which would allow an exact value of 17! (I think), but not much more.

    While a VB Double will not provide an exact value of 99! (Over 155 decimal digits), you can surely calculate an approximate value. My HP calculator will calculate factorials a little beyond 250! (About 490 decimal digits), with about 12 digit precision. The calculator floating point (like a VB Double) allows a larger exponent (up to 500) and less precision (about 12 decimal digits) than VB (308 & 15, respectively).
    Live long & prosper.

    The Dinosaur from prehistoric era prior to computers.

    Eschew obfuscation!
    If a billion people believe a foolish idea, it is still a foolish idea!
    VB.net 2010 Express
    64Bit & 32Bit Windows 7 & Windows XP. I run 4 operating systems on a single PC.

  15. #15
    transcendental analytic kedaman's Avatar
    Join Date
    Mar 2000
    Location
    0x002F2EA8
    Posts
    7,221
    : I do not understand the insistence on a Variant being the only way to go in VB. A Double will surely allow calculation of factorials a little beyond 175!. I personally avoid Variants. I generally know what my data looks like and choose the Data Type accordingly. There might be some reason for using a Variant to hold large decimal values, but I seldom need anything that cannot be stored in a Double.
    Variant datatype is an abstraction layer for all integrated types, classes and UDT's arrays of objects or integrated types but not arrays of UDT's for some freaky reason, and a set of types that cannot be created such as null, empty and error, and also Decimal, which is 96 bit integer(about 28 decimals) (achieved by casting a variant to CDEC() and then assigning a STRING to it) and also the largest integrated integer datatype in VB. Double's are 64 bit floating points and might often be best in physical, practical issues while mathematical or logical issues require exactness that floating points don't provide.

    I'm sorry about my code, haven't used VB for quite a while and i soon forget that there's no other assignment operators than =

    Code:
    Function mCn(m as Integer, n As Integer) As Double
    
    dim X as double,Y as double
    X=1
    Y=1
    for M=M-N to M
      X=X*C/N
      M=M-1
    next
    
    mCn=X
    End Function
    Code:
    Function mCn(m as Integer, n As Integer) As Double
    
    dim X as integer, Y as integer
    X=1
    Y=1
    for M=M-N to M
      X=X*C
      Y=Y*N
    M=M-1
    next
    
    X=X/Y
    
    mCn=X
    
    End Function
    And I do make mistakes, especially when I code without a compiler
    Use
    writing software in C++ is like driving rivets into steel beam with a toothpick.
    writing haskell makes your life easier:
    reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
    To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.

  16. #16
    pathfinder NotLKH's Avatar
    Join Date
    Apr 2001
    Posts
    2,397
    Originally posted by Guv
    ..... There might be some reason for using a Variant to hold large decimal values, but I seldom need anything that cannot be stored in a Double........ A VB Double provides about 15 decimal digits of precision, which would allow an exact value of 17! (I think), but not much more.......and less precision (about 12 decimal digits)
    I'm a little puzzled over the Emphasis on Decimal Precision when it comes to calculating Factorials {n!}. Surely when one calculates n!, you'll never return a decimal?

    {Hmmm, lets see, 5!, 5*4*3*2*1, nope, no decimal in sight! }

  17. #17
    Hyperactive Member thinktank2's Avatar
    Join Date
    Nov 2001
    Location
    Arctic
    Posts
    272
    Originally posted by Guv
    ThinkTank2: My HP calculator gave 9.332 621 544 39 E155, which agrees with the first 12 digits of your result. I did not count digits in your result, but assume it is correct. How did you obtain it?
    Mathematica !!!!

    Others: I do not understand the insistence on a Variant being the only way to go in VB. A Double will surely allow calculation of factorials a little beyond 175!. I personally avoid Variants........

    .....A VB Double provides about 15 decimal digits of precision, which would allow an exact value of 17! (I think), but not much more.
    I suspect a discrepancy

  18. #18
    DerFarm
    Guest
    You might want to try using logs instead of reals, integers, etc:


    Code:
    Function Factorial_as_Log(X As Integer) As Double
    '
    ' Non-recursive factorial, returning f as f=f+log(f)
    '
    Dim i As Integer, f As Double
          f = 0#
          For i = 2 To X
                f = f + Log(i)
          Next i
          Factorial_as_Log = f
    End Function

  19. #19
    Frenzied Member
    Join Date
    Jul 1999
    Location
    Huntingdon Valley, PA 19006
    Posts
    1,151
    Thinktank2: I envy your having Mathematica. I use MathCad 7, which is excellent, but not as good as Mathematica.

    I said the following.
    A VB Double will surely allow calculation of factorials a little beyond 175! . . . . A VB Double provides about 15 decimal digits of precision, which would allow an exact value for 17! (I think), but not much more . . .
    There is not really a discrepancy in the above, although I have discovered that overflow occurs with 175! (170! Is about the limit for a VB Double). 17! is approximately 3.55687E14, which is a 15 digit integer in decimal notation, allowing a VB Double to hold its precise value. 170! Is approximately 7.25742E306, which is a 307 digit integer. VB can compute an approximate value for 170!, but if converted to a 307 digit decimal value, only the first 15 digits would be correct.

    Note that 52! Is approximately 8.06582E67, which is a 68 digit decimal integer. While VB could not compute an exact integer value for 52!, a VB program could compute accurate probabilities relating to a standard 52-Card deck, even though such calculations might involve computation of 52!

    All: It seems that I have been using mathematical jargon rather than being college professor precise. I am sorry: I did not think this context required formal definitions.

    When specifying the precision of a value, the term decimal digits refers to the most significant digits of the value, not necessarily to the first six digits to the right of the radix point. In most contexts, decimal is assumed and omitted. In a computer context, one might specify the precision as a number of decimal, octal or hexidecimal digits, so decimal in decimal digits of precision refers to the radix, not the digits to the right of the radix point. One might refer to the velocity of light as 186,282 miles per second, and say that this value provides 6 decimal digits of precision, while the value 299,792.458 kilometers per second provides at least 8 decimal digits of precision (I am not sure about the 9th digit)
    Live long & prosper.

    The Dinosaur from prehistoric era prior to computers.

    Eschew obfuscation!
    If a billion people believe a foolish idea, it is still a foolish idea!
    VB.net 2010 Express
    64Bit & 32Bit Windows 7 & Windows XP. I run 4 operating systems on a single PC.

  20. #20
    pathfinder NotLKH's Avatar
    Join Date
    Apr 2001
    Posts
    2,397
    Can anybody confirm this for me?
    VB Code:
    1. 2000!= 331627509245063324117539338057632403828111720810578039457193543706038077905600822400273230859732592255402352941225834109258084817415293796131386633526343688905634058556163940605117252571870647856393544045405243957467037674108722970434684158343752431580877533645127487995436859247408032408946561507233250652797655757179671536718689359056112815871601717232657156110004214012420433842573712700175883547796899921283528996665853405579854903657366350133386550401172012152635488038268152152246920995206031564418565480675946497051552288205234899995726450814065536678969532101467622671332026831552205194494461618239275204026529722631502574752048296064750927394165856283531779574482876314596450373991327334177263608852490093506621610144459709412707821313732563831572302019949914958316470942774473870327985549674298608839376326824152478834387469595829257740574539837501585815468136294217949972399813599481016556563876034227312912250384709872909626622461971076605931550201895135583165357871492290916779049702247094611937607785165110684432255905648736266530377384650390788049524600712549402614566072254136302754913671583406097831074945282217490781347709693241556111339828051358600690594619965257310741177081519922564516778571458056602185654760952377463016679422488444485798349801548032620829890965857381751888619376692828279888453584639896594213952984465291092009103710046149449915828588050761867924946385180879874512891408019340074625920057098729578599643650655895612410231018690556060308783629110505601245908998383410799367902052076858669183477906558544700148692656924631933337612428097420067172846361939249698628468719993450393889367270487127172734561700354867477509102955523953547941107421913301356819541091941462766417542161587625262858089801222443890248677182054959415751991701271767571787495861619665931878855141835782092601482071777331735396034304969082070589958701381980813035590160762908388574561288217698136182483576739218303118414719133986892842344000779246691209766731651433494437473235636572048844478331854941693030124531676232745367879322847473824485092283139952509732505979127031047683601481191102229253372697693823670057565612400290576043852852902937606479533458179666123839605262549107186663869354766108455046198102084050635827676526589492393249519685954171672419329530683673495544004586359838161043059449826627530605423580755894108278880427825951089880635410567917950974017780688782869810219010900148352061688883720250310665922068601483649830532782088263536558043605686781284169217133047141176312175895777122637584753123517230990549829210134687304205898014418063875382664169897704237759406280877253702265426530580862379301422675821187143502918637636340300173251818262076039747369595202642632364145446851113427202150458383851010136941313034856221916631623892632765815355011276307825059969158824533457435437863683173730673296589355199694458236873508830278657700879749889992343555566240682834763784685183844973648873952475103224222110561201295829657191368108693825475764118886879346725191246192151144738836269591643672490071653428228152661247800463922544945170363723627940757784542091048305461656190622174286981602973324046520201992813854882681951007282869701070737500927666487502174775372742351508748246720274170031581122805896178122160747437947510950620938556674581252518376682157712807861499255876132352950422346387878954850885764466136290394127665978044202092281337987115900896264878942413210454925003566670632909441579372986743421470507213588932019580723064781498429522595589012754823971773325722910325760929790733299545056388362640474650245080809469116072632087494143973000704111418595530278827357654819182002449697761111346318195282761590964189790958117338627206088910432945244978535147014112442143055486089639578378347325323595763291438925288393986256273242862775563140463830389168421633113445636309571965978466338551492316196335675355138403425804162919837822266909521770153175338730284610841886554138329171951332117895728541662084823682817932512931237521541926970269703299477643823386483008871530373405666383868294088487730721762268849023084934661194260180272613802108005078215741006054848201347859578102770707780655512772540501674332396066253216415004808772403047611929032210154385353138685538486425570790795341176519571188683739880683895792743749683498142923292196309777090143936843655333359307820181312993455024206044563340578606962471961505603394899523321800434359967256623927196435402872055475012079854331970674797313126813523653744085662263206768837585132782896252333284341812977624697079543436003492343159239674763638912115285406657783646213911247447051255226342701239527018127045491648045932248108858674600952306793175967755581011679940005249806303763141344412269037034987355799916009259248075052485541568266281760815446308305406677412630124441864204108373119093130001154470560277773724378067188899770851056727276781247198832857695844217588895160467868204810010047816462358220838532488134270834079868486632162720208823308727819085378845469131556021728873121907393965209260229101477527080930865364979858554010577450279289814603688431821508637246216967872282169347370599286277112447690920902988320166830170273420259765671709863311216349502171264426827119650264054228231759630874475301847194095524263411498469508073390080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

    Just double checking a progie of mine.
    -Thanks
    -Lou

  21. #21
    transcendental analytic kedaman's Avatar
    Join Date
    Mar 2000
    Location
    0x002F2EA8
    Posts
    7,221
    those last zeroes seems suspicious
    Use
    writing software in C++ is like driving rivets into steel beam with a toothpick.
    writing haskell makes your life easier:
    reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
    To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.

  22. #22
    transcendental analytic kedaman's Avatar
    Join Date
    Mar 2000
    Location
    0x002F2EA8
    Posts
    7,221
    there should be a zero for each number ending with 5 or 0:2000/5=400
    There should be a zero for each number ending with 50 or 00: 2000/50=40
    There should be a zero for each number ending with 500 or 000: 2000/500=4
    now where are the missing 55?
    Use
    writing software in C++ is like driving rivets into steel beam with a toothpick.
    writing haskell makes your life easier:
    reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
    To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.

  23. #23
    Frenzied Member
    Join Date
    Jul 1999
    Location
    Huntingdon Valley, PA 19006
    Posts
    1,151
    Kedaman: Perhaps there are two zeros for each number ending in 50 or 00, and three zeros for each ending in 500 or 000. You might have to make adjustments for double & triple counts. Numbers ending in a single zero include those ending in 50, 500, double zero, or triple zero. Similarly numbers ending in double zero include those ending in 500 or triple zero.

    NotLKH: Perhaps Thinktank2 can use mathematica to verify for you.

    Using my above comment about the Kedaman post might give you a clue to verifying the trailing zeros.

    Perhaps you can use VB to compute the largest factorial it is capable of computing (170!, approximately 7.25742E306). Then compute a lot of products like 171*172*173 . . . If you divide each product by something like 1.00E200, and multiply all these products, you can verify the first 15 digits or so of your alleged value.

    Similarly, you could use your own software to calculate 1950!, then use VB to calculate 1951*1952*1953 . . . *1999*2000. Using these two values you could verify the first 15 digits of 2000! via VB calculations. If you do half a dozen similar verifications of the first 15 digits of other large factorial values, you should be able to either discredit or become confident in your software. You can also use the kedaman idea to verify the number of trailing zeros for various values.

    If you use your software to calculate several factorials of large but almost equal numbers (say 1495!, 1500!, & 1505!) you can use VB or a hand calculator to verify self consistency of the the total number of digits, the first 15 or so digits, and the number of trailing zeros.

    All: Does anybody (including NotLKH & Kedaman) really care about the exact value of 2000! ?
    Live long & prosper.

    The Dinosaur from prehistoric era prior to computers.

    Eschew obfuscation!
    If a billion people believe a foolish idea, it is still a foolish idea!
    VB.net 2010 Express
    64Bit & 32Bit Windows 7 & Windows XP. I run 4 operating systems on a single PC.

  24. #24
    pathfinder NotLKH's Avatar
    Join Date
    Apr 2001
    Posts
    2,397
    Originally posted by thinktank2
    I did a String Comparison using the StrComp function and it says they are the same.

    Anyway here is the mathematica output.
    Thanks for the verification. they Are Identical. I was pretty sure it worked, since it agreed with the posting of 99!. So, it seems that My program can return n! of up to 32k in length.

    Cool!

  25. #25
    transcendental analytic kedaman's Avatar
    Join Date
    Mar 2000
    Location
    0x002F2EA8
    Posts
    7,221
    Guv, yes I assumed that those numbers that ended with 00 and 50 were counted twice, 000 and 500 three times. Now when I think about whatyou said about 25's and 75 I think I know where those 48 of the 55 0e's are hiding.

    25*4=100, 75*8=600.. one extra beside ending with 5
    125*8 got one extra besides the above and ending with 5
    375*16 and so on...
    there should be 40 of the first and 8 of the latter

    Oh well, only 7 more to go
    Use
    writing software in C++ is like driving rivets into steel beam with a toothpick.
    writing haskell makes your life easier:
    reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
    To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.

  26. #26
    wossname
    Guest
    By my calculations 2000! yields a number many times larger than the number of elementary particles in the known universe!!!

    I sh*t ye not.

    In fact it is many orders of decimal magnitude larger. I would sincerely like to know what use numbers this large could be put to. Encryption doesn't count simply because there is no chance that any current algorithm can crack 160 bit encrytion, even running on ASCI Red or any other SC.

    http://www.sandia.gov/ASCI/Red/

  27. #27
    pathfinder NotLKH's Avatar
    Join Date
    Apr 2001
    Posts
    2,397
    Originally posted by kedaman
    Guv, yes I assumed that those numbers that ended with 00 and 50 were counted twice, 000 and 500 three times. Now when I think about whatyou said about 25's and 75 I think I know where those 48 of the 55 0e's are hiding.

    25*4=100, 75*8=600.. one extra beside ending with 5
    125*8 got one extra besides the above and ending with 5
    375*16 and so on...
    there should be 40 of the first and 8 of the latter

    Oh well, only 7 more to go
    This "Account for the 500 Zero's" Investigation is intriguing!

    I decided to try it this way.
    For the product of 2000 thru 1, for every 5 and 2 combination, you get 1 zero. So, if you count the number of times 5 is a factor of n, and similarly 2 is a factor of n, keeping a running total of both 2 counts and 5 counts, as n goes from 1 to 2000, then the number of zeros should be the smaller of the two running counts.

    for example, from 21 to 30, it breaks down this way:
    VB Code:
    1. n:   Num2's :       Num5's
    2. 21     0               0
    3. 22     1               0
    4. 23     0               0
    5. 24     3               0
    6. 25     0               2
    7. 26     1               0
    8. 27     0               0
    9. 28     2               0
    10. 29     0               0
    11. 30     1               1
    So there are 8 twos, and only 3 fives, so with my theory, mult(21 thru 30) should end with 3 zero's.
    And, since 21*...*30 = 109027350432000, we see that indeed it Does end with 3 zero's.
    So, with such a limited test, it seems my theory is sound.

    Now, the code.
    I whipped this up, and ran it:
    VB Code:
    1. Private Type hmmm
    2.     MyNum As Long
    3.     MyNumstr As String
    4.     IM_USED As Boolean
    5.     NUM_ZEROS As Long
    6.     WHATTIMESWHAT As String
    7.     num_5 As Long
    8.     num_2 As Long
    9. End Type
    10. Dim MyNums(2000) As hmmm
    11.  
    12. Private Sub Command2_Click()
    13. Dim SkipAgain As Boolean
    14. Dim MY_TEMP_NUM As Long
    15. Dim MY_TOT_2 As Long
    16. Dim MY_TOT_5 As Long
    17. For i = 1 To 2000
    18.     MyNums(i).IM_USED = False
    19.     MyNums(i).MyNum = i
    20.     MyNums(i).MyNumstr = i
    21.     MyNums(i).NUM_ZEROS = 0
    22.     MyNums(i).num_2 = 0
    23.     MyNums(i).num_5 = 0
    24.     MY_TEMP_NUM = i
    25.     While (MY_TEMP_NUM Mod 2) = 0
    26.         MY_TEMP_NUM = MY_TEMP_NUM / 2
    27.         MyNums(i).num_2 = MyNums(i).num_2 + 1
    28.     Wend
    29.     MY_TEMP_NUM = i
    30.     While (MY_TEMP_NUM Mod 5) = 0
    31.         MY_TEMP_NUM = MY_TEMP_NUM / 5
    32.         MyNums(i).num_5 = MyNums(i).num_5 + 1
    33.     Wend
    34.     MY_TOT_2 = MY_TOT_2 + MyNums(i).num_2
    35.     MY_TOT_5 = MY_TOT_5 + MyNums(i).num_5
    36.     Me.Caption = Format(i, "0000") & "::" & Format(MY_TOT_2, "0000") & "::" & Format(MY_TOT_5, "0000")
    37.     DoEvents
    38. Next i
    39.  
    40. MsgBox MY_TOT_2 & " " & MY_TOT_5
    41. End Sub

    it returns 1994 twos, and 499 fives, so since 499 is the smallest, there should be 499 zeros at the end of 2000!.

    So, wheres my missing 0? Whats wrong with this Checker Progie? Where is it missing a 5, and more than likely a 2 also, since both are calculated similarly?

    [EDITED]: Ahhh, Good! After double checking 2000!, There is only 499 zero's at the end of 2000!, NOT 500.

  28. #28
    pathfinder NotLKH's Avatar
    Join Date
    Apr 2001
    Posts
    2,397
    thinktank2,
    Whats the largest n that mathematica can return n!?

    Anyways, I think I've pretty much found my near upper limit, at this time.

    Can anyone confirm 9000! is 31682 digits long, with 2248 trailing zero's?

  29. #29
    transcendental analytic kedaman's Avatar
    Join Date
    Mar 2000
    Location
    0x002F2EA8
    Posts
    7,221
    NotLKH, Yes it makes sense:
    There is a zero for each factor 5 since there's always a larger amount of 2's to to make a zero. So in other words
    Zeroes=sumof( 2000\5^N )
    where \ stands for integer division, the sum of N=1 to log(2000)/log(5) (integers above won't contribute to the sum.
    The anwer is 499.

    for n=1 to log(9000)/log(5):s=s+9000\5^n:next:?s

    gives 2747 which makes me question your verification of 2248 trailing zeroes, count them again
    Use
    writing software in C++ is like driving rivets into steel beam with a toothpick.
    writing haskell makes your life easier:
    reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
    To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.

  30. #30
    transcendental analytic kedaman's Avatar
    Join Date
    Mar 2000
    Location
    0x002F2EA8
    Posts
    7,221
    it makes 2748, i forgot to null the variables, it was done in the immediate window, and the variables used seemed to be stored in IDE.
    Use
    writing software in C++ is like driving rivets into steel beam with a toothpick.
    writing haskell makes your life easier:
    reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
    To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.

  31. #31
    Hyperactive Member thinktank2's Avatar
    Join Date
    Nov 2001
    Location
    Arctic
    Posts
    272
    VB Code:
    1. Private Function NZeroes(n As Long) As Long
    2. Dim kMax As Long
    3. Dim NZ As Long
    4. Dim k As Long
    5.  
    6. kMax = Int(Log(n) / Log(5))
    7.  
    8. For k = 1 To kMax
    9.  NZ = NZ + Int(n / 5 ^ k)
    10. Next
    11.  
    12. NZeroes = NZ
    13.  
    14. End Function

    Coutesy : http://mathworld.wolfram.com/Factorial.html
    Attached Files Attached Files

  32. #32
    Hyperactive Member thinktank2's Avatar
    Join Date
    Nov 2001
    Location
    Arctic
    Posts
    272
    50000! for the really crazy ones...

    Took mathematica 4 minutes 32 seconds on a Celeron 600 MHZ with an Intranet web server, SQL server running in the Background + couple of other apps.

    I should say mathematica was a pretty decent app.
    It never got unstable, the maximum processor usage was something like 65% at one time. Copying the output to a text file was fun. Notepad or Word can't get that from Clipboard. So used the old dos edit. It took it some 6 minutes to paste.
    Attached Files Attached Files

  33. #33
    pathfinder NotLKH's Avatar
    Join Date
    Apr 2001
    Posts
    2,397
    OK. I think I got an app to figure m!/([m-n]!*n!). Just need a confirmation or two.

    Does
    VB Code:
    1. 999!/([999-441]!*441!) =
    2.  
    3. 1417971472058518209976919419370468948793352738245621
    4. 3013520109790488639218309117640325227291181691797408
    5. 8924431907561840053219116723534971112194936852491270
    6. 5577668288192893775702311700709931449149358280467056
    7. 3662329074394352553932014241200045132769006543768476
    8. 5395045353481222777525944406346759560

    and, if it does, does:
    VB Code:
    1. 987654!/([987654-87]!*87!) =
    2.  
    3. 1603815075717999944377845565146098131108484253760341
    4. 4660485892362528304845637405496845527723477030156965
    5. 3204282970944246669112392756452640178870020528153289
    6. 1464130883016178449351698746337613819576406830812395
    7. 6073379028490386478915296504699102152828698405731647
    8. 6771394400882099108410186209941718275773956903488459
    9. 0928720915346590050637576514379457894791533039280000
    10. 52718256923568960519001600

    It works for values less than 500, but Above 500, I'm not too sure.

    -Thanks
    -Lou

  34. #34
    pathfinder NotLKH's Avatar
    Join Date
    Apr 2001
    Posts
    2,397
    Originally posted by kedaman
    NotLKH, ......

    for n=1 to log(9000)/log(5):s=s+9000\5^n:next:?s

    gives 2747 which makes me question your verification of 2248 trailing zeroes, count them again
    which you later amended to 2748.
    Thinktank2's code:
    VB Code:
    1. Private Function NZeroes(n As Long) As Long
    2. Dim kMax As Long
    3. Dim NZ As Long
    4. Dim k As Long
    5.  
    6. kMax = Int(Log(n) / Log(5))
    7.  
    8. For k = 1 To kMax
    9.  NZ = NZ + Int(n / 5 ^ k)
    10. Next
    11.  
    12. NZeroes = NZ
    13.  
    14. End Function
    returns 2248 on 9000. {BTW, Thanks again ThinkTank for confirming 9000! for me!}

    I wonder where your extra 500 came from?
    The codes are pretty similar.
    BTW, in your line :for n=1 to log(9000)/log(5)

    Every time it loops, isn't it recalculateing the value of log(9000)/log(5)?

    -Lou

  35. #35
    Hyperactive Member thinktank2's Avatar
    Join Date
    Nov 2001
    Location
    Arctic
    Posts
    272
    Originally posted by NotLKH
    OK. I think I got an app to figure m!/([m-n]!*n!). Just need a confirmation or two.

    Does
    VB Code:
    1. 999!/([999-441]!*441!) =
    2.  
    3. 1417971472058518209976919419370468948793352738245621
    4. 3013520109790488639218309117640325227291181691797408
    5. 8924431907561840053219116723534971112194936852491270
    6. 5577668288192893775702311700709931449149358280467056
    7. 3662329074394352553932014241200045132769006543768476
    8. 5395045353481222777525944406346759560

    and, if it does, does:
    VB Code:
    1. 987654!/([987654-87]!*87!) =
    2.  
    3. 1603815075717999944377845565146098131108484253760341
    4. 4660485892362528304845637405496845527723477030156965
    5. 3204282970944246669112392756452640178870020528153289
    6. 1464130883016178449351698746337613819576406830812395
    7. 6073379028490386478915296504699102152828698405731647
    8. 6771394400882099108410186209941718275773956903488459
    9. 0928720915346590050637576514379457894791533039280000
    10. 52718256923568960519001600

    It works for values less than 500, but Above 500, I'm not too sure.

    -Thanks

    -Lou

    Yes both are correct !

    Calculating the nCm (or Binomial coefficient as mathematica calls it) is faster than calculating Factorials. It did 987654 C 87 in less than a second !!!

  36. #36
    transcendental analytic kedaman's Avatar
    Join Date
    Mar 2000
    Location
    0x002F2EA8
    Posts
    7,221
    Originally posted by NotLKH
    [B]
    which you later amended to 2748.
    Thinktank2's code:
    doh! I meant to post 2248 try it Basically It's the same thing as Thinkthank got, so there's no reason why it should produce a different result.
    BTW, in your line :for n=1 to log(9000)/log(5)

    Every time it loops, isn't it recalculateing the value of log(9000)/log(5)?
    No, for unlike while or for in other languages evaluates the criteria once and then loops until the iterator is equal to it.
    Use
    writing software in C++ is like driving rivets into steel beam with a toothpick.
    writing haskell makes your life easier:
    reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
    To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width