🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.pascal.misc
Article #8

Re: Tough FACTORIAL math problem...

#8
From: Kevin Cline
Date: Thu, 22 Feb 1996 20:41
88 lines
3013 bytes
In article <4gh4cq$8eo@agate.berkeley.edu>,
Bruce Kaskel <kaskel@durban.berkeley.edu> wrote:
>...

This thread should be dead.  Here is a tested program so simple and fast 
(about as fast as converting a number to base 5) that I can
compute the last digit of any factorial up to about 10000
in my head, and can also compute the last digit of factorials of large
powers of 10 (like 1 billion) in my head.

    #include <iostream.h>
    #include <stdlib.h>

    // last digits of powers of two
    static int t0[] = { 6, 2, 4, 8 };

    // powers of two (mod 5) of 0! - 4!
    static int t1[] = { 0, 0, 1, 0, 2 } ;

    static int f(int i) {
      if (i == 0) return 0;
      return t1[i % 5] + i/5 + f(i/5);
    }

    static int lastNonZeroDigitOfFactorial(int i) {
      if (i < 2) return 1;
      return t0[f(i) % 4];
    }

    int main(int argc, char **argv) {
      if (argc < 2) {
	cout << "usage: " << argv[0] << " n\n";
	exit(1);
      }

      int i = atoi(argv[1]);
      if (i < 0) {
	cout << argv[0] << ": non-negative argument required\n";
	exit(1);
      }

      cout << "The last non-zero digit of " << i << "! is "
	   << lastNonZeroDigitOfFactorial(i) << endl;
    }  

To compute this in your head, just keep dividing by 5, adding the
quotients + 1 when the remainder is 2 and 2 when the remainder is 4,
and continually reducing mod 4.

Computing the last non-zero digit of 1000000!:

f(1000000) = f(200000) (mod 4)	(No remainder when divided by 4 or 5)
f(200000) = f(40000) (mod 4)
f(40000) = f(8000) (mod 4)
f(8000) = f(1600) (mod 4)
f(1600) = f(320) (mod 4)
f(320) = f(64) (mod 4)
f(64) = 2 + 2 + f(12) = f(12) (mod 4)
f(12) = 1 + 2 + f(2) = 3 + 2 + f(2) (mod 4) = 1 + 1 = 2 (mod 4)

The last non-zero digit in 1000000! is t0[2] (2**2) or 4.

Now we see that the last non-zero digit in 10**n is the same
as the last non-zero digit in 2**n, so to compute 
the last non-zero digit in 1000000000!

f(1000000000) = f(512)
f(512) = t1[2] + 102 + f(102)
       =   1   +  2  + t1[2] + 20 + f(20)
       =   3         +   1   + 4 + f(4)
       =   0 + t1[4]
       = 2

The last digit of 1000000000! is t0[2] or 4.   

It's a bit harder for non-powers of 10, like 9731!

f(9731) = 1946 + f(1946)
	= 2 + 389 + f(389)
	= 3 +       2 + 77 + f(77)
	= 2 + 15 + f(15)    
	= 1 + f(3) 
        = 1

The last non-zero digit of 9731! is t0[1] (2**1) or 2.

-- 
Kevin Cline
Technical Details
Message-ID: <4gikei$nh7@sun152.spd.dsccc.com>
Path: arc1-ca.pugleaf.net!camelot.dsccc.com!not-for-mail
References: <4fr8be$ass@news.iconn.net> <danpop.824595562@rscernix> <4gaucn$cdu@beyond.escape.com> <4gh4cq$8eo@agate.berkeley.edu>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!camelot.dsccc.com!not-for-mail
From: kcline@sun152.spd.dsccc.com (Kevin Cline)
Newsgroups: comp.lang.pascal.misc,comp.lang.c++,comp.lang.c,comp.lang.pascal.borland
Subject: Re: Tough FACTORIAL math problem...
Date: 22 Feb 1996 14:41:54 -0600
Organization: DSC Communications Corporation Switch Products Division
Message-ID: <4gikei$nh7@sun152.spd.dsccc.com>
References: <4fr8be$ass@news.iconn.net> <danpop.824595562@rscernix> <4gaucn$cdu@beyond.escape.com> <4gh4cq$8eo@agate.berkeley.edu>
NNTP-Posting-Host: sun152.spd.dsccc.com