如何用C#编写一个程序求水仙花数?
C#,使用.Net6编写:
//水仙花数的搜索范围var index = 100; //因为水仙花数要求三位及以上,所以从100开始var end = 10000;
//循环主体 如上则范围为 [1,10000] 内寻找for (; index <= end; index++) {
//通过 log10 可以取得该数字的位数长度 int dg = (int)Math.Log10(index) +1; //将 log10 的位数向下取整保留进制数量的整数(+1是因为后续包含个位数) //将每一位转换成数字(不使用 string 中 char 转 int,纯数字转换) var sum = 0; //分位累加器 var digits = new int[dg]; //创建一个用于单独储存每一位的 for(int i = dg; i > 0; i--)
{
var x = index - sum; //用于舍去高位,见 P1 int dplace = (int)Math.Pow(10, i-1); //当前位数的值,如 1,10,100,1000... var p = x / dplace; //当前位的值 sum += dplace * p; //将前边已经取得的位计入累加用于在后续舍去(P1) digits[dg - i] = p; //将位数加在累加器上 }
//判断该数字是否符合条件 var nn = 0;
foreach(var d in digits)
{
nn += (int)Math.Pow(d, dg); //所有位 的位数幂 求和 }
if(nn == index) //当所有位的位数幂的和等于这个数本身时返回结果 {
Console.WriteLine($"{index} 是水仙花数");
}
}
首先你要理解啥是水仙花数:
水仙花数是指一个 n 位数 ( n≥3 ),它的每个位上的数字的 n 次幂之和等于它本身。(例如:1^3 + 5^3 + 3^3 = 153)
以上来自百度百科。
按照楼主的程序,有3层循环,姑且叫做a循环,b循环,c循环。
我们先从循环上下界和条件来看:
楼主用a循环代表个位数,用b循环代表10位数,c循环代表百位数,对嘛?假设是这种情况,让我们先不看代码。
事实上a循环是最外面的循环,c循环是最里面的循环,而计数按照逻辑应该是 111,112,113这样增长的,所以逻辑上应该反过来,a代表百位数,b代表10位数,c代表个位数。(其实您的方式也可以遍历所有您想遍历的数,只不过从逻辑上变成111,211,311...911,121,221...这样了,但是不觉得很不舒服嘛~)
然后我们来分析代码,结构很明白了:
a循环,百位数
{
b循环,十位数
{
c循环,个位数
{
验证
}
}
}
然后我们来确定验证:
一个水仙花数n,假设是1000以内的3位数,写作abc也就是 n = a*100 + b*10 + c = a^3 + b^3 + c^3,这不就是验证条件嘛?所以条件就是a*100 + b*10 + c = a*a*a + b*b*b + c*c*c;
然后来看循环上下界,百位数可以从1-9,十位数可以从0-9,个位可以从0-9,这时候程序就完成了啦。
楼主在确定上下界的时候犯了错哦,十位数不可以当做10到99,你要单纯的将她看成数字,因为十位数只可能出现0-9,这10种情况,而不会出现11,23,56这样的情况吧?
所以关键的循环体应该是:
for(a=1;a<=9;a++)
{
for(b=0;b<=9;b++)
{
for(c=0;c<=9;c++)
{
if(a*100 + b*10 + c == a*a*a + b*b*b + c*c*c)
{
printf("%d,%d,%d\n",a,b,c);
}
}
}
}
我把大括号全带上了,请养成良好的编程习惯哦~
当然你也可以把最后验证部分(if部分)替换成三元表达式,使用某一些编译器效率会提高一点:
for(a=1;a<=9;a++)
for(b=0;b<=9;b++)
for(c=0;c<=9;c++)
a*100 + b*10 + c == a*a*a + b*b*b + c*c*c ? printf("%d,%d,%d\n",a,b,c):; // 注意有个':'