C#编程之神奇程序找数
C#编程之神奇程序找数
问题1:这个程序要找的是符合什么条件的数?
问题2:这样的数存在么?符合这一条件的最小的数是什么?
问题3:在电脑上运行这一程序,你估计多长时间才能输出第一个结果?时间精确到分钟(电脑:单核CPU 4.0G Hz,内存和硬盘等资源充足)。
问题4:在多核电脑上如何提高这一程序的运行效率?
(注:该程序、用C#语言编写,但是只要有C语言基础完全没有阅读压力,如果对部分语句不懂请自行查询)
将上述问题结果写到博客上,截止时间本周日(3月19日)晚8时
using System;
using System.Collections.Generic;
using System.Text;
namespace FindTheNumber
{
class Program
{
static void Main(string[] args)
{
int [] rg =
{2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
20,21,22,23,24,25,26,27,28,29,30,31};
for (Int64 i = 1; i < Int64.MaxValue; i++)
{
int hit = 0;
int hit1 = -1;
int hit2 = -1;
for (int j = 0; (j < rg.Length) && (hit <=2) ; j++)
{
if ((i % rg[j]) != 0)
{
hit++;
if (hit == 1)
{
hit1 = j;
}
else if (hit == 2)
{
hit2 = j;
}
else
break;
}
}
if ((hit == 2)&& (hit1+1==hit2))
{
Console.WriteLine("found {0}", i);
}
}
}
}
}
首先,对于上述的几个问题我先不做回答,我先谈一下自己对于这个程序的理解,这个程序我自己运行了差不多三个小时,但是并没有出来结果,我想这应该是大多数同学共同的问题。第一眼看到这段代码的时候,我以为会在一分钟以内出来结果,然而第一次运行直接宣告了我认知上的错误。这说明这个程序有自己的内部原理,并不是我们常规情况下所遇到的很快就会出现结果的程序。运行没有得到任何的结果,但我并没有就此放弃,通过在稿纸上的模拟运算,我基本上了解了这段代码的目的。这段代码看起来并不难,但实际上它的运算量是相当庞大的。说完自己的理解,接下来我就对于这几个问题做简单分析解答。
问题1:
对于第一个问题,我的理解是寻找一个变量i,而这个i满足的条件应该是这几个条件:
条件一:(i % rg[j]!= 0)&&(i % rg[j+1]!= 0)&&(i % rg[j+2]== 0),也就是说对于三个连续的数a,b,c;i不能整出a和b,但可以整除c,比如当a=7,b=8,c=9;此时当i=54时满足这个条件;这是我分析的第一个条件。
条件二:在条件一的基础上还必须满足(hit == 2)&& (hit1+1==hit2)这个条件,此时这个数的范围就可以进一步缩小了,因为hit==2,这说明这个数只有不能被rg[j]和rg[j+1]整除,它可以被除rg[j]和rg[j+1]之外的所有数整除。
问题二:
1、对于这个问题,我们应该注意到问题1中的两个条件,因为通过问题1已经分析到rg[j]和rg[j+1]是两个连续的数,那么我们可以确定rg[j]和 rg[j+1]不小于16,以为如果rg[j]一旦小于16,那么rg[j]*2也在rg[]数组内,这样肯定是不满足(hit == 2)&& (hit1+1==hit2)这个条件的。最后得到的hit结果必然大于2。
2、rg[j]和rg[j+1]这两个连续的数也不能由rg[]数组中其他成员变量相乘得到,如果rg[j]和rg[j+1]中任意一个数可由数组中两个数相乘得到,那么该数组中将至少有四个数可以被i整除,也不满足(hit == 2)&& (hit1+1==hit2)这个条件。
3、结合以上两点我们将满足上述条件的数筛选出来{17,19,23,29,31},那么我们需要寻找的rg[j]和rg[j+1]中肯定有一个数在这个数组当中,而且我们完全可以分析得到这两个数是一奇一偶,那我们考虑乘积最小且必须满足第一点的情况,那就是rg[j]和rg[j+1]为16和17,与此同时,我们也考虑17和18,我们分析一下这两组数的区别,不能被16和17整除,但需要被数组内其他所有数整除,虽然16可以由2和8相乘得到,但2是8的因子,所以只要i能整除8,就必能整除2,这就是说i应该可以被8整除但不能被16整除。如果我们考虑18,那么i应该是可以被2和9整除的,但却不能被18整除,这显然是矛盾的。所以rg[j]和rg[j+1]为16和17。
4、以上这几点分析都是个人观点,而最后的答案我自己感觉应该是一个比较大的数,其实我个人观点是通过计算缩小i取值范围之后,可以从高位依次向下取值,这样可以更快的接近结果。具体答案我们可以参考CSDN上边也有大神的具体讲解,这里我对答案做一个引用i=8*25*27*7*11*13*19*23*29*31=2123581660200,之所以考虑到8,25,27,而不考虑除17之外的所有素数,能被27整除的数一定能被3和9整除,反之就不一定了。同理我们可以理解其他情况。
问题三:
对于这个问题,我自己的想法是考虑程序执行一次外循环,大约执行平均10次左右内循环,那么我们就需要计算执行着一次循环所需的时间,当然我自己确实没有什么更好的方法,参考网上的计算方法:我们可以假设该原子操作需要120个时钟周期。因此4GHz的CPU在1秒内能跑4*10^9 / 120= 3.33*10^7 即1670万次原子操作。对于外层循环执行了2123581660200次,内层循环取决于i的情况,这里我们粗略估计,内层循环平均可以跑10次,通过这样的计算方式我们大致可以得出总共执行的操作约为2123581660200/3.33*10^7=6.37*10^5秒,也就是大约10616分钟。
问题四:
首先多核运行比单核要快些,虽然系统说是可多任务运行,但对于单核来说实际上任务在CPU上还是串行处理,而多核就可以由多核来实现并行处理,总体运行速度当然也得到提高。这样我们就可以对程序进行并行运算,我的想法是将数值范围缩小到2...31相乘然后除去特殊数,并且让i从高位数开始计算。这样可能会提高程序效率。那么如果以自己电脑作为参照,我的笔记本在内核版本是占优为双核,但是CPU频率2.5GHZ,按照这些来进行计算,并且考虑对于算法的优化,那么这个时间大约为2123581660200/(2.5*10^9 / 200)= 16984分钟。那么如果是一个双核4GHZ的CPU,这个时间应该将减少大约一半。
总结:
这次的作业如果要说学到了什么,那我就觉得我学到了如何去分析一个程序的条件以及如何把复杂的问题转换为简单,通过一层一层的分析,最终接近了问题的答案,这次的作业有很多地方是参照大神们的方法进行理解和求解的,当然也有自己思考为什么要这么去做?感觉这次的作业应该是对于问题求解的方法的思考,如果我们直接考虑问题的答案,那么我们估计很难通过程序运行得到最终的结果。如果方法得当结果应该自然就可以得到了,至于思考的结果应该是仁者见仁智者见智了,当然具体我们可以参考这篇文章http://blog.csdn.net/zhuhuiby/article/details/6742980,这篇博客对于作业的前三个问题做了详细的分析以及作答,我们当然想不到这么全面,但是大概的思路是值得我们借鉴和学习的。
C#编程之神奇程序找数的更多相关文章
- UC高级编程--实现myls程序
跟着达内视频,学习UC高级编程,完毕程序小练习. 主要练习的函数为: int lstat(const char *path, struct stat *buf); size_t strftime( ...
- AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题
AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子. 一 AOP的基本概念 (1)Asp ...
- JavaScript之父Brendan Eich,Clojure 创建者Rich Hickey,Python创建者Van Rossum等编程大牛对程序员的职业建议
软件开发是现时很火的职业.据美国劳动局发布的一项统计数据显示,从2014年至2024年,美国就业市场对开发人员的需求量将增长17%,而这个增长率比起所有职业的平均需求量高出了7%.很多人年轻人会选择编 ...
- vc++编程之在程序中加入网址链接
在vc++对话框编程中,我们处于某种需要(介绍自己的软件或者自己的博客)可以在对话框上增加一个网址链接,用户只要一点击,就进入了相应的网页,我在此演示下如何完成. 1 打开编译器,我们新建一个基于对话 ...
- Java经典算法四十例编程详解+程序实例
JAVA经典算法40例 [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 1.程 ...
- Linux shell编程02 shell程序的执行 及文件权限
第一个shell脚本 1. shell编程的方式 交互式shell编程 非交互式shell编程:执行的语句存放到一个文件 shell脚本:可以任意文件名,建议扩展名为sh 2. ...
- Socket编程之聊天程序 - 模拟Fins/ModBus协议通信过程
设备控制软件编程涉及到的基本通信方式主要有TCP/IP与串口,用到的数据通信协议有Fins与ModBus. 更高级别的通信如.net中的Remoting与WCF在进行C/S架构软件开发时会采用. 本篇 ...
- Linux 高性能服务器编程——高性能服务器程序框架
问题聚焦: 核心章节. 服务器一般分为如下三个主要模块:I/O处理单元(四种I/O模型,两种高效事件处理模块),逻辑单元(两种高效并发模式,有效状态机)和存储单元(不讨论). 服务器模 ...
- Linux 高性能服务器编程——Linux服务器程序规范
问题聚焦: 除了网络通信外,服务器程序通常还必须考虑许多其他细节问题,这些细节问题涉及面逛且零碎,而且基本上是模板式的,所以称之为服务器程序规范. 工欲善其事,必先利其器,这篇主要来探 ...
随机推荐
- JavaWeb基础—数据库连接池DBCP、C3P0
一.基本概念 数据库连接池负责分配.管理和释放数据库连接 数据库连接池:(池用map来实现居多) 用处:为了可重用(销毁创建麻烦,开销大)(招培训老师的例子) 二.编写实现数据库连接池 池参数: 初识 ...
- 【python3】酷狗音乐及评论回复下载
新年快乐,上班第一天分享一个python源码,功能比较简单,就是实现酷狗音乐的音乐文件(包含付费音乐)和所有评论回复的下载. 以 米津玄師 - Lemon 为例, 以下为效果图: 1.根据关键词搜索指 ...
- Unity3d之Hash&Slash学习笔记(一)--角色属性类的构架
角色属性类的构架 角色属性类有8个类,继承关系如下图: 每个类的具体作用见之后的随笔
- Codeforces 915 C. Permute Digits (dfs)
题目链接:Permute Digits 题意: 给出了两个数字a,b(<=1e18),保证a,b都不带前缀0.用a的字符重组一个数字使这个值最大且小于b.(保证这个值存在) 题解: 这题遇到了不 ...
- restful framework之频率组件
一.频率简介 为了控制用户对某个url请求的频率,比如,一分钟以内,只能访问三次 二.自定义频率类.自定义频率规则 自定义的逻辑 #(1)取出访问者ip # (2)判断当前ip不在访问字典里,添加进去 ...
- 如何为一个高负荷站点配置tomcat连接器(connector)【译文】(第一篇)
引言 最近正好要用到这些内容,因此就找了一篇比较有分量的文章,思来想去,还是尝试写一下译文吧.其实LZ的英语是非常烂的(四级没过的LZ眼泪掉下来),因此这篇文章翻译的水平LZ自己也不敢恭维.各位猿友大 ...
- VRRP+tunnel+IP SLA+Track实现冗余切换
IP SLA(Internet Protocol Service-Level Agreement)互联网服务等级协议,本实验里通过发送测试报文,测试下一跳是否可达,结合Track实现冗余静态路由的切换 ...
- 弄啥嘞?热爱你的Bug
有人喜欢创造世界,他们做了开发者:有的人喜欢开发者,他们做了测试员.什么是软件测试?软件测试就是一场本该在用户面前发生的灾难提前在自己面前发生了,这会让他们生出一种救世主的感觉,拯救了用户,也就拯救者 ...
- 行为事件(ActionChains)源码详解
ActionChains简介 actionchains是selenium里面专门处理鼠标相关的操作如:鼠标移动,鼠标按钮操作,按键和上下文菜单(鼠标右键)交互. 这对于做更复杂的动作非常有用,比如悬停 ...
- JUC——阻塞队列
Queue是一个队列,而队列的主要特征是FIFO先进先出,要实现生产者与消费者模型,也可以采用队列来进行中间的缓冲读取,好处是:生产者可以一直不停歇的生产数据. BlockingQueue是Queue ...