大数运算之阶乘

Int不能存储较大数

int 代表有符号整数,也就是说,用 int 声明的变量可以是正数,可以是负数,也可以是零,但是只能是整数。标准规定 int 的最小取值范围是 -32767 到 32767。

int 的取值范围因机器而异,但是一定要大于或者等于 -32767 到 32767。一般来说,int 占用一个字的内存空间。因此,字长为 16 位(Bit)的旧式 IBM 兼容机使用 16 位来储存整型 int ,取值范围是-32768 到 32767 。目前的个人电脑一般都是 32 位字长的,这些电脑中,int 一般也是 32 位的,取值范围是 -2147483648 到 2147483647。对于使用 64 位 CPU 的电脑,使用更多位储存 int 也是很自然的事情,取值范围当然也会更大。

Int:

16 -2^15  ~ 2^15-1

32 -2^31  ~2^31-1

64 -2^63  ~2^63-1

对于大数感觉长度还是不够,大数动辄都是几百位数,最近看到一段代码,自己研究了一段时间,感觉C语言真是强大,再加上这次国庆去北京,了解到C语言其实从来都不像大家人为的那样只是作为初级语言,入门语言供大家学习的,其实C语言的强大远远超出你我的想象。好吧,闲扯了一下。

大数阶乘:1000!

精简代码:

#include<stdio.h>
#define N 1000
long a[8916]={1,0},n,i,c,len;
int main(void) {
         n=N;
         for ( len=1; n>1; n--) {
                   for (c=0,i=0; i<len; i++ ){
                            a[i]= ( c+= a[i]*n )% 10000;
                            c/=10000;
                   }
 
                   ((a[i]=c)>0)?len++:0;
 
         }
         for(len--,printf("%d",a[len--]); len>=0; len--)printf("%04d",a[len]);
 
         return 0;
}


 

我的调试代码:

#include<stdio.h>
#define N 1000/* 最大到10555的阶乘 */
long a[8816] = {1, 0 }, n, i, c, len;
int main( void )
{
         n = N;
         for ( len = 1; n > 1; n-- )
         {
                   printf( "第1层for:len:%d,n:%d\n",len, n );
 
                   for ( c = 0, i = 0; i <len; i++ )
                   {
                            printf( "第2层for参数:c:%d,i:%d\n", c, i );
 
                            a[i]   = (c += a[i] * n) % 10000;
                            c       /= 10000;
                            printf( "第2层for:a[i]:%d,c:%d\n",a[i], c );
                   }
                   ( (a[i] = c) > 0) ? len++: 0;
                   printf( "第2层for结束:len:%d\n", len );
                   printf( "\n" );
         }
 
 
/*
 * for( len--,printf("for内:%d\n",a[len--]); len>=0; len--)
 * {
 * //          printf("打印:len:%d,a[len--]:%d\n",len,a[len--]);
 *     printf("%04d\n",a[len]);
 * }
 */
         for ( len--, printf( "%d", a[len--]); len >= 0; len-- )
                   printf( "%04d",a[len] );
         /* %04d  4代表着一共有几位,前面加0代表着输出时不够的位数用0填充 */
         return(0);
}
 
 
/* for (len=1;n>1; n--)     //把len的长度初始为1,因为数组中已经有一个元素了a[0]=1
 * {
 *  for(c=0,i=0; i<len;i++ ) //c初始为0,一开始还没运算哪来的进位,这是个内层循环,数组a中的len
 *                         //个元素都必须参与运算,都必须*n,这就是下面a[i]*n的来由
 *
 *    {
 *         a[i]= ( c+= a[i]*n ) % 10; c/=10;  //c是进位,不用说了,c+=a[i]*n,a每个元素与n
 *                                               //相乘必须考虑低位是否有进位,有就加起来
 *    }
 *
 * ((a[i]=c)>0)?len++:0;  //最后一个元素也有进位吗,有的话就在当前的元素的下个数组位置直接等于进位值,并
 *                         // 且数组的元素值要加1,没有的话什么都不干 ,光一个0什么都不是
 *
 * }
 */


精简版代码编译信息:

Compiling singlefile...

--------

- Filename:D:\dev++\99.cpp

- Compiler Name: TDM-GCC 4.9.2 64-bit Release

 

Processing C++source file...

--------

- C++ Compiler:E:\Dev-Cpp\MinGW64\bin\g++.exe

- Command: g++.exe "D:\dev++\99.cpp" -o"D:\dev++\99.exe" -I"E:\Dev-Cpp\MinGW64\include"-I"E:\Dev-Cpp\MinGW64\x86_64-w64-mingw32\include"-I"E:\Dev-Cpp\MinGW64\lib\gcc\x86_64-w64-mingw32\4.9.2\include"-I"E:\Dev-Cpp\MinGW64\lib\gcc\x86_64-w64-mingw32\4.9.2\include\c++"-L"E:\Dev-Cpp\MinGW64\lib"-L"E:\Dev-Cpp\MinGW64\x86_64-w64-mingw32\lib" -static-libgcc

 

Compilationresults...

--------

- Errors: 0

- Warnings: 0

- OutputFilename: D:\dev++\99.exe

- Output Size: 163.51953125 KiB

- Compilation Time: 0.34s

运行结果:


调试代码方便理解:自己切实运行一下,我就不贴啦。

自己动手会更加记忆深刻一些。

版权说明

著作权归作者所有©。 
商业转载请联系作者获得授权,非商业转载请注明出处。 
本文作者:Joe.Smith

发表日期:2016年10月8日 
本文链接:http://blog.csdn.net/qq_26816591/article/details/52761015

来源:CSDN 

更多内容:字母或数字全排列问题

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,需要明确一下大数的概念。一般来说,我们认为大数是指位数超过计算机所能处理的数据类型的数,比如说1000位以上的整数。在计算大数阶乘时,由于需要进行大量的乘法运算,因此需要采用高精度计算的方法,而顺序存储结构是一种比较常用的实现方法。 具体实现方法如下: 1. 首先定义一个数组来存储大数,数组中每个元素表示一位数字,比如说arr[i]表示第i位数字。 2. 将初始值赋给该数组,比如说要计算1000的阶乘,就可以将arr[0]赋值为1,其他位均赋值为0。 3. 然后按照阶乘的定义,从1开始依次乘以2、3、4……直到n。每次乘法运算都需要遍历数组,将每一位数字乘以当前的乘数,然后将结果保存到数组中。需要注意的是,如果乘积超过了10,就需要将进位的数字加到高位上。 4. 最后输出数组中的所有数字即可。 下面是一个基于顺序存储结构的大数阶乘的实现示例(以计算1000!为例): ```c #include<stdio.h> #define MAX 10000 int main() { int arr[MAX] = {0}; //定义数组 int i, j, n=1000, carry=0; //n为阶乘的数值,carry为进位值 arr[0] = 1; //初始值为1 for(i = 2; i <= n; i++) //从2开始依次乘以2、3、4……直到n { for(j = 0; j < MAX; j++) //遍历数组 { arr[j] = arr[j] * i + carry; //将每一位数字乘以当前的乘数,然后加上进位值 carry = arr[j] / 10; //计算进位值 arr[j] = arr[j] % 10; //计算当前位的值 } } for(i = MAX-1; i >= 0; i--) //倒序输出数组 { if(arr[i] != 0) //找到数组中第一个非零元素 break; } printf("1000! = "); for(; i >= 0; i--) //从第一个非零元素开始输出 { printf("%d", arr[i]); } printf("\n"); return 0; } ``` 需要注意的是,在实际的应用中,需要根据具体的需求来确定数组的大小。如果要计算更大的数,就需要使用更大的数组。同时,也需要注意避免数组越界的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值