Mathjax

jsxgraph

Wednesday, July 31, 2013

Factorial Summary

Time to summarize the factorial study and move on to other fun topics.

Computer representation of numbers

The key issue with large numbers like factorials, is how they are represented on the computer.  For performing mathematical operations the computer hardware has fixed size numbers.  For integer number types, this is related to the size of registers and number of wires connecting devices.  Each bit of a number is held in a flip-flop.  A flip-flop is an electronic device with two stable states, one representing a 0 and the other a 1.
Two types of integers are signed and unsigned.  Unsigned integers are represented in straight binary based numbers.  While signed integers are represented in twos compliment.  To change signs in twos compliment, invert (compliment) all bits then add one.  The following table shows four bit binary numbers and their values for both signed and unsigned integers. 

8 bit
Sign bit
4 bit 2 bit 1 bit Unsigned Signed
0 0 0 0 0 0
0 0 0 1 1 1
0 0 1 0 2 2
0 0 1 1 3 3
0 1 0 0 4 4
0 1 0 1 5 5
0 1 1 0 6 6
0 1 1 1 7 7
1 0 0 0 8 -8
1 0 0 1 9 -7
1 0 1 0 10 -6
1 0 1 1 11 -5
1 1 0 0 12 -4
1 1 0 1 13 -3
1 1 1 0 14 -2
1 1 1 1 15 -1

An interesting thing with these four bit signed numbers is that seven plus one is negative eight.  Also, for the unsigned numbers 15 plus one is zero.  The same thing happens with larger number formats but at different numbers.  This is also an issue when comparing signed and unsigned integers because -1 (signed) equals 15 (unsigned) for the four bit numbers above.  The table below shows various numbers and the result of adding one.

Precision
Value
(Signed Value)
Unsigned
+1
Signed
+1
1 Byte
127
128
-128
1 Byte
255  (-1)
0
0
2 Bytes
32767
32768
-32768
2 Bytes
65535  (-1)
0
0
4 Bytes
2147483647
2147483648
-2147483648
4 Bytes
4294967295  (-1)
0
0
8 Bytes
9223372036854775807
9223372036854775808
-9223372036854775808
8 Bytes
18446744073709551615 (-1)
0
0

This is how numbers are represented in hardware on a computer.  Memory addresses are also represented by fixed length binary numbers and the same issues can arise.  The memory addresses are usually unsigned so an index of -1 typically results in a segmentation fault because it is translated into a very large unsigned number.
The hardware is very fast at arithmetic but software can also be used to extend the number range or change the behavior.  The Gnu Multiple Precision Arithmetic Library (GMP) uses several integers internally to represent single larger integers.  This is very slow compared to hardware arithmetic.  Some hardware arithmetic is still used internally by the library.

Factorial Results

The C program for factorial was revised to calculate and print using different precision numbers.  Both signed and unsigned numbers were used.  The signed results were printed first with char, short int, int, long int, long long int variables.  The corresponding unsigned values were printed below.  Your results may vary because the C standard does not specify a precision for the variable types, except for char which is one byte.  The results for several factorials are listed below.


Bytes    1       2       4               8                       8
Enter a number > 0, or 0 to quit :5                                                    
5!      120     120     120             120                     120                                            
        120     120     120             120                     120                                            
Enter a number > 0, or 0 to quit :6                                                    
6!      -48     720     720             720                     720                                            
        208     720     720             720                     720                                            
Enter a number > 0, or 0 to quit :7                                                    
7!      -80     5040    5040            5040                    5040                                           
        176     5040    5040            5040                    5040                                           
Enter a number > 0, or 0 to quit :8                                                    
8!      -128    -25216  40320           40320                   40320
        128     40320   40320           40320                   40320
Enter a number > 0, or 0 to quit :9
9!      -128    -30336  362880          362880                  362880
        128     35200   362880          362880                  362880
Enter a number > 0, or 0 to quit :10
10!     0       24320   3628800         3628800                 3628800
        0       24320   3628800         3628800                 3628800
Enter a number > 0, or 0 to quit :11
11!     0       5376    39916800        39916800                39916800
        0       5376    39916800        39916800                39916800
Enter a number > 0, or 0 to quit :12
12!     0       -1024   479001600       479001600               479001600
        0       64512   479001600       479001600               479001600
Enter a number > 0, or 0 to quit :13
13!     0       -13312  1932053504      6227020800              6227020800
        0       52224   1932053504      6227020800              6227020800
Enter a number > 0, or 0 to quit :14
14!     0       10240   1278945280      87178291200             87178291200
        0       10240   1278945280      87178291200             87178291200
Enter a number > 0, or 0 to quit :15
15!     0       22528   2004310016      1307674368000           1307674368000
        0       22528   2004310016      1307674368000           1307674368000
Enter a number > 0, or 0 to quit :16
16!     0       -32768  2004189184      20922789888000          20922789888000
        0       32768   2004189184      20922789888000          20922789888000
Enter a number > 0, or 0 to quit :17
17!     0       -32768  -288522240      355687428096000         355687428096000
        0       32768   4006445056      355687428096000         355687428096000
Enter a number > 0, or 0 to quit :18
18!     0       0       -898433024      6402373705728000        6402373705728000
        0       0       3396534272      6402373705728000        6402373705728000
Enter a number > 0, or 0 to quit :19
19!     0       0       109641728       121645100408832000      121645100408832000
        0       0       109641728       121645100408832000      121645100408832000
Enter a number > 0, or 0 to quit :20
20!     0       0       -2102132736     2432902008176640000     2432902008176640000
        0       0       2192834560      2432902008176640000     2432902008176640000
Enter a number > 0, or 0 to quit :21
21!     0       0       -1195114496     -4249290049419214848    -4249290049419214848
        0       0       3099852800      14197454024290336768    14197454024290336768

Enter a number > 0, or 0 to quit :32
32!     0       0       -2147483648     -6045878379276664832    -6045878379276664832
        0       0       2147483648      12400865694432886784    12400865694432886784
Enter a number > 0, or 0 to quit :33
33!     0       0       -2147483648     3400198294675128320     3400198294675128320
        0       0       2147483648      3400198294675128320     3400198294675128320
Enter a number > 0, or 0 to quit :34
34!     0       0       0               4926277576697053184     4926277576697053184
        0       0       0               4926277576697053184     4926277576697053184

Enter a number > 0, or 0 to quit :64
64!     0       0       0               -9223372036854775808    -9223372036854775808
        0       0       0               9223372036854775808     9223372036854775808
Enter a number > 0, or 0 to quit :65
65!     0       0       0               -9223372036854775808    -9223372036854775808
        0       0       0                9223372036854775808     9223372036854775808
Enter a number > 0, or 0 to quit :66
66!     0       0       0               0                       0
        0       0       0               0                       0


Typically, the result gets smaller or negative as the factorial increases beyond when the precision gets insufficient to hold the full result.  The int type at 16! is an exception.  From the results above it can be seen that a long int and a long long int are the same on this system.  Every multiplication by a number divisible by two adds a zero to the right side of the binary number.  Thus after sufficient zeros are added the number becomes zero.  Note that one odd number multiplication of the number before becoming zero does not change the result.

The modified C code with different precision factorial computations.

 #include <stdio.h>  
 /* Program for computing the factorial of a number */  
 int main(int nvar, char** vars) {  
  int n,i;  
  char ck;  
  short sk;  
  int ik;  
  long int lk;  
  long long int llk;  
  unsigned char uck;  
  unsigned short usk;  
  unsigned int uik;  
  unsigned long int ulk;  
  unsigned long long int ullk;

  printf("Bytes\t%d\t%d\t%d\t%d\t%d\n",sizeof(ck),sizeof(sk),sizeof(ik),sizeof(lk),sizeof(llk));  
  while( 1 ) {  
   printf("Enter a number > 0, or 0 to quit :");  
   scanf("%d",&n);  
   if( n < 1 ) break;  
   ck = sk = ik = lk = llk = uck = usk = uik = ulk = ullk = 1;  
   for(i=1;i<=n;i++) {  
    ck *= i;  
    sk *= i;  
    ik *= i;  
    lk *= i;  
    llk *= i;  
    uck *= i;  
    usk *= i;  
    uik *= i;  
    ulk *= i;  
    ullk *= i;  
   }  
   printf("%d!\t%hhi\t%hi\t%i\t%li\t%lli\n",n,ck,sk,ik,lk,llk);  
   printf("\t%hhu\t%hu\t%u\t%lu\t%llu\n",uck,usk,uik,ulk,ullk);  
  }  
 }  

No comments:

Post a Comment