不是你逻辑思维不行,而是你的思维方式不一样。碰到一个问题,你的思维方式可能和熟练程序员的思维方式不一样。还有就是你的基础知识不够好,不要以为编程只要会C++,JAVA就可以了,这只是很小而且很不重要的一方面。
想要做程序员,首先要达到抛弃语言的境界,也就是纯思想编程。等你达到这个境界,才可以称的上真正入门。
你需要:
很聪明,大脑灵活
严密的逻辑分析能力,就象柯南
不错的数学造诣,这个很重要
普通的书面英语能力,(建议要不错的书面英文能力)编程的词汇总不能看不懂吧,而且大量的资料都是英文的。
楼上的几位说的都非常好,就是有点看不懂,我就写一个比较通俗一点的。
你写程序的时候有没有发现,没一个流程都是很清晰的,比如:在哪里判断,判断条件是什么?几个分支?在哪里循环,循环条件是什么?循环多少次?
就是没一条都列出来,可以一条条的说出来,很有条理。如果还不懂,那就举个更通俗的例子:
1.有一个问题,悬赏20分。A回答 B不回答
2.选择回答(因为有时间有精力) 接下来看看别的回答的怎么样,如果有很优秀的答案,就不浪费口舌。
3.发现没有很优秀的,所以回答。以一种通俗的方式。
4.有可能通俗的方式也不够清晰,所以举一个更通俗的例子。
5.return 0.
计算机编程能很好地锻炼逻辑思维能力
计算机软件编程需要细心、耐心等品质,计算机语言的精确性要求编程者要具备非常严密的逻辑思维。所以经常进行计算机编程的人往往逻辑能力很强,解决实际问题的思路很清晰,并且思维品质很好。
基础学得再好,没有一个成熟的思维那也没用.
因为你根本就没法应用它.
对于一个有C经历而学C++的话,更多的是学习"思想".
很多程序编的好的人数学都很好,这是因为:数学好,逻辑必然强! 有人会说,那我数学差,逻辑就差,不适合编程么…… 不是的! 逻辑好未必数学好,数学差未必逻辑差……
要边学基础,边编写一些小程序试试,经验和所谓的逻辑思维是建立在牢固的基础和大量的实践基础上的
逻辑思维,我觉得就是遇到问题的想法和解决问题的办法。应该指的是一个人的理性方面吧!条条大路通罗马,问题出现了:解决问题的办法真的是很多种啊,笨人有笨法,懒人有懒法,聪明人呢?当然有巧法!
编程员是个苦力活! 你基础好,编程就是苦力活,但是基础差,就是脑力加苦力! 你选择哪一个
李开复大学时代时,两年编程量10万行! 这就是基础!
编程没有捷径,有的只是锻炼出来的思想和经验!
逻辑思维训练 一(2005-9-20 21:03:00)【收藏】 【评论】 【打印】 【关闭】
标签:逻辑,分析,编程
题目要求:
对6个嫌疑犯进行分析,
(1)A,B至少一人做案
(2)A,E,F三人至少 2人作案
(3)A,B两人不可能是同案犯
(4)B,C或同时作案或与本案无关
(5)C,D有且仅有一人作案
(6) 如果D没参与作案,则 Z也不可能参与作案
通过编程说出嫌疑犯是谁。
算法分析:
按照条件:4->5->6,2->3得出结果。
即:BC去->D不去->A去、E不去->F去
BC不去->D去->A不去、E去->F去
代码:
#include
void main()
{
int a[6];
int n,i;
printf("请设计B的假设值(0为不去,1为去)->:");
scanf("%d",&n);
a[1]=n;
if(a[1]==1)a[2]=1;
else
if(a[1]==0)a[2]=0;
if(a[2]==0)a[3]=1;
if(a[2]==1)a[3]=0;
if(a[3]==0){a[0]=1;a[4]=0;}
if(a[3]==1){a[0]=0;a[4]=1;}
if(a[0]==1&&a[4]==0)a[5]=1;
if(a[0]==0&&a[4]==1)a[5]=1;
printf("A,B,C,D,E,F\n");
for(i=0;i<6;i++)
printf("%d,",a);
}
结果:
(1)ABC不是罪犯,DEF是罪犯
(2)ABCF是罪犯,DE不是罪犯
要把握内在逻辑结构,首先你要对事物的宏观结构有个把握,这就像如果你要画一张主题确定的油画,你首先要大致把主要事物之间的结构排好,先搞清整体框架,然后再慢慢填充内在。
发言也是一样的,你首先要搞清自己的中心,然后哪几个命题是为你这个核心论点服务的,又应该以什么样的顺序来阐述它们。而不是信马由缰想到哪儿说到哪儿,那样叫漫谈扯淡,鬼才知道你会扯到哪里去。
所以你要有图形想象力,如果你看不清自己要把握的几个论点之间的关系,唯一的办法就是走出去,站高点,然后从上往下看。
走进迷宫去绘制迷宫地图不是不可能,但是太费劲,还要用到一大堆测距和记录工具,而如果你从飞机上俯瞰,你只需要拍张照片,然后一目了然。
我对Java的面向对象的特性琢磨良久,自认为有所领悟,也开始有意识的运用OOP风格来写程序,然而还是经常会觉得不知道应该怎样提炼类,面对一个具体的问题的时候,会觉得脑子里千头万绪的,不知道怎么下手,一不小心,又会回到原来的思路上去。
举个例子,要发广告邮件,广告邮件列表存在数据库里面。倘若用C来写的话,一般会这样思考,先把邮件内容读入,然后连接数据库,循环取邮件地址,调用本机的qmail的sendmail命令发送。
然后考虑用Java来实现,既然是OOP,就不能什么代码都塞到main过程里面,于是就设计了三个类:
一个类是负责读取数据库,取邮件地址,调用qmail的sendmail命令发送;
一个类是读邮件内容,MIME编码成HTML格式的,再加上邮件头;
一个主类负责从命令读参数,处理命令行参数,调用发email的类。
把一件工作按照功能划分为3个模块分别处理,每个类完成一件模块任务。
仔细的分析一下,就会发现这样的设计完全是从程序员实现程序功能的角度来设计的,或者说,设计类的时候,是自低向上的,从机器的角度到现实世界的角度来分析问题的。因此在设计的时候,就已经把程序编程实现的细节都考虑进去了,企图从底层实现程序这样的出发点来达到满足现实世界的软件需求的目标。
这样的分析方法其实是不适用于Java这样面向对象的编程语言,因为,如果改用C语言,封装两个C函数,都会比Java实现起来轻松的多,逻辑上也清楚的多。
我觉得面向对象的精髓在于考虑问题的思路是从现实世界的人类思维习惯出发的,只要领会了这一点,就领会了面向对象的思维方法。
举一个非常简单的例子:假使现在需要写一个网页计数器,客户访问一次页面,网页计数器加1,计数器是这样来访问的
后台有一个数据库表,保存每个id(一个id对应一个被统计访问次数的页面)的计数器当前值,请求页面一次,对应id的计数器的字段加1(这里我们忽略并发更新数据库表,出现的表锁定的问题)。
如果按照一般从程序实现的角度来分析,我们会这样考虑:首先是从HTTP GET请求取到id,然后按照id查数据库表,获得某id对应的访问计数值,然后加1,更新数据库,最后向页面显示访问计数。
现在假设一个没有程序设计经验的人,他会怎样来思考这个问题的呢?他会提出什么样的需求呢?他很可能会这样想:
我需要有一个计数器,这个计数器应该有这样的功能,刷新一次页面,访问量就会加1,另外最好还有一个计数器清0的功能,当然计数器如果有一个可以设为任意值的功能的话,我就可以作弊了。
做为一个没有程序设计经验的人来说,他完全不会想到对数据库应该如何操作,对于HTTP变量该如何传递,他考虑问题的角度就是我有什么需求,我的业务逻辑是什么,软件应该有什么功能。
按照这样的思路(请注意,他的思路其实就是我们平时在生活中习惯的思维方式),我们知道需要有一个计数器类 Counter,有一个必须的和两个可选的方法: getCount()
// 取计数器值方法
resetCounter()
// 计数器清0方法
setCount()
// 设计数器为相应的值方法
把Counter类完整的定义如下:
public class Counter
{
public int getCount(int id)
{
}
public void resetCounter(int id)
{
}
public void setCount
(int id, int currentCount)
{
}
}
解决问题的框架已经有了,来看一下如何使用Counter。在count.cgi里面调用Counter来计数,程序片断如下:
// 这里从HTTP环境里面取id值
...
Counter myCounter = new Counter();
// 获得计数器
int currentCount = myCounter.getCount(id);
// 从计数器中取计数
// 这里向客户浏览器输出
...
程序的框架全都写好了,剩下的就是实现Counter类方法里面具体的代码了,此时才去考虑具体的程序语言实现的细节,比如,在getCount()方法里面访问数据库,更新计数值。
从上面的例子中看到,面向对象的思维方法其实就是我们在现实生活中习惯的思维方式,是从人类考虑问题的角度出发,把人类解决问题的思维方式逐步翻译成程序能够理解的思维方式的过程,在这个翻译的过程中,软件也就逐步被设计好了。
在运用面向对象的思维方法进行软件设计的过程中,最容易犯的错误就是开始分析的时候,就想到了程序代码实现的细节,因此封装的类完全是基于程序实现逻辑,而不是基于解决问题的业务逻辑。
学习JDBC编程的经典错误问法是:“我怎样封装对数据库的select操作?”
面向对象的设计是基于解决业务问题的设计,而不是基于具体编程技术的设计。我不会去封装select语句的,我只封装解决问题的业务逻辑,对数据库的读取是在业务逻辑的编码实现阶段才去考虑的问题。
回过头看上面那个发广告邮件的例子,应该如何应用面向对象的思维方法呢?
对于一个邮件来说,有邮件头,邮件体,和邮件地址这三个属性,发送邮件,需要一个发送的方法,另外还需要一个能把所有邮件地址列出来的方法。所以应该如下设计:
类JunkMail
属性:
head
body
address
方法:
sendMail()
// 发送邮件
listAllMail()
// 列邮件地址
用Java来表示:
public class JunkMail
{
private String head;
private String body;
private String address;
public JunkMain()
{
// 默认的类构造器
// 从外部配置文件读邮件头和邮件体
this.head=...;
this.body=...;
}
public static boolean
sendMail(String address)
{
// 调用qmail,发送email
}
public static Collection listAllMail()
{
// 访问数据库,返回一个邮件地址集合
}
}
当把JunkMail设计好了以后,再调用JunkMail类完成邮件的发送,将是非常轻松的事情。
如果说传统的面向过程的编程是符合机器运行指令的流程的话,那么面向对象的思维方法就是符合现实生活中人类解决问题的思维过程。
在面向对象的软件分析和设计的时候,要提醒自己,不要一上来就去想程序代码的实现,应该抛开具体编程语言的束缚,集中精力分析我们要实现的软件的业务逻辑,分析软件的业务流程,思考应该如何去描述和实现软件的业务。毕竟软件只是一个载体,业务才是我们真正要实现的目标。
但是在设计过程中,心里却往往在担心,如果我完全不去考虑程序代码的实现的话,那么我怎么知道我的设计一定合理呢?我怎么知道我设计的类、接口一定可以实现呢?所以经常可以看到的现象就是:
在设计过程中,虽然知道不能过早考虑代码实现,但是每设计一个类,一个接口,心里都要不知不觉的用自己熟悉的编程语言大概的评估一下,看看能否编出来,因此,一不小心,就会又回到按照程序功能实现的思路进行设计的老路上去了。
举个例子来说明,在做Web程序设计的时候,经常要遇到分页显示数据的情况。比如说需要把系统中所有的用户都列出来这样的功能。假设使用User类来表示用户,增加用户addUser(),删除用户deleteUser(),查询所有用户listUsers()方法。而数据库中有一个user表,一条记录是一个用户的信息。下面考虑一下User类的方法的实现:
addUser()和deleteUser()方法都好实现,就是对数据库增加记录和删除记录。对于listUsers()方法,其实就是对user表的select,取出一个记录集。但是该怎么从listUsers()方法中得到所有用户的列表呢?
一个方法调用的返回值只有一个,没有多个,所以很多情况下采用的办法就是返回值定义为集合类型,比如Vector。这样就可以在listUsers()方法的具体代码实现的时候,从数据库依次取出一个个记录,插入到Vector里面来。在主程序里面,调用listUsers()方法可以返回一个Vector,然后再对Vector遍历操作,就可以得到用户列表了。
public class User
{
public static void addUser(...)
{
// 数据库insert一条记录
}
public static void deleteUser(...)
{
// 数据库delete一条记录
}
public Vector listUsers(...)
{
// 数据库select结果放到一个集合里面
}
}
这样的设计基本合理,但是仍然有点小问题。因为在设计的时候,就考虑到了用Java的集合类Vector来实现对不定长数据集的存放,因而违反了面向对象设计的一个原则:在设计的时候不应过早的考虑具体程序语言的实现。所以必须用抽象的方法,和具体实现无关的方法来表达业务逻辑。
我们知道,通常对具有集合特征的数据结构进行遍历通常可以使用next和hasNext方法,next实现取下一个用户,hasNext判断是否还有元素。 因此我们定义一个接口Iterator,这个接口中定义两个方法next和hasNext:
public interface Iterator
{
public boolean hasNext()
{
}
public Object next()
{
}
}
而User类的listUses方法返回值
改为Iterator接口的实现类:
public class User
{
...
public Iterator listUsers()
{
}
...
}
因为普遍来说他们的逻辑感强,思维缜密,做事周到,而这些能力在实际生活中是相当重要的。
软件编程与数学思维发布
《消费导刊》(CN11-5052/Z, ISSN 1672-5719)原名《中国轻工业经济》,曾入选《中文核心期刊要目总览》(1992版)(1996版)
湖北工业大学理学院 张水坤
[摘 要]近年来,学科的高速发展已经明确地反映出这样一个特点:学科基础研究和技术开发越来越多地同数学建立更为紧密的联系,对各种数学工具的使用不仅越来越广泛,而且越来越深入。要掌握好软件编程,数学思维是非常重要的。先讨论软件编程与数学的联系,再以一些具体的代码作为例子,结合实际经验谈点看法。
[关键词]软件编程 数学思维 耦合性
中图分类号:O14 文献标识码:A 文章编号:1002—6908(2007)0420
一、引 言
数学是一门工具性很强的科学,它与别的科学比较起来还具有较高的抽象性等特征。起初是计算机科学工作者离不开数学,而数学工作者认为计算机对他们可有可无,但是现在是互相都离不开对方了,计算机也提高了数学工作者在人们心目中的地位,大部分的数学工作者开始认识到计算机的重要性,并越来越多地进入到计算机领域发挥作用。但是随着人工智能、GPS(全球定位系统)等飞速的发展和计算机运算性能飞跃性的提升,计算机的优势越来越深入到思维领域,于是计算机将高深的数学理论用到实际中来,十分有效地解决了许多实际问题,例如著名难题四色问题就是被计算机证明的。问题的求解过程中有许多具有实用价值的数学分支如分析几何、小波分析、离散数学、仿生计算、数值计算中的有限单元方法等。它让人们知道计算机程序设计结合的就是数学知识和数学思想。
软件编程是基于数学模型的基础上面的,所以,数学是计算机科学的主要基础,以离散数学为代表的应用数学是描述学科理论、方法和技术的主要工具。软件编程中不仅许多理论是用数学描述的,而且许多技术也是用数学描述的。从计算机各种应用的程序设计方面考察,任何一个可在存储程序式电子数字计算机上运行的程序,其对应的计算方法首先都必须是构造性的,数据表示必须离散化,计算操作必须使用逻辑或代数的方法进行,这些都应体现在算法和程序之中。此外,到现在为止,算法的正确性、程序的语义及其正确性的理论基础仍然是数理逻辑,或进一步的模型论。真正的程序语义是模型论意义上的语义。于是软件编程思想运行的严密性、学科理论方法与实现技术的高度一致是计算机科学与技术学科同数学学科密切相关的根本原因。从学科特点和学科方法论的角度考察,软件编程的主要基础思想是数学思维,特别是数学中以代数、逻辑为代表的离散数学,而程序技术和电子技术仅仅只是计算机科学与技术学科产品或实现的一种技术表现形式。
二、软件编程与数学思维的联系
(一)数学在计算机领域的发展
如今形形色色的软件,都与数学有必然的联系,它们相互相成。例如,逻辑学在学科中的应用从早期的数理逻辑发展到今天的程序设计模型论;数学在学科中的应用从早期的抽象代数发展到今天的图形学、工程问题方面;几何学的应用从早期的二维平面计算机绘图发展到今天的三维动画软件系统,并在与复分析的结合中产生了分形理论与技术;在游戏、图形软件开发中引用了线性代数中大量的坐标变换,矩阵运算;在数据压缩与还原、信息安全方面引入了小波理论、代数编码理论等。
(二)软件编程的思维定式
软件编程的思维定式决定了一个人编程的水平,在编程过程中,数学思维清晰,编写出来的程序让人耳目一新。结合教学,通过调查分析,了解到超过85%的学生,他们在编程时是根据语法而编写程序,完全脱离了软件编程的思维,这种思维定式使得他们编写的程序相当糟糕,没有一点逻辑。
之所以造成这种软件编程的思维,是因为他们平时对数学思维的培养不够重视。很多学计算机的学生想:学高数,这有什么用?学线性代数有什么用?学离散数学,有什么用?于是他们很少去上这些课,马马虎虎,整天闷在寝室里,玩玩游戏,装装软件,看看C语言。只知道概率问题和矩阵知识在其它课程上起到了互补作用,学的不是很深。但是当他们看到<<数据结构和算法>>时,感到其中的内容对他们而言感觉相当的艰涩难懂,这时他们就隐约感觉到了数学思维的作用了。在此之前,他们不仅荒废了大学的高等数学,连初中的初等数学也忘的好多,当他们进行高抽象思维时,确实感觉自己的思维已经很迟钝了。学计算机的学生之所以觉得《数据结构》这门课程很难,就是因为他们的数学思维锻炼的不够!其实生活中有很多这样的例子:对于一个刚毕业的,编应用软件的大学生,在编程中用到《线性代数》的矩阵时,恐怕便会想,在大学把线性代数学好就好了;当在程序中用到动态链表、树时,恐怕也会想“在大学时花点时间去学《数据结构》,会多么的有意义”;当学数据结构时,恐怕也会想“学《离散数学》时为什么要逃那么多的课,要不然学离散的时候就会很轻松”。所以数学思维不够,在软件编程会有很多的疑虑,显的有点缩手缩尾,而且写的程序也不够健全,缺乏逻辑。
(三)软件编程与数学思维的融合
很多专业人士觉得数学和软件编程能力就像太极和拳击,软件编程能力很强就好比出拳速度很快很重,能直接给人以重击;数学很好的话就好像一个太极高手,表面上看没有太大的力量但是内在的能量是更强大的,但是好的拳击手是越年轻越好,而太极大师都是资历越深越厉害。所以数学是成就大师的必备能力,虽然很多学生看上去感觉没有什么用途,但是到了一定的水平之后就会体会它的力量了。
三、数学思维在软件编程中的应用
目前很多出名的IT公司在笔试的时候,都会在程序设计题中考察应聘者的数学思维能力,因此,这应该引起广大学生在平时的学习中注意锻炼自己的数学思维,有机会的话参加一下数学建模比赛,你便会有很深刻的体会---原来数学和计算机结合得这样紧密。下面典型的代码,在设计过程中充分的运用了数学思维。
题目一:从3个红球,5个白球,6个黑球中任意取出8个球,且其中必须有白球,输出所有可能的方案。
程序一:
#include "stdio.h"
void main()
{
int i,j,k; //I代表红球,j代表白球,k代表黑球
printf("\n red write black\n");
for(i=0;i<=3;i++)
for(j=1;j<=5;j++) //j=1是因为题目中要求必须要有白球
{
k=8-i-j; //黑球的个数
if(k>=0&&k<=6)
{
printf("%3d,%3d,%3d",i,j,k); //输出组成方案
}
}
}
从上面的例子中我们可以隐隐知道数学思维在软件编程中的应用。尽管学习数学带给计算机专业人士的回报大过常人,但现今社会里每个人都能由此受益,是让人们提高自己思维能力,变得聪颖的绝佳方法。这种思维能力能让人们在各方面受益!但实际上,数学上功底扎实,在软件编程上的优势尽显,项目的设计模式格外地优化,程序逻辑条理也格外地清晰。因为数学可以培养人的逻辑思维能力,而程序设计需要很强的逻辑思维能力。
这些让我们深刻的体会到数学思维与软件编程的耦合性,其实我们国家的计算机软件水平的落后不是因为我们缺少程序员,而是因为缺乏懂数学的高质量的程序员。一个具有数学修养的程序员在写代码时更有可能写出逻辑严密的最简化的高质量代码。而目前一些龙头IT公司,比如微软公司总裁比尔·盖茨年青时就对数学很痴迷,而他们的项目经理,必须得具备超强的数学思维,而且有些还是数学专业的博士,从这也可以看出微软公司对于数学人才的重视程度。
四、结束语
软件编程的思想最重要是算法,而算法是建立在数学思维上的,其实说白了,程序只是一件衣服,算法才是它的灵魂,算法就来自于数学,没有深厚的数学思维功底,是弄不懂算法的。所以,如果你想从事软件编程,那么就认真的培养自己的数学思维吧!
文章评论(0条评论)
登录后参与讨论