=C语言= 整型变量与过大的整数
整型家族
在使用C语言写程序时,会储存各种长度的整型,而在整型家族中,长度的比较如下
char < short <= int <= long <long long
整型是如何储存在内存中的
以char
为例
char
的长度为1个字节
,8个比特位
,其中最高位是符号位,0
表示正数,1
表示负数,剩下的位数用于储存变量的绝对值
而当使用无符号整型(带前缀unsigned
)时,只需把符号位也用于存值即可
能够储存的最大正整数
int
长度为4字节
,能够储存的最大值为2的31次方-1
,即2,147,483,647
unsigned int
能够储存的最大值为4294967295
unsigned long long
长度为8字节
,能够储存的最大值为2的64次方-1
,即18,446,744,073,709,551,615
限制
虽然unsigned long long
已经很大了,但当遇到指数
,阶乘
之类的运算时仍然可能存不下!(光21!
就比unsigned long long
长了)
思路
过大的整数,可能出现在程序的过程中,也可能出现在输出中,对于过程,可以尝试改变实现思路,让过程中不出现过大的整数;对于输出,可以尝试改变输出的类型,采用输出字符或字符串
以下皆为例题
1.求n!的结尾有多少个0
最直白的思路就是把n!
算出来,然后用%10
再/=10
的方法统计末尾的0
,想法很简单,“实现”起来也不难,但不幸的是,21!
就已经储存不了了,所以不能暴力求解
所以要改变思路,先从末尾0是怎么来的下手。末尾的n个0来自因式分解后10的n次方,而采用质因数分解的方法,可以发现0
来自分解后2的n次方
和5的n次方
,而一个数分解后2的n次方
必定比5的n次方
多,所以只需统计5的n次方
。注意:就别再倒回去,想着先算出阶乘再求5的n次方
了。
这里采用逐步计数的方法:结果中的5的n次方
来自各个因数中5的N次方
的累乘,所以只需要历遍每个因数,并统计其中因数5
的次数。这样过程中就不会有过大的数字了
1 | //代码实现 |
快速输出1+2+……+10^n
如下图:当我们试图算一算答案时,发现n
到了10
时就已经算不出答案了
所以要改变输出答案答案的方式,观察一下n
在1~9
时的输出
这时我们发现答案颇有规律:每个输出都是两段先一个5,然后n-1个0
!
这样我们只需从最高位往最低位逐位打印即可,代码如下
1 | void printChar(int n)//版本一,逐位打印字符(串) |