引入问题:求2+22+222+2222+…+222…222(n个2)+…的值(精确计算)
当n取很大时,该如何储存每个加数以及他们的和?
考虑是用字符数组还是数值数组储存每个加数,
每个数组元素存一位数还是多位数?
如果不考虑n取很大时,程序其实很简单,有几种方法,既可以用循环,也可以用递归。
#include<stdio.h>
void main()
{
long a[256],s;
int n,i;
printf("请输入n:");
scanf("%d",&n);
a[1]=2;
s=2;
printf("2");
for(i=2;i<=n;i++)
{
a[i]=10*a[i-1]+a[1];
printf("+%ld",a[i]);
s=s+a[i];
}
printf("=%ld",s);
}
这里采用虽然是long类型,其实256个长度没有必要,因为当n取10的时候,就已经溢出了,即使是long long类型,我试过,当n取20时,也溢出了
下面是各种类型的取值范围:
unsigned int 0~4294967295
int 2147483648~2147483647
unsigned long 0~4294967295
long 2147483648~2147483647
long long的最大值:9223372036854775807
long long的最小值:-9223372036854775808
unsigned long long的最大值:18446744073709551615
__int64的最大值:9223372036854775807
__int64的最小值:-9223372036854775808
unsigned __int64的最大值:18446744073709551615
其实int64位也就是long long
那如果考虑n取很大的值时,应该怎么保存呢
这里采用的是用long类型数组,每个数组元素储存6位数
直接上代码:
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
//编译环境是vs2019,如果不是,可以忽略上面两行
#include<stdio.h>
void main()
{
long a[100], s[256] = { 0 },b,d; //a数组储存加数,s数组储存结果
//进位变量d,中间结果b
int n, i, j, x, m = 1; //m记录当前的位数
int k = 2;
long p; //p为中间变量
printf("请输入n:");
scanf("%d", &n);
s[1] = 2;
a[1] = 2;
d = 0;
printf("2");
for (i = 2; i <= n; i++)
{
if (a[k - 1] * 10 > 1000000)
{
p = (a[k - 1] * 10 + 2) / 1000000;
a[k] = p;
k++;
}
else
{
a[k - 1] = a[k - 1] * 10 + 2;
}
printf("+");
for (x = 1; x <= k - 1; x++)
{
printf("%ld", a[x]);
}
if (k - 1 > m)
{
m++;
}
for (j = 1; j <= m; j++)
{
if (j <= (k - 1))
{
b = a[j] + s[j] + d;
s[j] = b % 1000000;
d = b / 1000000;
}
else
{
b = s[j] + d;
s[j] = b % 1000000;
d = b / 1000000;
}
}
if (d != 0)
{
s[j] = d;
m++;
}
}
printf("\n=");
//for (x = m; x >=1; x--)
//{
// printf("%ld",s[x]);
//}
printf("%ld",s[m]);
for (x = m; x >= 2; x--)
{
if (s[x] > 0)
{
if (s[x - 1] < 100000) //如果是5位数
{
printf("0");
if (s[x - 1] < 10000)
{
printf("0");
if (s[x - 1] < 1000)
{
printf("0");
if (s[x - 1] < 100)
{
printf("0");
if (s[x - 1] < 10)
{
printf("0");
}
}
}
}
printf("%ld", s[x - 1]);
}
else //若6位数全占满了
{
printf("%ld", s[x - 1]);
}
}
}
puts("");
printf("m=%d", m);
//for (x = 1; x <= k - 1; x++)
//{
// printf("%ld\n", a[x]);
//}
}
这里在写代码的时候其实有个问题,那就是累加计算的和,与下一次相加的加数,到底哪一个比较大,其实就是数列A(n+1)-A(n)=2*10^(n+1),求出Sn?A(n+1),当n取前面几个,很显然是A(n+1)大,但是当n取很大呢,我没有仔细算,如果不管n取多大,A(n+1)始终是大于Sn的,那程序中间有一部分可以简化。具体没有算。如果有人知道的话,欢迎指出。
后面输出的时候,也有个问题,不能直接for循环,倒着输出s[]。因为若当s[]
记录的和为123456 001234时,这样输出的是123456 1234,中间的0没有输出
来,因为这是当成一个六位数保存,所以输出的格式要用if语句判断是几位数,
然后补0