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服务器程序规范
问题聚焦: 除了网络通信外,服务器程序通常还必须考虑许多其他细节问题,这些细节问题涉及面逛且零碎,而且基本上是模板式的,所以称之为服务器程序规范. 工欲善其事,必先利其器,这篇主要来探 ...
随机推荐
- django的数据库配置-13
数据库配置 打开mysite下的settings.py文件 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NA ...
- MacOS下netstat和lsof使用的若干问题
[-= 博客目录 =-] 1-相关说明 1.1-博客介绍 1.2-netstat和lsof 2-学习过程 2.1-netstat 2.2-lsof 2.3-netstat和lsof区别和关联 3-资料 ...
- Noip前的大抱佛脚----文章索引
Noip前的大抱佛脚----赛前任务 Noip前的大抱佛脚----考场配置 Noip前的大抱佛脚----数论 Noip前的大抱佛脚----图论 Noip前的大抱佛脚----动态规划 Noip前的大抱佛 ...
- HDU - 5289 Assignment (RMQ+二分)(单调队列)
题目链接: Assignment 题意: 给出一个数列,问其中存在多少连续子序列,使得子序列的最大值-最小值<k. 题解: RMQ先处理出每个区间的最大值和最小值(复杂度为:n×logn),相 ...
- pathon之多线程详解
一.线程理论 1.什么是线程 线程指的是一条流水线的工作过程 进程根本就不是一个执行单位,进程其实是一个资源单位--------将资源集合到一起: 一个进程内自带一个线程,线程才是CPU上的执行单位 ...
- node的 node-sass@^4.11.0 出现:npm: no such file or directory, scandir '.../node_modules/node-sass/vendor'
解决办法: 查看node_modules文件夹,发现,并无vender 文件夹.如下图: 2. 在 node_modules/node-sass 下创建 vendor 文件夹 3. 最后运行: n ...
- Win10家庭版无法打开策略组问题
Win10家庭版无法打开策略组问题 • 复制以下代码至记事本中 @echo off pushd "%~dp0" *.mum >List.txt *.mum >>L ...
- 精确的double加减乘除运算工具类
import java.math.BigDecimal; /** * 精确的double加减乘除运算 * @author cyf * */ public class DoubleUtil { /** ...
- myeclipse激活后server不能用问题
一般是由于激活失败造成的,这种问题就卸了重新安装吧,目前还没有找到合理的方法解决,这个还真的看哥们的运气了,我是装了不下5遍才激活成功的,一般情况下,在激活的时候 出现下图的情况,Usercode写好 ...
- 【SIKIA计划】_03_C#初级教程 (2015版)笔记
Win32 API是微软的操作系统Windows提供给开发人员的编程接口,它决定了我们开发的Windows应用程序的能力.MFC是微软为开发人员提供的类库,在某种意义上是对Win32 API的封装.M ...