C#程序设计多位水仙花数计算Word文档格式.docx
《C#程序设计多位水仙花数计算Word文档格式.docx》由会员分享,可在线阅读,更多相关《C#程序设计多位水仙花数计算Word文档格式.docx(23页珍藏版)》请在冰豆网上搜索。
最早被人们认识的水仙花数为153。
谈祥柏教授在文献[2]第74—75页中谈到“数论大师(Hardy)在其名著《数学家的辨解》中曾指出过,有四个三位数具有这种性质,除153外,其他三数为370,371与407。
”,文献[3]也给出了由88个自然数组成的水仙花数表。
近年来.计算机的发展及应用突飞猛进.也为水仙花数的计算提供了很好的计算工具。
但是,如果对每一个n位正整数、求出它的各位数的次方之和,进而通过判别得到的和是否与它本身相等来判别该数是否为水仙花数,则需要遍历每一个正整数,可以看出每当位数增加1时,所要处理的正整数个数将增加1O倍。
因此,当位数n增大时,其计算量将呈几何级数骤增。
显然这种方法只适用于n较小的情况,对于较大的n如果也采用这种方法,即使应用计算机计算也是很困难的。
本文从应用计算机计算水仙花数的角度出发,讨论应用计算机快速计算所有水仙花数的算法。
2课题介绍
2.1功能要求
(1)用C#语言实现程序设计;
(2)循序渐进地从低位到多位展示水仙花数的计算机实现;
(3)界面友好(良好的人机互交),程序要有注释。
2.2主要任务
(1)创建窗体作为交换和展示界面;
(2)实现三位水仙花数的多种实现;
(3)实现3-9位水仙花数的计算和展示;
(4)实现3-17位水仙花数的计算和展示;
(5)定义结构实现3-60位水仙花数的计算。
2.3运行环境
(1)WINDOWS2003/XP系统
(2)VisualStudio2008开发环境
2.4开发语言
C#语言
3概要设计与详细设计
3.1系统流程图
系统的主要功能包括多位水仙花数的计算
系统的流程及框架如图3.1所示。
图3.1系统流程图
3.2详细设计
(1)功能计算0-9的n次幂的详细设计
计算0-9的n次幂功能是计算0-9的n次幂
该功能的实现流程如下:
privatevoidCalculateArray(intn,long[]array)
{
//Console.WriteLine计算并保存0-9的n次幂
for(inti=0;
i<
=9;
i++)
array[i]=i;
for(intj=2;
j<
=numLength;
j++)
array[i]*=i;
}
(2)功能数组比较的详细设
数据比较功能是比较判断两数组是否相等,如果两数组的每个对应元素都想等,则这两个数组相等。
该功能的实现如下:
privateboolarrayEqual(long[]arrayLeft,long[]arrayRight)
boolflag;
flag=true;
10;
if(arrayLeft[i]==arrayRight[i])
//donothing
else
flag=false;
returnfalse;
returnflag;
(3)读取文件功能的详细设计
读取文件函数的功能是从给的的文件名中读去文件并显示在窗体的文本框中。
该功能的详细实现如下:
//读取文件
privatevoidReadText(stringfileName)
richTextBox1.Clear();
if(File.Exists(fileName))
using(StreamReadersr=File.OpenText(fileName))
Stringinput;
while((input=sr.ReadLine())!
=null)
richTextBox1.Text+=input+"
\n"
;
sr.Close();
4关键代码与特色功能的实现
4.1关键代码
C#的long型数据只能保存17位的十进制正整数,然后要计算18及更多位数的水仙花数则会溢出,所以在本系统中定义了一个BigInt结构。
来保存64位的正整数。
定义如下:
//结构定义开始
structBigInt
privatelong[]bigInt;
privatestaticlonglimit=100000000;
//构造函数
publicBigInt(longa)
bigInt=newlong[8];
longb=limit*limit;
if(a>
=b)
thrownewOverflowException("
初始值必须小于10**16"
);
bigInt[0]=a%limit;
bigInt[1]=a/limit;
publicBigInt(BigInta)
8;
bigInt[i]=a.bigInt[i];
//显示实现转换符操作,主要用于求模后赋值
publicstaticexplicitoperatorlong(BigIntlhs)
returnlhs.bigInt[0];
publicstaticexplicitoperatorint(BigIntlhs)
return(int)lhs.bigInt[0];
//运算符重载
publicstaticBigIntoperator+(BigIntlhs,longrhs)
if(rhs>
=limit)
BigInt的long型加数不得超过最大的八位数"
BigIntnum=newBigInt(lhs);
longcarry=0;
//保存进位
num.bigInt[0]=num.bigInt[0]+rhs;
num.bigInt[i]=num.bigInt[i]+carry;
carry=0;
if(num.bigInt[i]>
limit)
carry=num.bigInt[i]/limit;
num.bigInt[i]=num.bigInt[i]%limit;
//检测carry是否为0,如果不为0则表示num.bigInt[7]产生l进位溢出
if(carry>
0)
BigInt与long加法运算后结果产生溢出即超过64位"
returnnum;
publicstaticBigIntoperator+(BigIntlhs,BigIntrhs)
BigIntsum=newBigInt(0);
BigIntnumLeft=newBigInt(lhs);
BigIntnumRight=newBigInt(rhs);
sum.bigInt[i]=carry+numLeft.bigInt[i]+numRight.bigInt[i];
if(sum.bigInt[i]>
carry=sum.bigInt[i]/limit;
sum.bigInt[i]=sum.bigInt[i]%limit;
BigInt与BigInt型加法法运算后结果产生溢出即超过64位"
returnsum;
publicstaticBigIntoperator*(BigIntlhs,longrhs)
BigInt的乘数不得超过最大的八位数"
longcarry=0;
//运算逻辑:
每位先乘然后加上前一位的进位并清空进位
num.bigInt[i]=num.bigInt[i]*rhs;
num.bigInt[i]+=carry;
carry=0;
//如此进位后超出limit则产生新的进位
BigInt乘法运算后结果产生溢出即超过64位"
publicstaticBigIntoperator*(longlhs,BigIntrhs)
if(lhs>
与BigInt相乘的long型数据不得超过最大的八位数"
BigIntnum=newBigInt(rhs);
num.bigInt[i]=num.bigInt[i]*lhs;
num.bigInt[i]+=carry;
publicstaticBigIntoperator/(BigIntlhs,longrhs)
BigInt的除数不得超过最大的八位数"
//保持每位除后的余数
for(inti=7;
i>
=0;
i--)
//运算逻辑每位加上上一位的余数然后在除;
把该位除得的余数保存在carr,商保存num.bigInt[i]。
num.bigInt[i]=num.bigInt[i]+carry*limit;
carry=num.bigInt[i]%rhs;
num.bigInt[i]=num.bigInt[i]/rhs;
publicstaticBigIntoperator%(BigIntlhs,longrhs)
BigInt的模数不得超过最大的八位数"
returnnewBigInt(carry);
publicstaticbooloperator==(BigIntlhs,BigIntrhs)
if(lhs.bigInt[i]==rhs.bigInt[i])
publicstaticbooloperator!
=(BigIntlhs,BigIntrhs)
if(lhs==rhs)
returntrue;
publicstaticbooloperator>
(BigIntlhs,BigIntrhs)
if(lhs.bigInt[i]>
rhs.bigInt[i])
(BigIntlhs,longrhs)
for(inti=6;
lhs.bigInt[i]+=lhs.bigInt[i+1]*limit;
rhs)
lhs.bigInt[i]=lhs.bigInt[i]%limit;
publicstaticbooloperator<
=newBigInt(rhs))
longa=lhs.bigInt[i];
longb=rhs.bigInt[i];
if(a!
=0&
&
b!
=0)
if(a<
b)
elseif(a==0)
if(lhs.bigInt[i]<
if(rhs.bigInt[i]!
=rhs.bigInt[i])
publicoverridestringToString()
returnString.Format("
{0:
d8}{1:
d8}{2:
d8}{3:
d8}{4:
d8}{5:
d8}{6:
d8}{7:
d8}"
this.bigInt[7],this.bigInt[6],this.bigInt[5],this.bigInt[4],
this.bigInt[3],this.bigInt[2],this.bigInt[1],this.bigInt[0]);
//结构定义结束
多位水仙花数计算函数:
如果对每一个n位正整数、求出它的各位数的次方之和,进而通过判别得到的和是否与它本身相等来判别该数是否为水仙花数,则需要遍历每一个正整数,可以看出每当位数增加1时,所要处理的正整数个数将增加1O倍。
本系统的思路是,对于给定的n位数。
这个数字中0,1,2,3,4,5,6,7,8,9的位数之后一定为n,然后依次累加0的n次幂乘以0的个数、1的n次幂乘以1的个数、2的n次幂乘以2的个数。
如果所得的和等于这个数,则这个数就是水仙花数。
具体代码如下:
privatevoidEntrance(intn)
//主函数开始
//定义所求水仙花数的位数,有效值为3-60.
longtime=0;
long[]arraySum=newlong[10];
//记录循环遍历中0-9的个数
longi0,i1,i2,i3,i4,i5,i6,i7,i8,i9;
//循环控制变量
BigIntnumStart=newBigInt
(1);
BigIntnumEnd=newBigInt
(1);
BigIntbasic=newBigInt(0);
BigInt[]array=newBigInt[10];
//保存0-9的n次幂
//计算n位数的最小值和最大值
for(inti=1;
n;
numStart=numStart*10;
numEnd=numStart*10;
//计算并保存0-9的n次幂
CalculateArray(n,array);
richTextBox1.Text+=string.Format("
开始数值:
\n{0}"
numStart)+"
\r\n"
结束数值:
numEnd)+"
richTextBox1.Text+=n.ToString()+"
位数的水仙花数"
+"
for(i9=n;
i9>
i9--)
//9
arraySum[9]=i9;
basic=i9*array[9];
if(basic>
=numEnd)
continue;
for(i8=n-i9;
i8>
i8--)
//8
arraySum[8]=i8;
basic=i9*array[9]+i8*array[8];
for(i7=n-i9-i8;
i7>
i7--)
//7
arraySum[7]=i7;
basic=i9*array[9]+i8*array[8]+i7*array[7];
for(i6=n-i9-i8-i7;
i6>
i6--)
//6
arraySum[6]=i6;
basic=i9*array[9]+i8*array[8]+i7*array[7]+i6*array[6];
for(i5=n-i9-i8-i7-i6;
i5>
i5--)
//5
arraySum[5]=i5;
basic=i9*array[9]+i8*array[8]+i7*array[7]+i6*array[6]+i5*array[5];
for(i4=n-i9-i8-i7-i6-i5;
i4>
i4--)