zoukankan      html  css  js  c++  java
  • 10000的阶乘的算法(大数的阶乘)

       很多天没有更新自己的Blog了,前几天拿到一个题目.就是写一段程序计算10000的阶乘.当时我还以为这题目非常简单,没想到还是需要动点大脑的.花了将近半个小时才搞定,拿出来分享一下. 
       为什么不能用普通的方法来写呢,比如说递归?在我的教科书上可是用的是递归呀?不知道你注意没有,如果是100的阶乘的话,其结果肯定是非常大的,以我们现有语言的数据类型肯定是没法使用的,就拿C来说,long型能存的下100的阶乘吗?未必.所以我就使用数组来存储结果的每一位,然后输出每一位不就是结果吗.
      那么具体怎样去做?
      首先确定结果的位数?如何确定呢?请看下面.
      2!=1*2<=10*10
      3!=1*2*3<=10*10*10
    .......
    所以我们可以得出一个结论
              n!<=10
    n
    所以n!的位数可以这样计算:
    两边取对数,即log10n!<=log1010n

    两边n>=Log101+Log102+Log10 3+....Log10 n
    这样n!的位数肯定等于小于Log101+Log102+Log10 3+....Log10 n.

    以上是错误的
    正确的推断如下:

    可以将n!表示成10的次幂,即n!=10^M(10的M次方)则不小于M的最小整数就是 n!的位数,
    对该式两边取对数,有=log10^n!即:
    M = log10^1+log10^2+log10^3...+log10^n
    循环求和,就能算得M值,该M是n!的精确位数。


    位数的确定解决之后,就看看如何计算了.
    看看如下代码:

     1int index=0;
     2    long carrier=0;
     3    double bitCount = 1
     4    int begin = 0
     5  
     6    for(index=2; index<=n; ++index) 
     7    
     8        long multiValue = 0;   
     9        bitCount += log10((long double)index); 
    10        if(arrValue[begin] == 0
    11            begin++
    12  
    13        for(int j=begin; j<int(bitCount); ++j) 
    14        
    15            multiValue += (index*arrValue[j]); 
    16            arrValue[j] = char(multiValue % 10); 
    17            multiValue /= 10
    18        }
     
    19    }
     

    这里就是计算的关键了.注意一下进位问题即可.所有代码如下:

      1
      2//////////////////////////////////////////////////////////////////////////
      3//      Date created:    2005/07/12
      4//     Author:        Confach Zhang
      5//     Purpose:         计算n!的值
      6//////////////////////////////////////////////////////////////////////////
      7
      8  
      9using namespace std; 
     10#include "StdAfx.h"
     11#include <iostream.h>
     12#include <conio.h>
     13#include <stdlib.h>
     14#include <math.h>
     15#include <stdio.h>
     16#include <iomanip.h>
     17  
     18int GetNumber();                                   //输入 n 
     19int GetBitLength(int n);                           //求n!的位数
     20char* Initialize(int);                             //初始化存储结果的值
     21void PrintValue(char *a,int size);                 //打印值到屏幕
     22void PrintValue(char *a,int size,char* fileName);  //打印值到文件
     23char* GetValue(int val);                           //计算
     24char* SubGetValue(char* ,int);                      
     25
     26
     27int main() 
     28
     29    int value=GetNumber();
     30    char fileName[16];
     31    int size=GetBitLength(value);
     32    char *pa = Initialize(size);
     33
     34    //pa=GetValue();
     35    pa=GetValue(value);
     36
     37    PrintValue(pa,size); 
     38
     39    //sprintf(fileName,"%s","10000!.txt");
     40    sprintf(fileName,"%d!.txt",value);
     41    
     42    PrintValue(pa,size,fileName);
     43    delete []pa;  //note: 
     44    return 1;
     45}
     
     46//函数GetValue
     47// 求得计算结果
     48//返回结果
     49//History:
     50//1)char* GetValue()
     51//2)GetValue(int val)
     52//  参数:val 计算阶乘的值
     53char* GetValue(int val)
     54{
     55    //定义一个数组存储阶乘的值
     56    //首先得到10000!阶乘的位数
     57    int VALUE=val; 
     58    int length=GetBitLength(VALUE);
     59    char *arrValue = new char[length]; 
     60    if(!arrValue) {
     61        cout <<"申请内存失败!" << endl; 
     62        exit(1); 
     63    }
     
     64    arrValue[0= 1
     65    for(int i=1; i<length; i++
     66        arrValue[i] = 0
     67    arrValue=SubGetValue(arrValue,VALUE);
     68    return arrValue;
     69}

     70
     71char* SubGetValue(char* arrValue,int n)
     72{
     73    int index=0;
     74    long carrier=0;
     75    double bitCount = 1
     76    int begin = 0
     77  
     78    for(index=2; index<=n; ++index) 
     79    
     80        long multiValue = 0;   
     81        bitCount += log10((long double)index); 
     82        if(arrValue[begin] == 0
     83            begin++
     84  
     85        for(int j=begin; j<int(bitCount); ++j) 
     86        
     87            multiValue += (index*arrValue[j]); 
     88            arrValue[j] = char(multiValue % 10); 
     89            multiValue /= 10
     90        }
     
     91    }
     
     92  return arrValue;
     93}

     94
     95//得到计算阶乘的值,此函数为新增
     96int GetNumber() 
     97
     98    int n; 
     99    cout << "请输入要计算阶乘的n值: "
    100    cin >> n; 
    101    while(n < 0
    102        cout << "输入错误,请重新输入: "
    103        cin >> n; 
    104    }
     
    105    if(n == 0
    106        exit(1); 
    107    return n; 
    108}
     
    109
    110//函数GetBitLength
    111// 求得计算结果的位数,本函数为新增加
    112//参数
    113//     n 需要计算的阶乘的数
    114//返回结果的位数
    115int GetBitLength(int n) 
    116
    117    double sum = 1.0
    118    for(int i=1; i<=n; i++
    119        sum += log10((long double)i);
    120    return int(sum); 
    121}
     
    122//-----------
    123//函数:Initialize
    124//   初始化存储结果的数组
    125//参数:
    126//     size      数组的长度  
    127//返回值
    128//    初始化后的数组
    129//-------------
    130char * Initialize(int size) 
    131
    132    char *arrValue = new char[size];
    133    if(!arrValue) {
    134        cout << size<<"太大,申请内存失败!" << endl; 
    135        exit(1); 
    136    }
     
    137    arrValue[0= 1
    138    for(int i=1; i<size; i++
    139        arrValue[i] = 0
    140    return arrValue; 
    141}
     
    142  
    143//-----------
    144//函数:PrintValue
    145//   将结果输入到屏幕上
    146//参数:
    147//     buff      存储结果的数组
    148//   buffLen   数组的长度
    149//   fileName  文件名         
    150//-------------
    151void PrintValue(char *buff, int buffLen) 
    152
    153    int bit = 0
    154    int nCol=0;
    155    for(int i=buffLen-1; i>=0; i--
    156        if(bit % 10 == 0
    157        {
    158            cout << " " ; 
    159            nCol++;
    160            if(nCol==10)cout<<endl;
    161        }

    162          cout << int (buff[i]);   
    163        bit++
    164    }
     
    165    cout << endl; 
    166    
    167}
     
    168//-----------
    169//函数:PrintValue
    170//   将结果输入到一个文件中
    171//参数:
    172//     buff      存储结果的数组
    173//   buffLen   数组的长度
    174//   fileName  文件名         
    175//-------------
    176
    177void PrintValue(char *buff,int buffLen,char *fileName)
    178{
    179     int bit = 0
    180    int nCol=0;
    181
    182    FILE *fp=NULL;
    183    //-----------------------------
    184
    185    if (fileName==NULL)        return ;
    186    fp=fopen(fileName,"wt");
    187    if (fp==NULL)
    188    {
    189        printf("不能创建文件%s",fileName);
    190        return ;
    191    }

    192
    193    for(int i=buffLen-1; i>=0; i--)
    194    {
    195        fprintf(fp,"%d",int(buff[i]));
    196        
    197         if(bit % 9 == 0
    198        {
    199            fprintf(fp,"%s"," "); 
    200            nCol++;
    201            if(nCol==8)
    202            {
    203                fprintf(fp,"%s","\n");
    204                nCol=0;
    205            }

    206        }

    207        bit++;
    208        
    209    }

    210    fprintf(fp,"\n");
    211    fclose(fp);
    212}

    213
    好了,不说了.
    下载代码
    Last Updated: 2005年7月14日12:43:07 感谢kwklover 的建议
    Last Updated: 2005年7月15日 8:48:20 感谢arbean.wu的精彩建议
    Last Updated:2006年4月21日
  • 相关阅读:
    PHPStorm--美化
    Laravel5.1 模型--关联关系(复杂)
    HTML5 getUserMedia/AudioContext 打造音谱图形化
    如何在终端实时展现当前运行的git分支
    关于ionic的跨域问题
    ionic插件安装与卸载
    虚拟机调试ionic项目
    ionic双击退出键退出APP
    npm install 镜像
    对Date的扩展,将 Date 转化为指定格式的String
  • 原文地址:https://www.cnblogs.com/confach/p/192703.html
Copyright © 2011-2022 走看看