C的几个小程序和概念(常见操作)(中)
1、求和计数
(1)常见的有三种方法:累乘,累加,递推迭代法。
(2)求Pi/4=1-1/3+1/5-1/7+...
正负交叉项数列。用一个符号变量来实现。
abs(ai)=1/i
a=1.0;
pi=0;
s=1;
i=1;
while(a>le-6){
pi+=s*a;//累加,累乘,一般先执行这步
i+=2;
a=1.0/i;
s=-s;
}//while
pi=pi*4;
(3)求ex
s=ex=1+x/1!+x2/2!+x3/3!+x4/4!+...
ak=1 k=0时,当k=1,2,3,...时ak=x/k*ak-1
cin>>x;
a=1;
s=0;
k=0;
while(fabs(a)>le-6) {
s+=a;
k++;
a=x/k*a;
}
(4)cos=1-x2/2!+x4/4!-...
当k=0时,ak=1,当k=2,4,6,8,...时,ak=-x2/k(k-1)*ak-2
(5)组合问题
P=Cnm
=从k等于1到m对(n-m+k)/k求乘积。
cin>>n>>m;
p=1.0;
if(n<0||m<0||m>n) return;
if(n-m<m) m=n-m;
for(k=1;k<=m;k++) p=p*(n-m+k)/k;
(6)Fibonacci数列
方法一:每次只前进一步,用两个数进行迭代
f1=1;
f2=1;
for(k=3;k<=n;k++)
{
f2=f1+f2;
f1=f2-f1;//f1是f2的前一个,每次只前进一步
cout<<f2;
}//for
或
result=pr_result=1;
while(n>2){
n--;
nx_old_result=pr_result;
pr_result=result;
result=pr_result+nx_old_result;
}
方法二:用数组
a[0]=a[1]=1;
for(k=2;k<n;k++)
a[k]=a[k-1]+a[k-2];
方法三:递归法
long fib(int n){
if(n<=2) return 1;
return fib(n-1)+fib(n-2)
}
(7)计算一元n次多项式
y=a0xn+a1xn-1+a2xn-2+...+an-1x+an
我们把y写作如下表达
y=(...(a0x+a1)x+a2)x+...+an-1)x+an
设y-1=0
y0=a0=y-1x+a0
y1=a0x+a1=y0x+a1
y2=(a0x+a1)x+a2=y1x+a2
....
yn=yn-1x+an
我们发现迭代式是y=y*x+a。
cin>>x>>n;
int k=0;
y=0;
while(k<=n){
cin>>a;//依次输入a0,a1,...
y=y*x+a;
k++;
}//while
这个算法同样可以解决进制转换问题,如x=10,m=3,输入a0,a1,a2,a2,a3则y=a0×103+a1×102+a2×101+a3×100。
(8)阶乘
double fact(int n){
if(n<=0) return 1.0L;
return n*fact(n-1);
}
2、字符输出
printf("%*s",n-i," ")
(1)有什么规律?
12345
22345
33345
44445
55555
有什么规律?
(2)杨辉三角
1
1 1
1 2 1
...........
杨辉三角的第k行有k个数字,是二项式(x+y)k-1展开项系数。即Ck-10,Ck-11,Ck-12...Ck-1k-1
经过变化,我们可以得出,
当j=0时,Ck-1j为1,当j=1,2,3,...时,Ck-1j=((k-j)/j)*Ck-1j-1,j=1,2,3...k-1
for(k=1;k<=n;k++)
{
c=1;
cout<<c;
for(j=1;j<=k-1;j++)
{
c=c*(k-j)/j;
cout<<c;//调整间距
}//for
cout<<endl;
}//for
3、穷举搜索
(1)水仙花数
for(i=1 to 9;i++)
for(j=1 to 9;j++)
for(k=1 to 9;k++)
{
a=100*i+10*j+k;
b=i*i*i+j*j*j+k*k*k;
if(a==b) cout<<a;
}
方法二
for(m=100;m<999;m++)
{
i=m/100;
j=m/10%10;
k=m%10;
if(m==i*i*i+j*j*j+k*k*k) cout<<m;
}
(2)求素数
求素数的传统算法和新思维
http://blog.163.com/zhoumhan_0351/blog/static/399542272009722113310392
两个微程序
http://blog.163.com/zhoumhan_0351/blog/static/39954227201032814216610
可以改一个第二个链接中链接的程序。素数都是奇数。所以从3开始,每次前进两步。
cout<<2;//先把输出来
for(m=3;m<=1000;m+=2){
sqrt_m=(int)sqrt(m+1) //加克服误差
for(k=3;k<=sqrt_m;k+=2)
if(m%k==0) break;
if(k>sqrt_m) cout<<m;//加上调整格式的代码
}//for
(3)最大公约数
欧几里德及其扩展算法,Stein算法(高效有用)
http://blog.163.com/zhoumhan_0351/blog/static/3995422720097236954783
(4)判断闰年及给定日期求星期几
http://blog.163.com/zhoumhan_0351/blog/static/39954227200972422927165
(5)输出自然数
756=2×2×3×3×3×7;
k=2;
如果k<=n,则转下步,否则终止
n%k==0,输入k,n=n/k,转上步,否则转下步
k++转第二步。
isfirst=1;
k=2;
while(k<=n)
if(0==n%k)
{
if(isfirst){
cout<<n<<"="<<k;
isfirst=0;
}//if
else{
cout<<"*"<<k;
}
n=n/k;
}//if
else k++;
4、字符文件操作与二进制文件操作的区别
(1)字符文件操作需要处理字符行的结尾:当输入函数读到一个字节是13时,跳过,即不返回13,当读到10时才返回;写入'\n'时,先写入'\r',再写入'\n'.
(2)字符支持格式化的输入输出。文件内容是可以显示的字符。
可以把字符文件当作二进制文件来处理,但无法把一个真正的二进制文件,如声音,视频等作一个字符文件处理。
C语言用一个非负长整形来表示文件的读写位置。
fgets(char *s,int n,FILE *fp);读取n-1个字符,最后再加一个'\0'.
删除注释程序
#include "iostream"
using namespace std;
int main(){
FILE *fp=fopen("c:\\TRACE.OUT","rb+");
if(!fp) {cout<<"error";return 1;}
char ch1,ch2,ch;
long pos1,pos2;
ch1=fgetc(fp);
if(feof(fp)) {fclose(fp); return 1;}
while(1){
ch2=fgetc(fp);
if(feof(fp)) break;
if(ch1=='/'&&ch2=='*') pos1=ftell(fp)-2;
if(ch1=='*'&&ch2=='/'){
pos2=ftell(fp)-1;
fseek(fp,pos1,0);
for(;pos1<=pos2;pos1++)
{
ch=fgetc(fp);
if(ch!='\n'&&ch!='\r')
{
fseek(fp,-1,1);
fputc(' ',fp);
fseek(fp,0,1);
}//if
}//for
}
ch1=ch2;
}//while
fclose(fp);
}
5、输入输出格式控制
printf函数中的格式控制如下
%[flags][width][.precision][h|l|L]type
scanf函数的格式控制如下
%[*][width][h|l|L]type