zoukankan      html  css  js  c++  java
  • 2.2 C#语法的学习(二) && 穷举

    光明小学六年级选出的男生的1/11和12名女生参加数学竞赛,剩下的男生人数是剩下的女生人数的2倍.已知六年级共有156人,问男、女生各有多少人?

    这是一道小学六年级的数学题,大家肯定都会:
    设置男生人数为x,女生人数为y,则有两个表达式

    x+y=156
    (10/11)x=(y-12)*2
    (`*`是乘号,x是男生人数不是乘号)
    

    然后一波计算,x=99,y=57

    那么,用C#应该怎么写呢?
    C#可以使用穷举的方式,来获得答案。和之前一样,先确定算法:
    男生/女生的人数大于等于0,小于等于156。
    我们将男生的人数从0递增到156(循环),而将女生人数设置为156-男生人数。
    当(10/11)男生人数=(女生人数-12)2的时候,输出结果。
    所以代码如下:

    for(int boysNumber=0; boysNumber<=156; boysNumber++)
    {
    	var girlsNumber = 156 - boysNumber;
    	//双等号表示“等于”
    	//10.0/ 11.0不能改成10/ 11,涉及精度问题
    	if ((10.0/ 11.0)  * boysNumber   == ((girlsNumber - 12) * 2))
    	{
    		Console.WriteLine($"男生人数为{boysNumber},女生人数为{girlsNumber}");
    		break;
    	}
    }
    

    当然笨一点可以写两个循环,外层循环男生人数,内层循环女生人数,也可以得到正确答案。
    同时,我们需要在if语句中多加了一个条件,“girlsNumber + boysNumber == 156”并且两个条件取交集,即同时满足才能为真。具体可以看C# 运算符中的逻辑运算符

    for (int boysNumber = 0; boysNumber <= 156; boysNumber++)
    {
    	for(int girlsNumber=0; girlsNumber<=156; girlsNumber++)
    	{
    		if ((girlsNumber + boysNumber == 156) &&
    			(10.0 / 11.0) * boysNumber == ((girlsNumber - 12) * 2))
    		{
    			Console.WriteLine($"男生人数为{boysNumber},女生人数为{girlsNumber}");
    		}
    	}
    }
    

    这样写的效率会比第一种差一些, 有以下几种因素:
    1.我们做了两层循环;
    2.我们穷举的可能性比第一种算法多;
    3.第一种方法在得到一种可能性后立即break停止执行,第二种会一直循环完毕(当然第二种也可以在得到一种可能性后停止循环,我为了不混淆重点没有这样写)。
    至此,我们明白了对待有限种可能性的问题,我们可以使用穷举的思想来解决。

    类似问题

    输出所有的“水仙花数”,所谓“水仙花数”是指一个三位数,其中各位数字立方和等于该数字本身。例如:153是一个“水仙花数”,因为153=111+555+333。
    具体的实现,自己尝试写一下。我的示例代码里面可以找到答案。

    延展:精度问题

    刚刚提到,在C#中,(10.0 / 11.0)和(10/ 11)是不一样的。
    我们先讲下在数学、生活中的“10”和“10.0”。“10”和“10.0” 是相等的,看起来也是“一样”的。但实际上,我们认为“10”是整数,“10.0”是小数,这点应该没有问题吧。那么在C#中,“10”和“10.0”是严格区分的,整数就是整数,小数就是小数,不同的类型采用不同的存储方式(小数有多种存储方式,在此不拓展讲)。
    以上的观点,就是说明C#是强类型语言,它的每一个对象/变量都需要一个明确的类型,类型的资料可以看这里
    举个例子,一个变量被定义为int(整数类型),它就不能再设置为其他类型,比如浮点数,也不能为其赋值小数。
    所以(10.0 / 11.0)会按照数学中小数的运算方式,算出一个无限循环小数,并且因为计算机的限制,在最末位四舍五入得到一个接近真正答案的有限小数。(也因为这种运算方式的答案不“精确”,像银行这样的金融机构并不会使用这样的方式计算。)
    而(10/ 11)则会根据整型的计算方式,得到答案“0”。整型的计算方式,可以理解为只计算整数部分,不取小数位,不进行四舍五入,可以试试(11/5)、(11/3)的计算。
    这个问题初学可能理解有点难,如果想要深入理解,需要理解计算机中整数、小数的多种存储方式,以及“除法”是怎么实现的。比较复杂,我觉得记个答案算了,然后日常写代码需要注意小数的精度问题。另外不同语言在小数、除法的处理上也有差别,这点需要格外注意。

    示例代码

    Exhaustion

  • 相关阅读:
    GSON -JSON 反序列化-多节点名称支持
    Jedis 分片原理
    闭锁-CountDownLatch
    XML序列化及反序列化
    用GIT操作SVN
    报表worker-CPU使用率过高原因排查
    二.PlantUML 之活动图
    一.PlantUML 与 IDEA 集成
    ArrayList
    VI常用命令
  • 原文地址:https://www.cnblogs.com/Lulus/p/12343017.html
Copyright © 2011-2022 走看看