|
2008年1月1日
偶然发现了盛大的maiku, 是一个不错的日志和资源整理平台。于是转向了它,地址是 http://note.sdo.com/u/dongwq
欢迎来看看。
• 前者:看见与不看见,但是位置保留。
• 后者处理与位置有关:block, inline, none 分别是有前后换行,不换行,不显示功能但是不保留位置。
• 二者功能差异:保留位置,和位置形式
<script language="javascript">
function toggleVisibility(me)
{
if(me.style.visibility=="hidden")
{
me.style.visibility="visible";
}
else
{
me.style.visibility="hidden";
}
}
</script>
<DIV onclick="toggleVisibility(this)"
style="position:relative">
第一行文本将会触发"hidden"和"visible"属性,注意第二行的变化。
</DIV>
<DIV>因为visibility会保留元素的位置,所以第二行不会移动.</DIV>
<script language="javascript">
function toggleDisplay(me){
if(me.style.display=="block"){
me.style.display="inline";
alert("文本现在是:'inline'.");
}
else{
if(me.style.display=="inline"){
me.style.display="none";
alert("文本现在是:'none'.3秒钟后自动重新显示。");
window.setTimeout("blueText.style.display='block';",
3000,"javascript");
}
else{
me.style.display="block";
alert("文本现在是:'block'.");
}
}
}
</script>
<DIV>在<span id="blueText"
onclick="toggleDisplay(this)"
style="color:blue;position:relative;cursor:hand;">
蓝色</span>文字上点击来查看效果.</DIV>
摘要: 1 . 日志的组成:配置文件,写日志
log.cfg
############################################################
# Default Logging Configuration File
#
# You&nbs... 阅读全文
文章分类:软件开发管理
副标题——名不正言不顺,项目管理难度加倍
你能想象美国总统上任,却没有总统就职仪式吗?
你能想象北京奥林匹克运动会,没有开幕式表演吗??
OK。相信你一定见过这样的场景:
某老板匆匆忙忙地进了屋,忽地来了一嗓子:“大家静静,通知大家一下:以后,某项目就由小张负责了!”
**************************************************
话说楚汉相争。刘邦在萧何的再三举荐下,决定让韩信为大将。
“来人,叫韩信过来,我要封他为大将。”刘邦道。
萧何表示异议:“汉王你一向傲慢没有礼貌,现在拜大将就和喊一个小孩子那么随便,所以韩信才会离开的。汉王要想用人家,必须选一个吉日,吃素,设祭坛,用非常郑重地礼节来拜将才行。”刘邦同意萧何的意见。
结果,尽管韩信是个无名小卒,却顺利的接过了军权,而没有碰到那些元老们的抵抗,成功地导演了一幕幕战争奇迹。
**************************************************
登台拜将,是一件具有深刻管理内涵的故事。它告诉我们这样一个道理:
——内容是重要的,但形式却是不容忽视。
我们不求老板非要在某个公开场合悠扬地宣告:“某项目成立了!!小张从此站起来了!!!”什么吉日,什么斋戒,什么礼仪。。。也就罢了。
但是,不给正式任命书;不在正式场合公布;甚至连一个头衔都舍不得。这绝对是没天理的。
**************************************************
“看,老板不重视这个项目。。。”(相关人员)
“瞧,老板不重视这个家伙。估计这个家伙没有什么后台” (相关人员)
“你负责某项目?我怎么不知道有这么个项目呢?你是哪位啊?” (相关人员)
“老板似乎并不重视/信任我啊” (项目经理)
***************************************************
以上种种,对项目的推动极为不利的。尤其是手下有资深员工、或者项目经理候补者等挑战者的时候,问题将会加倍严重。
大家可能会怀疑:“没有那么严重吧?”
没有不严重,只有更严重!!
这其中蕴含着一个深刻的道理——名不正则言不顺!!
言不顺是什么意思呢?
-你的意见可能被忽视;
-你的命令可能被当作建议;
-你的计划可能被别人忘记;
试想,你如果是项目经理,你的项目将会怎样。。。。。。
*********************************************************
Question: 我没有办法叫老板改变。那么,我该怎么办?
Answer:要写一封邮件!!告诉别人你是谁。
*********************************************************
你的老板犯了错误,可是你不能将错就错!你的老板忽视了“名”的问题(形式问题),你一定要扳回来!!
试想,你的老板不重视,你也不重视,你能指望别人重视吗??
当然,答案就是别人会更不重视!!
那么,这封邮件该怎么写呢??
**************************************************
MailTo: 所有下属
CC: 所有相关领导,所有相关人员,自己
Title: 【A项目】A项目的新项目经理小张向大家问好
Content:
1 开门见山地告诉别人自己的位置(正名)
2 向相关人员致敬,并自然地点出自己的优势(自我介绍)
3 向领导致敬致谢(拉近和领导关系)
4 暗示自己的权利范围(宣布自己的领地)
5 喊两句口号(合作和积极的姿态是必要的)
6 不要忘了签名(进一步加深印象)
//其中,1、2、4是必须要表现出来的
**************************************************
上面这封邮件,基本上完成了告诉别人你是谁的问题,而且完成了你的位置身份暗示。
如果说老板不负责任的任命形式带给你身份位置认同危机,沉重打击了你的威信的话,
通过这份邮件,你已经用身份暗示这个武器,夺回了主动权!!
从这封信以后,由于你的身份位置的明确,
相关人员在潜意识中会认同你的领地所有权,
会对在你的领地上和你发生冲突产生不自然,不合法甚至负罪感,
从而下意识中就会避免和你发生冲突。
反过来讲,你的位置身份的明确,将成为你自信的源泉,
而这种位置感产生的自信将使你的发言充满了正义感,
加上项目经理这个位置所带来的小小的势能。。。
权力这个东西,真好!!
嗯,一个好的开端,不是吗?
1、函数定义和使用
<script>
function sqrt(x) {
return x * x;
}
function other(f) {
var y = f(10);
return y;
}
var farr = new Array();
farr[0] = function(arg) { return arg + arg;};
farr[1] = function(arg) { return arg * arg;};
document.write(farr[0](10) + '<br/>');
document.write(farr[1](10));
document.write(other(sqrt));
</script>
sqrt.count = 0;
sqrt.getcount = function() {
return this.count;
}; // 附加函式
//sqrt();
document.write(sqrt.count, '<br/>');
document.write(sqrt.getcount());
杜拉拉升级记:
关键一点,你的上级要喜欢你。工作中涉及要决策的都要跟上级报告。这是上级的作用。
对于平级的同事是不能用命令,不能要求别人做事的。
事情不能自己承担下来。
感谢小熊同学借我这本书看
说说我的感受:此书没有书评中说的那么好,当然也没有那么坏。大家各取所需就好。与其叫小说,不如说是一种创新形式的职场教材。不要太去在意作者的文笔,而要更多的体会书中各位同学的处事之道。
几句话总结一下:
1、勤奋是王道,其他的都属于EQ范畴了
2、要注意技巧,尤其是沟通技巧,别干了半天,没人知道你的工作量有多少。
3、掂量自己的能力,做好该做的事,不做不该做的事,比如越级汇报。
4、不要说人坏话,能帮助别人时要帮,关键时刻即使没有人帮你说话,但也不会有人说你的坏话。不信的话,去看看圣经怎么说得吧。
5、要有气量,做事要圆通。
6、要有自己的风格,风格没有好坏之分,但是一定要有。
7、告诉我们什么是好工作,这点比较长,见下面的摘抄(感谢“木马|造化弄人”的贡献):
“一、关于什么样的职位算好职位
1.你得找一家好公司
什么是好公司?
1)产品附加值高,生意好,并且从业务线看,具备持续发展的能力和前景;
2)有专业的/聪明能干的/经验丰富的/并且为人现实的管理层,在把握这公司,并且有保护一贯这样用人的制度的公司;
3)有严格的财务制度,对预算、费用和利润等于投入产出有关的内容,敏感并且具有强控制力的公司;
4)崇尚客户导向/市场导向/结果导向/执行力的公司;
5)有专业严谨全面的流程和制度,并且其执行有利于推动业务的良性发展,具有控制性和实操性兼备的特点;
---总结起来,就是一家具有持续赢利能力的牛B公司
2.你的找一个好的方向
什么是好的方向?
永远不要远离核心业务线。你得看明白,在企业中,哪个环节是实现利润最大化的关键环节。有时候是销售环节,有时候是市场策划环节,有时候是研发环节,有时候是生产环节,视乎你所在行业而不同。
最重要的环节,总是 最贵的,最牛的,最得到重视的,也是最有发展前途的部门。它拥有最多的资源和最大的权威--你应该依附在这样的核心业务线上发展,至少能避免被边缘化,而成为关键人才的可能性则更大了。
3.你得跟一个好老板。
好老板的标准很多,关键的是,你要设法跟上一个在公司处于强势地位的老板。他强,你才能跟着上。跟了一个弱势的老板,你的前途就很同意被根着给耽搁了。
二、关于具备谋取好职位的资格
要具备怎么样的资格呢?一般情况下,你得是用人部门眼中的优秀者。
怎么样才算优秀呢?
1.对上级
1)你要知道与他建立一致性,他觉得重要的事情,你就觉得重要,他认为紧急的事情你也认为紧急,你得和他劲往一处使--通常情况下,你得表现和能力好还是不好,主要是你得直接主管说了算的;
2)你的具备从上级那里获得支持和资源的能力--别你干的半死,你的老板还对你爱搭不理的,那你就不具备本条件的能力。
2.对下级
1)要能明确有效的设置正确的工作目标,使其符合SMART原则;
2)要能有效地管理团队内部冲突;
3)要能公平合理地控制分配团队资源;
4) 要有愿望和能力发展指导下属,并恰当授权;
5)恰当的赞扬鼓励认可团队成员;
6)尊重不同想法,分享知识经验和信息,建立信任的氛围。
3.对内、外部客户
1)愿意提供协助和增值服务(不然要你干嘛);
2)善意聆听并了解需求(搞明白人家需要的到底是啥);
3)可靠的提供产品和服务,及时跟进(千万注意及时);
4)了解组织架构并具影响力。及早地建立并维护关键的关系,是这样的关系有利于你达成业绩(专业而明智的选择);
比如你想取得一个内部职位,你的搞明白了,谁是关键的做决定的人物,别傻乎乎不小心给这个人留下坏印象。
比如必要去客人那里拿订单,你找了一个关键的人物A,可是你也别忽略作购买决定环节上的另一个人物B,没准B和A是死敌,本来B会同意给你下订单的,就因为A同意给你单子,B就是不同意给你单子。
4.对本岗任务
1)清楚自己的定位和职责--别搞不清楚自己是谁,什么是自己的活,知道什么该报告,什么要自己独立做决定;
2)结果导向--设立高目标,信守承诺,承担责任,注重质量、速度和期限,争取主动,无需督促;
3)清晰的制定业务计划并有效实施;
4)学习能力--愿意学,坚持学,及时了解行业趋势/竞争状况和技术更新,并学以致用;
5)承受压力的能力--严峻的工作条件下,能坚忍不拔,想办法获取资源、支持和信息,努力以实现甚至超越目标;
6)适应的能力--如适应多项要求并存,优先级变换以及情况不明等工作条件,及时调整自己的行为和风格来适应不同个人及团队的需要(工作重心会变化,老板会换人,客人也会变,别和他们说“我过去如何如何”,多去了解对方的风格) ”。
方与圆:
最少期望的去感谢别人。不要抱着目的去感谢别人,甚至事前感谢也好。感谢只需说一次。
发掘别人不明显的优点加以赞扬。
赞扬行动和品性,而不要扩大到赞扬一个人。赞扬的原因要说明。
和气生财吗?喝杯水。
对陌生人要特别要笑。微笑是影响人气质的一个特别重要的东西。
对生活的真诚,快乐的感情最能够打动人。 男的微笑也很好。
认真的品质:画一个月和十年。
组装的质量差?认真的态度。德国人的认真,指路会指出的很具体的。
只有最认真的人才能做出最好的产品。
自动自发的精神,一定要发挥自己的主观能动性。
当成自己的事来做吧。要主动的来做。
做好产品是人的一种尊严。争强好胜在自己的工作上面。因为这是你的发挥场地。
只办总裁班?成本与质量观念不一样的? 规模经济?质量了的产品成本会降低。
检查的目的是为了改进生活流程。
管制图?
困定的供货商?不是投标。是指定方式做。
永远追求持续不断的完善。
有必要再试一次。
改进自己的产品吧。
也淘汰了自己的竞争者。 一个系列的生产方式是不错的。
到外去演讲,不做化疗?活过了三年?
要有自己的追求。活就要活出自己的价值。无论在何时的年龄,都要有自己的追求。
人生不是直线的,是C型的人生。
人生可以随时开始。
<设计模式:java语言中的应用>摘要、总结 收藏
<设计模式:java语言中的应用>一书已经学完,现做个摘要、总结。
创建模式(Creational Patterns)
Abstract Factory Builder
Factory Method Prototype
Singleton
结构模式(Structural Patterns)
Adapter Bridge
Composite Decorator
Facade Flyweight
Proxy
行为模式(Behavioral Pattern)
Chain of Responsibility Command
Interpreter Iterator
Mediator Memento
Observer State
Strategy Template Method
Visitor
一、创建模式(Creational Patterns)
1.Abstract Factory(抽象工厂)—把相关零件组合成产品
Abstract Factory Pattern 是把各种抽象零件组合成抽象产品。换句话说,处理的重点是在接口(API)而不是零件的具体实现。只利用接口(API)就能把零件组合成产品.
程序示例:
--Main.java 测试用的类
|-factory
| |-------Factory.java 表示抽象工厂的类(产生Link,Tray,Page)
| |-------Itme.java 用来统一处理Link和Tray的类
| |-------Link.java 抽象零件:表示HTML连接的类
| |-------Tray.java 抽象零件:抽取Link和Tray的类
| |-------Page.java 抽象零件:表示HTML网页的类
|
|-listfactory
|-------listFactory.java 表示具体工厂的类(产生ListLink,ListTray,ListPage)
|-------listLink.java 具体零件:表示HTML连接的类
|-------listTray.java 具体零件:抽取Link和Tray的类
|-------listPage.java 具体零件:表示HTML网页的类
步骤:定义抽象零件->用抽象零件定义抽象工厂->定义具体零件(继承实现抽象零件)->定义具体工厂(继承实现抽象工厂,制造实际产品)
2.Factory Method
Factory Method Pattern 在父类规定对象的创建方法,但并没有深入到较具体的类名.所有具体的完整内容都放在子类.根据这个原则,我们可以大致分成产生对象实例的大纲(框架)和实际产生对象实例的类两方面.
程序示例:
--Main.java 测试用的类
|-framework
| |-------Product.java 仅定义抽象方法use的抽象类
| |-------Factory.java 规定createProduct,registerProduct,实现create的抽象类(类似模板方法)
|
|-idcard
|-------IDCard.java 实现方法use的具体类
|-------IDCardFactory.java 实现方法createProduct,registerProduct的类
步骤:定义抽象产品->根据抽象产品定义抽象工厂->定义具体产品(继承实现抽象产品)->定义具体工厂(继承实现抽象工厂,制造实际产品)
3.Singleton(单件)-唯一的对象实例
Singleton Pattern 是针对一个类而言. Singleton类只会产生1个对象实例.Singleton类把singleton定义为static字段(类变量),再以Singleton类的对象实例进行初始化.这个初始化的操作仅在加载Singleton类时进行一次.
Singleton类的构造函数是private的,主要是为了禁止从非Singleton类调用构造函数.即使下面这个表达式不在此类之内,编译时仍然会出现错误.
程序示例:
|--Main.java 测试用的类
|--Singleton.java 只有1个对象实例的类
步骤:定义一个该类类型的static字段,同时实例化->该类的构造方法设为private->定义一个static的getInstance()方法,返回已经实例化的static字段.
4.Builder(生成器)-组合复杂的对象实例
Builder Pattern 是采用循序渐进的方式组合较复杂对象实例的.
程序示例:
|--Main.java 测试用的类
|--Builder.java 规定建立文件时的方法的抽象类
|--Director.java 产生1个文件的类
|--TextBuilder.java 产生plaintext格式(一般文本格式)的类
|--HTMLBuilder.java 产生HTML格式的类
步骤:定义建立文件时的通用方法(Builder.java)->根据通用方法组织建立文件(Director.java)->根据不同需求实现建立文件的通用方法(TextBuilder.java,HTMLBuilder.java)
5.Prototype(原型)-复制建立对象
Prototype Pattern 不是利用类产生对象实例,而是从一个对象实例产生出另一个新对象实例.
程序示例:
|--Main.java 测试用的类
|--MessageBox.java 把字符串框起来use的类.实现use和createClone
|--UnderlinePen.java 把字符串加上下划线的类.实现use和createCone
|--framework
|-------Product.java 已声明抽象方法use和createClone的接口
|-------Manager.java 利用createClone复制对象实例的类
步骤:规定可复制产品的接口(Product.java,继承Cloneable接口)->保存可复制的产品(以Product类型存以哈西表中),并提供复制产品的方法create(调用产品的复制方法,复制工作在具体产品类中执行)(Manager.java)->定义可复制的具体产品(UnderlinePen.java,MessageBox.java,实现复制产品方法)
二、结构模式(Structural Patterns)
1.Adapter(适配器)-换个包装再度利用
Adapter Pattern 把既有的无法直接利用的内容转换成必要的类型后再使用.具有填平"既有内容"和"需要结果"两者间"落差"的功能.
Adapter Pattern 有继承和委托两种形式.
程序示例:
|--Main.java 测试用的类
|--Banner.java 具有原始功能showWithParen,showWithAster的类
|--Print.java 所需新功能printWeak,printStrong的接口或抽象类
|--PrintBanner.java 把原始功能转换成新功能的类
步骤:
(继承)构造具有原始功能的类(Banner.java)->定义具有新功能的接口(Print.java)->转换(PrintBanner.java,继承Banner实现Print接口,即继承旧方法实现新功能)
(委托)构造具有原始功能的类(Banner.java)->定义具有新功能的抽象类(Print.java)->转换(PrintBanner.java,继承具有新功能的Print类.定义委托对象,即原始功能类.构造时传入原始功能实例对象,新功能的实现利用委托对象的原始功能.)
2.Bridge(桥接)-分成功能层次和实现层次
Bridge Pattern 沟通着"功能的类层次"和"实现的类层次"
功能的类层次:给父类增加不同的功能
实现的类层次:给父类以不同的实现
Bridge Pattern 本质上是通过功能类(最上层的功能类)中的一个实现类(最上层的实现类,一般是抽象类)字段来桥接两个类层次的.
程序示例:
|--Main.java 测试用的类
|--Display.java 功能类层次的最上层类
|--CountDisplay.java 功能类层次的新增功能类
|--DisplayImpl.java 实现类层次的最上层类
|--StringDisplayImpl.java 实现类层次的实现类
步骤:定义实现类层次的最上层类(DisplayImpl.java)->定义功能类层次的最上层类(Display.java,使用Adapter Pattern的委托方式把DisplayImpl.java的原始功能转换成Display.java的新功能)->定义功能类层次的新增功能类(CountDisplay.java)->定义实现类层次的实现类(StringDisplayImpl.java)
3.Composite(组成)-对容器和内容一视同仁
有时候把容器和内容当作是同类来处理会比较好下手。容器里面可以是内容,也可以是更小一号的容器;而这个小一号的容器里还可以再放更小一号的容器,可以建立出像这样大套小的结构和递归结构的Pattern就是Composite Pattern
使用Composite Pattern,容器和内容必须有一定的共性.
程序示例:
|--Main.java 测试用的类
|--File.java 表示文件的类
|--Directory.java 表示目录的类
|--Entry.java 对File和Directory一视同仁的抽象类
|--FileTreatmentException.java 欲在文件内新增Entry时所发生的异常类
步骤:定义异常类(FileTreatmentException.java)->定义进入点类,即将容器和内容一视同仁的抽象类(Entry.java,容器和内容都含有共同的方法)->定义容器类和内容类(File.java,Directory.java,继承Entry,实现通用方法)
4.Decorator(装饰)-对装饰和内容一视同仁
先建立一个核心对象,再一层层加上装饰用的功能,就可以完成符合所需的对象.可以看成是多个通用的适配器.
程序示例:
|--Main.java 测试用的类
|--Display.java 打印字符串用的抽象类
|--StringDisplay.java 只有1行的打印字符串用的类
|--Border.java 表示"装饰外框"的抽象类
|--SideBorder.java 只在左右加上装饰外框的类
|--FullBorder.java 在上下左右加上装饰外框的类
步骤:定义核心对象的抽象类(Display.java)->定义核心对象类(StringDisplay.java)->定义装饰类的抽象类(Border.java,继承核心对象的抽象类Display.java,以便装饰和内容一视同仁.装饰类中继承自核心对象抽象类的方法委托给传入的核心对象)->定义其它装饰类(SideBorder.java,FullBorder.java,继承Border.java)
5.Facade(外观)-单一窗口
Facade Pattern 能整理错综复杂的来龙去脉,提供较高级的接口(API).Facade参与者让系统外部看到较简单的接口(API).而且Facade参与者还会兼顾系统内部各类功能和互动关系,以最正确的顺序利用类.
Facade Pattern 把业务逻辑封装起来,只提供一个简单的接口给外部调用.
程序示例:
|--Main.java 测试用的类
|--maildata.txt 邮件列表文件
|--pagemaker
|-------Database.java 从邮件信箱取得用户名称的类
|-------HtmlWriter.java 产生HTML文件的类
|-------PageMaker.java 根据邮件信箱产生用户网页的类
步骤:定义业务逻辑需要的相关类(Database.java,HtmlWriter.java)->定义外部接口类(PageMaker.java)
6.Flyweight(享元)-有相同的部分就共享,采用精简政策
"尽量共享对象实例,不做无谓的new".不是一需要对象实例就马上new,如果可以利用其他现有的对象实例,就让它们共享.这就是Flyweigth Pattern的核心概念.
Flyweight Pattern 实质是把创建的占用内存量大的对象存储起来(一般用hashtable存储),后续使用时,再从hashtable取出.
程序示例:
|--Main.java 测试用的类
|--BigChar.java 表示"大型字符"的类
|--BigCharFactory.java 共享并产生BigChar的对象实例的类
|--BigString.java 表示多个BigChar所产生的"大型文本"的类
步骤:定义占用内存量大,需要共享的类(Display.java)->定义共享实例的类(BigCharFactory.java,共享处理在此进行,将产生的共享对象存储在哈希表中,第二次使用时从表中取出即可,不需要new)->定义共享对象组合使用类(BigString.java)
7.Proxy(代理)-需要再建立
代理就是那个代替本来应该自己动手做事的本人的人.
由于代理纯粹只是代理工作而已,因此能力范围也有限.如果遇到超出代理能力所及的范围,代理就应该去找本人商量才对.
程序示例:
|--Main.java 测试用的类
|--Printer.java 表示命名的打印机的类(本人)
|--Printable.java Printer和PrinterProxy共享的接口
|--PrinterProxy.java 表示命名的打印机的类(代理)
步骤:定义本人和代理都能处理的问题的接口(Printable.java)->建立本人类(Printer.java,实现Printable.java接口)->建立代理类(PrinterProxy.java,定义本人字段,把代理无法处理的问题交给本人)
三、行为模式(Behavioral Pattern)
1.Chain of Responsibility(职责链)-责任转送
先对人产生一个要求,如果这个人有处理的能力就处理掉;如果不能处理的话,就把要求转送给"第二个人".同样的,如果第二个人有处理的能力时就处理掉,不能处理的话,就继续转送给"第三个人",依此类推.这就是Chain of Responsiblility Pattern.
Chain of Responsibility Pattern 的关键在于定义转送字段(next)和定义职责链.
程序示例:
|--Main.java 建立Support的连锁,产生问题的测试用类
|--Trouble.java 表示发生问题的类.内有问题编号.
|--Support.java 解决问题的抽象类.内有转送字段和处理方法.
|--NoSupport.java 解决问题的具体类(永远"不处理")
|--LimitSupport.java 解决问题的具体类(解决小于指定号码的问题)
|--OddSupport.java 解决问题的具体类(解决奇数号码的问题)
|--SpecialSupport.java 解决问题的具体类(解决特殊号码的问题)
步骤:建立问题类(Trouble.java)->建立解决问题的抽象类(Support.java,定义了转送字段next,设置转送字段的方法setNext和处理问题的方法support)->建立解决问题的具体类(NoSupport.java,LimitSupport.java,OddSupport.java,SpecialSupport.java,继承Support.java)->产生处理问题的对象,建立职责链
2.Command(命令)-将命令写成类
用一个"表示命令的类的对象实例"来代表欲执行的操作,而不需采用"调用方法"的类的动态处理.如欲管理相关纪录,只需管理该对象实例的集合即可.而若预先将命令的集合存储起来,还可再执行同一命令;或者是把多个命令结合成一个新命令供再利用.
Command Pattern 重点在于存储/使用命令
程序示例:
--Main.java 测试用的类
|-command
| |-------Command.java 表示"命令"的接口
| |-------MacroCommand.java 表示"结合多个命名的命令"的类
|
|-drawer
|-------DrawCommand.java 表示"点的绘制命令"的类
|-------Drawable.java 表示"绘制对象"的接口
|-------DrawCanvas.java 表示"绘制对象"的类
步骤:建立命令接口(Command.java)->建立命令结合类(MacroCommand.java,将各个命令存储到一个Stack类型的字段)->建立绘制命令类(DrawCommand.java,定义绘制对象字段drawable,实现命令接口)->建立绘制对象接口(Drawable.java)->建立绘制对象类(DrawCanvas.java,实现绘制对象接口,定义命令集合字段history)->测试
3.Interpreter(解释器)-以类来表达语法规则
Interpreter Pattern 是用简单的"迷你语言"来表现程序要解决的问题,以迷你语言写成"迷你程序"而表现具体的问题.迷你程序本身无法独自启动,必须先用java语言另外写一个负责"解释(interpreter)"的程序.解释程序能分析迷你语言,并解释\执行迷你程序.这个解释程序也称为解释器.当应解决的问题发生变化时,要修改迷你程序来对应处理.而不是修改用java语言写成的程序.
迷你语言语法:
<program>::=program<command list>
<command list>::=<command>* end
<command>::=<repeat command>|<primitive command>
<repeat command>::=repeat<number><command list>
<primitive command>::=go|right|left
程序示例:
|--Main.java 测试用的类
|--Node.java 树状剖析中"节点"的类
|--ProgramNode.java 对应<program>的类
|--CommandListNode.java 对应<command list>的类
|--CommandNode.java 对应<command>的类
|--RepeatCommandNode.java 对应<repeat command>的类
|--PrimitiveCommandNode.java 对应<primitive command>的类
|--Context.java 表示语法解析之前后关系的类
|--ParseException.java 语法解析中的例外类
步骤:确定迷你语言的语法->建立语法解析类(Context.java,使用java.util.StringTokenizer类)->建立解析异常类(ParseException.java)->建立语法节点抽象类(Node.java,定义parse解析方法)->建立各语法节点对应的语法类(ProgramNode.java,CommandListNode.java,CommandNode.java,RepeatCommandNode.java,PrimitiveCommand.java,继承语法节点Node.java类)
4.Iterator-迭代器
Iterator Pattern 是指依序遍历并处理多个数字或变量.
程序示例:
|--Main.java 测试用的类
|--Aggregate.java 表示已聚合的类
|--Iterator.java 执行递增\遍历的接口
|--Book.java 表示书籍的类
|--BookShelf.java 表示书架的类
|--BookShelfIterator.java 扫描书架的类
步骤:定义聚合接口(Aggregate.java)->定义遍历接口(Iterator.java)->建立具体的遍历对象类(Book.java)->建立具体的聚合类(BookShelf.java,实现聚合接口)->建立具体的遍历类(BookShelfIterator.java,实现遍历接口)
5.Mediator(中介者)-只要面对一个顾问
每个成员都只对顾问提出报告,也只有顾问会发出指示给各个成员;成员们彼此也不会去探问目前状况如何,或乱发指示给其他成员.
程序示例:
|--Main.java 测试用的类
|--Mediator.java 决定"顾问"接口(API)的接口
|--Colleague.java 决定"成员"接口(API)的接口
|--ColleagueButton.java 实现Colleagues接口.表示按键的类
|--ColleagueTextField.java 实现Colleagues接口.输入文本的类
|--ColleagueCheckbox.java 实现Colleagues接口.表示选择项目(在此为选择按钮)的类
|--LoginFrame.java 实现Mediator接口.表示登录对话框的类
步骤:定义顾问接口(Mediator.java)->定义成员接口(Colleague.java)->建立具体的成员类(ColleagueButton.java,ColleagueTextField.java,ColleagueCheckbox.java,实现成员接口)->建立具体的顾问类(LoginFrame.java,实现顾问接口)
6.Memento(备忘录)-存储状态
Memento Pattern 会把某个时间点的对象实例状态记录存储起来,等到以后再让对象实例复原到当时的状态.
程序示例:
|--Main.java 进行游戏的类.先把Memento的对象实例存储起来,如有必要时再复原Gamer的状态
|--game
|-------Gamer.java 玩游戏的主人翁的类
|-------Memento.java 表示Gamer状态的类.产生Memento的对象实例
步骤:建立需要存储状态的类(Gamer.java)->建立状态类(Memento.java,状态类与需要存储状态的类Gamer.java应具有相同的必要字段)
7.Observer(观察者)-通知状态变化
当被Observer Pattern 列入观察名单的状态发生变化,就会通知观察者.在写一些跟状态变化有关的处理时,Observer Pattern是很好用的工具.
程序示例:
|--Main.java 测试用的类
|--Observer.java 表示观察者的接口
|--NumberGenerator.java 表示产生数值对象的抽象类
|--RandomNumberGenerator.java 产生随机数的类
|--DigitObserver.java 以数字表示数值的类
|--GraphObserver.java 以简易长条图表示数值的类
步骤:定义观察者接口(Observer.java)->建立被观察的类(NumberGenerator.java,RandomNumberGenerator.java,定义观察者结合字段将观察者存储起来)->建立具体的观察者类(DigitObserver.java,GraphObserver.java,实现观察者接口)
8.State(状态)-以类表示状态
以类来表示状态之后,只要切换类就能表现“状态变化”,而且在必须新增其他状态时,也很清楚该编写哪个部分。
程序示例:
|--Main.java 测试用的类
|--State.java 表示金库状态的接口
|--DayState.java 实现State的类。表示白天的状态
|--NightState.java 实现State的类。表示夜间的状态
|--Context.java 管理金库的状态变化,跟保安中心联络的接口
|--SafeFrame.java 实现Context的类。含有按钮、画面显示等的用户接口
步骤:定义状态接口(State.java,将使用State Pattern之前各种行为方法抽象出来)->建立具体的状态类(DayState.java,NightState.java,实现状态接口,状态变化的具体动作在这里执行)->定义管理状态变化的接口(Context.java,规定状态变化及相关的调用方法)->建立状态管理类(SafeFrame.java,实现状态管理接口)
9.Strategy(策略)-把算法整个换掉
在Strategy Pattern之下,可以更换实现算法的部分而且不留痕迹。切换整个算法,简化改为采用其他方法来解决同样的问题。
程序示例:
|--Main.java 测试用的类
|--Hand.java 表示猜拳“手势”的类
|--Strategy.java 表示猜拳“战略”的接口
|--WinningStrategy.java 表示猜赢之后继续出同样招式的战略的类
|--ProbStrategy.java 表示从上一次出的招式,以概率分配方式求出下一个招式机率的类
|--Player.java 表示玩猜拳的游戏者的类
步骤:定义策略接口(Strategy.java)->建立具体的策略类(WinningStrategy.java,ProbStrategy.java,实现策略接口)->建立使用策略的类(Player.java,定义策略字段,以便使用切换策略)->建立其它类(Main.java,Hand.java)
10.Template Method(模板方法)-实际处理交给子类
在父类指定处理大纲、在子类规定具体内容的Design Pattern就称为Template Method Pattern
程序示例:
|--Main.java 测试用的类
|--AbstractDisplay.java 只实现方法display的抽象类
|--CharDisplay.java 实现方法open,print,close的类
|--StringDisplay.java 实现方法open,print,close的类
步骤:定义模板类(AbstractDisplay.java,实现dispaly方法,即制作了模板)->建立具体内容类(CharDisplay.java,StringDisplay.java,继承模板类,实现模板类没有实现的方法)
11.Visitor(访问者)-在结构中穿梭还同时做事
Visitor Pattern 把数据结构和处理两者分开,另外写一个表示在数据结构内穿梭来去的主体“访客”的类,然后把处理交给这个类来进行。如此一来,如果想追加新的处理行为时,只要再建立一个新的“访客”即可。而在数据结构这边,也只要能接受来敲门的“访客”就能完成动作。
在父类指定处理大纲、在子类规定具体内容的Design Pattern就称为Template Method Pattern
程序示例:
|--Main.java 测试用的类
|--Visitor.java 表示访问文件或目录的访客的抽象类
|--Acceptor.java 表示接受Visitor类的对象实例的数据结构的接口
|--ListVisitor.java Visitor类的子类,打印文件和目录信息的类
|--Entry.java File和Directory的父类的抽象类(实现Acceptor接口)
|--File.java 表示文件的类
|--Directory.java 表示目录的类
|--FileTreatmentException.java 发生在对File进行add时的例外类
步骤:定义访问者的抽象类(Visitor.java,定义访问方法)->定义受访者接口(Acceptor.java,定义接受访问的方法)->建立具体的访问者类(ListVisitor.java,继承访问者抽象类,实现访问方法)->建立具体的受访者类(Entry.java,File.java,Directory.java,实现受访者接口)->编写异常类(FileTreatmentException.java)
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/pian_yun/archive/2007/09/14/1784981.aspx
直接在html中使用xml导入数据
<xml id="cdcat" src="cd_catalog.xml"></xml>
<table border="1" datasrc ="#cdcat">
<tr>
<td><span datafld="ARTIST"></span></td>
<td><span datafld="TITLE"></span></td>
<td datafld="price"> </td>
<td><span datafld="year"></span></td>
</tr>
</table>
注意可以引入xml字段的元素有 限:
例如,与DIV元素绑定的代码如下:
d: U) f1 y
注意:并非所有的HTML元素都能与XML数据岛绑定。目前,支持这种DSO绑定机制的元素如下:. H2 V- _% j! E/ {4 i
$ \( \$ l" b+ H( M& Y
A、APPLET、BUTTON、DIV、FRAME、IFRAME、 IMG、INPUT (此处类型是:CHECKBOX、HIDDEN、 LABEL、PASSWORD、RADIO和TEXT)、LABEL、 MARQUEE、SELECT、SPAN、TABLE和 TEXTAREA。
H.264中的NAL技术
NAL技术
1.NAL概述
NAL全称Network Abstract Layer, 即网络抽象层。
在H.264/AVC视频编码标准中,整个系统框架被分为了两个层面:视频编码层面(VCL)和网络抽象层面(NAL)。其中,前者负责有效表示视频数据的内容,而后者则负责格式化数据并提供头信息,以保证数据适合各种信道和存储介质上的传输。
现实中的传输系统是多样化的,其可靠性,服务质量,封装方式等特征各不相同,NAL这一概念的提出提供了一个视频编码器和传输系统的友好接口,使得编码后的视频数据能够有效地在各种不同的网络环境中传输。
2.NAL单元
NAL单元是NAL的基本语法结构,它包含一个字节的头信息和一系列来自VCL的称为原始字节序列载荷(RBSP)的字节流。头信息中包含着一个可否丢弃的指示标记,标识着该NAL单元的丢弃能否引起错误扩散,一般,如果NAL单元中的信息不用于构建参考图像,则认为可以将其丢弃;最后包含的是NAL单元的类型信息,暗示着其内含有效载荷的内容。
送到解码器端的NAL单元必须遵守严格的顺序,如果应用程序接收到的NAL单元处于乱序,则必须提供一种恢复其正确顺序的方法。
3.NAL实现编解码器与传输网络的结合
NAL提供了一个编解码器与传输网络的通用接口,而对于不同的网络环境,具体的实现方案是不同的。对于基于流的传输系统如H.320、MPEG等,需要按照解码顺序组织NAL单元,并为每个NAL单元增加若干比特字节对齐的前缀以形成字节流;对于RTP/UDP/IP系统,则可以直接将编码器输出的NAL单元作为RTP的有效载荷;而对于同时提供多个逻辑信道的传输系统,我们甚至可以根据重要性将不同类型的NAL单元在不同服务质量的信道中传输[2]。
4.结论
为了实现编解码器良好的网络适应性,需要做两方面的工作:第一、在Codec中将NAL这一技术完整而有效的实现;第二、在遵循H.264/AVC NAL规范的前提下设计针对不同网络的最佳传输方案。如果实现了以上两个目标,所实现的就不仅仅是一种视频编解码技术,而是一套适用范围很广的多媒体传输方案,该方案适用于如视频会议,数据存储,电视广播,流媒体,无线通信,远程监控等多种领域。
NALU类型
标识NAL单元中的RBSP数据类型,其中,nal_unit_type为1, 2, 3, 4, 5及12的NAL单元称为VCL的NAL单元,其他类型的NAL单元为非VCL的NAL单元。
0:未规定
1:非IDR图像中不采用数据划分的片段
2:非IDR图像中A类数据划分片段
3:非IDR图像中B类数据划分片段
4:非IDR图像中C类数据划分片段
5:IDR图像的片段
6:补充增强信息 (SEI)
7:序列参数集
8:图像参数集
9:分割符
10:序列结束符
11:流结束符
12:填充数据
13 – 23:保留
24 – 31:未规定
NALU的顺序要求
H.264/AVC标准对送到解码器的NAL单元顺序是有严格要求的,如果NAL单元的顺序是混乱的,必须将其重新依照规范组织后送入解码器,否则解码器不能够正确解码。
1.序列参数集NAL单元必须在传送所有以此参数集为参考的其他NAL单元之前传送,不过允许这些NAL单元中间出现重复的序列参数集NAL单元。所谓重复的详细解释为:序列参数集NAL单元都有其专门的标识,如果两个序列参数集NAL单元的标识相同,就可以认为后一个只不过是前一个的拷贝,而非新的序列参数集。
2.图像参数集NAL单元必须在所有以此参数集为参考的其他NAL单元之先,不过允许这些NAL单元中间出现重复的图像参数集NAL单元,这一点与上述的序列参数集NAL单元是相同的。
3.不同基本编码图像中的片段(slice)单元和数据划分片段(data partition)单元在顺序上不可以相互交叉,即不允许属于某一基本编码图像的一系列片段(slice)单元和数据划分片段(data partition)单元中忽然出现另一个基本编码图像的片段(slice)单元片段和数据划分片段(data partition)单元。
4.参考图像的影响:如果一幅图像以另一幅图像为参考,则属于前者的所有片段(slice)单元和数据划分片段(data partition)单元必须在属于后者的片段和数据划分片段之后,无论是基本编码图像还是冗余编码图像都必须遵守这个规则
5.基本编码图像的所有片段(slice)单元和数据划分片段(data partition)单元必须在属于相应冗余编码图像的片段(slice)单元和数据划分片段(data partition)单元之前。
6.如果数据流中出现了连续的无参考基本编码图像,则图像序号小的在前面。
7.如果arbitrary_slice_order_allowed_flag置为1,一个基本编码图像中的片段(slice)单元和数据划分片段(data partition)单元的顺序是任意的,如果arbitrary_slice_order_allowed_flag置为零,则要按照片段中第一个宏块的位置来确定片段的顺序,若使用数据划分,则A类数据划分片段在B类数据划分片段之前,B类数据划分片段在C类数据划分片段之前,而且对应不同片段的数据划分片段不能相互交叉,也不能与没有数据划分的片段相互交叉。
8.如果存在SEI(补充增强信息) 单元的话,它必须在它所对应的基本编码图像的片段(slice)单元和数据划分片段(data partition)单元之前,并同时必须紧接在上一个基本编码图像的所有片段(slice)单元和数据划分片段(data partition)单元后边。假如SEI属于多个基本编码图像,其顺序仅以第一个基本编码图像为参照。
9.如果存在图像分割符的话,它必须在所有SEI 单元、基本编码图像的所有片段slice)单元和数据划分片段(data partition)单元之前,并且紧接着上一个基本编码图像那些NAL单元。
10.如果存在序列结束符,且序列结束符后还有图像,则该图像必须是IDR(即时解码器刷新)图像。序列结束符的位置应当在属于这个IDR图像的分割符、SEI 单元等数据之前,且紧接着前面那些图像的NAL单元。如果序列结束符后没有图像了,那么它的就在比特流中所有图像数据之后。
11.流结束符在比特流中的最后。
本文来自CSDN博客,转载请标明出处:file:///D:/新建文件夹/桌面/H_264中的NAL技术%20-%20Bolt%20的专栏%20-%20CSDN博客.htm
生成zigzag序,
1、分析关键,在以zigzag序的每一行,以上三角为计算对象分别以i或j的增序排列,因此利用这一点就可以得出结果。
程序中s即为zigzag行号,而变换则以i和j交替。所以程序很简单。
#include<iostream>
#include<iomanip>
using namespace std;
#define M 255
void zigzag(const int N)
{
int squa = N * N;
int a[M][M]={0};
for (int i = 0;i < N; i++)
{
for (int j = 0;j < N;j++)
{
int s = i + j;
if ( s < N)
{
a[i][j] = s * (s+1)/2 + ( (s %2 !=0)?i:j);//注意?:的优先级低于+
}
else
{
int sn = (N-1-i) + (N-1-j);
a[i][j] = squa - sn * (sn+1)/2 - (N - ( (sn%2 != 0)? i:j));
}
}
}
for (int i=0; i < N; i++)
{
for (int j = 0;j < N;j++)
{
cout<<setw(4)<<a[i][j]<<",";
}
cout<<endl<<endl;
}
}
int main()
{
zigzag(5);
cout<<endl;
zigzag(8);
cout<<endl;
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void zigzag(int n)
{
int **a =(int**) malloc(n*sizeof(int *)); //分配空间
if(NULL == a)
return ;
int i;
for(i = 0; i < n; i++) {
if((a[i] =(int*) malloc(n * sizeof(int))) == NULL) {
while(--i>=0)
free(a[i]);
free(a);
return;
}
}
bool flag = false; //这个标志位用来判断是从45度角生成还是225度角生成
int count = 0;
for(i=0; i<n; i++) //生成的上半部分的数据
{
if(flag)
{
for(int r = 0; r<=i; r++)
{
a[r][i-r] = count;
count++;
}
flag = false;
}
else
{
for(int r = i; r>=0; r--)
{
a[r][i-r] = count;
count++;
}
flag = true;
}
}
for(i=n-1; i>=0; i--) //生成的是下半部分的数据
{
// cout<<i<<endl;
if(flag)
{
for(int r = 0; r<=i-1; r++)
{
int r1 = n-i+r; //代表当前行
int c1 = 2*n-i-1-r1; //代表当前列
a[r1][c1] = count;
count++;
}
flag = false;
}
else
{
for(int r = i-1; r>=0; r--)
{
cout<<"ddd"<<endl;
int r1 = n-i+r;
int c1 = 2*n-i-1-r1;
// cout<<r1<<","<<c1<<endl;
a[r1][c1] = count;
count++;
}
flag = true;
}
}
for(int r = 0; r<n; r++)
{
for(int c=0; c<n; c++)
cout<<a[r][c]<<",";
cout<<endl;
}
}
int main()
{
int n;
cin>>n;
zigzag(n);
return 0;
}
网上还有一个人写了一个比较巧的算法:
/**
* 得到如下样式的二维数组
* zigzag(jpeg编码里取象素数据的排列顺序)
*
* 0, 1, 5, 6,14,15,27,28,
* 2, 4, 7,13,16,26,29,42,
* 3, 8,12,17,25,30,41,43,
* 9,11,18,24,31,40,44,53,
* 10,19,23,32,39,45,52,54,
* 20,22,33,38,46,51,55,60,
* 21,34,37,47,50,56,59,61,
* 35,36,48,49,57,58,62,63
*/
#include <stdio.h>
int main()
{
int N;
int s, i, j;
int squa;
scanf("%d", &N);
/* 分配空间 */
int **a = malloc(N * sizeof(int *));
if(a == NULL)
return 0;
for(i = 0; i < N; i++) {
if((a[i] = malloc(N * sizeof(int))) == NULL) {
while(--i>=0)
free(a[i]);
free(a);
return 0;
}
}
/* 数组赋值 */
squa = N*N;
for(i = 0; i < N; i++)
for(j = 0; j < N; j++) {
s = i + j;
if(s < N)
a[i][j] = s*(s+1)/2 + (((i+j)%2 == 0)? i : j);
else {
s = (N-1-i) + (N-1-j);
a[i][j] = squa - s*(s+1)/2 - (N - (((i+j)%2 == 0)? i : j));
}
}
/* 打印输出 */
for(i = 0; i < N; i++) {
for(j = 0; j < N; j++)
printf("%-6d", a[i][j]);
printf("\n");
}
return 0;
}
几道面试笔试题
2008-02-26 18:38
一、如何判断一个单链表是有环的?(注意不能用标志位,最多只能用两个额外指针)
struct node { char val; node* next;}
bool check(const node* head) {} //return false : 无环;true: 有环
一种O(n)的办法就是(搞两个指针,一个每次递增一步,一个每次递增两步,如果有环的话两者必然重合,反之亦然):
bool check(const node* head)
{
if(head==NULL)
return false;
node *low=head, *fast=head->next;
while(fast!=NULL && fast->next!=NULL)
{
low=low->next;
fast=fast->next->next;
if(low==fast)
return true;
}
return false;
}
二、删除一个单项链表的最中间的元素,要求时间尽可能短(不能使用两次循环)
struct link
{
int data;
struct link *next;
};
void delMiddle(link *head)
{
if(head == NULL)
return;
else if(head->next == NULL)
{
delete head;
return;
}
else
{
link *low = head;
link *fast = head->next;
while(fast != NULL && fast->next != NULL)
{
fast = fast->next->next;
if(fast == NULL)
break;
low = low->next;
}
link *temp = low->next;
low->next = low->next->next;
delete temp;
}
}
int main()
{
struct link *head,*l;
struct link *s;
head = (link*)malloc(sizeof(link));
head->data=0;
head->next = NULL;
l = head;
for(int i=1; i<9; i++)
{
s = (link*)malloc(sizeof(link));
s->data = i;
s->next = NULL;
l->next= s;
l = l->next;
}
print(head);
delMiddle(head);
print(head);
return 0;
}
三、输入n,求一个n*n矩阵,规定矩阵沿45度线递增(威盛)
/**
* 得到如下样式的二维数组
* zigzag(jpeg编码里取象素数据的排列顺序)
*
* 0, 1, 5, 6,14,15,27,28,
* 2, 4, 7,13,16,26,29,42,
* 3, 8,12,17,25,30,41,43,
* 9,11,18,24,31,40,44,53,
* 10,19,23,32,39,45,52,54,
* 20,22,33,38,46,51,55,60,
* 21,34,37,47,50,56,59,61,
* 35,36,48,49,57,58,62,63
*/
void zigzag(int n)
{
int **a =(int**) malloc(n*sizeof(int *)); //分配空间
if(NULL == a)
return ;
int i;
for(i = 0; i < n; i++) {
if((a[i] =(int*) malloc(n * sizeof(int))) == NULL) {
while(--i>=0)
free(a[i]);
free(a);
return;
}
}
bool flag = false; //这个标志位用来判断是从45度角生成还是225度角生成
int count = 0;
for(i=0; i<n; i++) //生成的上半部分的数据
{
if(flag)
{
for(int r = 0; r<=i; r++)
{
a[r][i-r] = count;
count++;
}
flag = false;
}
else
{
for(int r = i; r>=0; r--)
{
a[r][i-r] = count;
count++;
}
flag = true;
}
}
for(i=n-1; i>=0; i--) //生成的是下半部分的数据
{
// cout<<i<<endl;
if(flag)
{
for(int r = 0; r<=i-1; r++)
{
int r1 = n-i+r; //代表当前行
int c1 = 2*n-i-1-r1; //代表当前列
a[r1][c1] = count;
count++;
}
flag = false;
}
else
{
for(int r = i-1; r>=0; r--)
{
cout<<"ddd"<<endl;
int r1 = n-i+r;
int c1 = 2*n-i-1-r1;
// cout<<r1<<","<<c1<<endl;
a[r1][c1] = count;
count++;
}
flag = true;
}
}
for(int r = 0; r<n; r++)
{
for(int c=0; c<n; c++)
cout<<a[r][c]<<",";
cout<<endl;
}
}
int main()
{
int n;
cin>>n;
zigzag(n);
return 0;
}
网上还有一个人写了一个比较巧的算法:
/**
* 得到如下样式的二维数组
* zigzag(jpeg编码里取象素数据的排列顺序)
*
* 0, 1, 5, 6,14,15,27,28,
* 2, 4, 7,13,16,26,29,42,
* 3, 8,12,17,25,30,41,43,
* 9,11,18,24,31,40,44,53,
* 10,19,23,32,39,45,52,54,
* 20,22,33,38,46,51,55,60,
* 21,34,37,47,50,56,59,61,
* 35,36,48,49,57,58,62,63
*/
#include <stdio.h>
int main()
{
int N;
int s, i, j;
int squa;
scanf("%d", &N);
/* 分配空间 */
int **a = malloc(N * sizeof(int *));
if(a == NULL)
return 0;
for(i = 0; i < N; i++) {
if((a[i] = malloc(N * sizeof(int))) == NULL) {
while(--i>=0)
free(a[i]);
free(a);
return 0;
}
}
/* 数组赋值 */
squa = N*N;
for(i = 0; i < N; i++)
for(j = 0; j < N; j++) {
s = i + j;
if(s < N)
a[i][j] = s*(s+1)/2 + (((i+j)%2 == 0)? i : j);
else {
s = (N-1-i) + (N-1-j);
a[i][j] = squa - s*(s+1)/2 - (N - (((i+j)%2 == 0)? i : j));
}
}
/* 打印输出 */
for(i = 0; i < N; i++) {
for(j = 0; j < N; j++)
printf("%-6d", a[i][j]);
printf("\n");
}
return 0;
}
四、打印1到1000的整数,不能使用流程控制语句(for,while,goto等)也不能使用递归
1.
typedef struct _test{
static int a;
_test(){
printf("%d\n",_test::a);
a++;
}
}Test;
int Test::a = 1;
int main()
{
Test tt[1000];
return 0;
}
2.
#include <stdio.h>
#define B P,P,P,P,P,P,P,P,P,P
#define P L,L,L,L,L,L,L,L,L,L
#define L I,I,I,I,I,I,I,I,I,I,N
#define I printf( "%3d ",i++)
#define N printf( "\n ")
int main()
{
int i = 1;
B;
}
或
#define A(x) x;x;x;x;x;x;x;x;x;x;
int main ()
{
int n = 1;
A(A(A(printf ("%d ", n++))));
return 0;
}
五、struct S {
int i;
int * p;
};
void main()
{
S s;
int * p = &s.i;
p[0] = 4;
p[1] = 3;
s.p = p;
s.p[1] = 1;
s.p[0] = 2;
}
问程序会在哪一行死掉。 (microsoft)
解: S s;
int * p = &s.i; //s.i的地址存储在p里
p[0] = 4; //修改了s.i
p[1] = 3; //修改了s.p
s.p = p; //s.p指向s.i
s.p[1] = 1; //修改s.p本身
s.p[0] = 2; //s.p指向的是0x00000001,尝试向这里写,出错
s.p[0] = 2; 时出错
因为s.p存的是s.i的地址,s.p[1]为s.p,当s.p[1]=1时,s.p此时存放的是1了,而不是地址s.i,故在s.p[0] = 2时出错.
此时相当于s.p=ox00000001;地址ox0000001 = 2;当然就出错了
如果语句s.p[0] =2 先于s.p[1]=1则程序就不会出错.此时语句相当于s.i=2;s.p=1;
六、题目描述:
1. int swap(int *x,int *y)
{
if(x==NULL | | y==NULL)
return -1;
*x += *y;
*y = *x- *y;
*x -= *y;
return 1;
}
请改错,溢出已经考虑,不是错误
2.
void foo(int *x, int *y)
{
*x += *y;
*x += *y;
}
void fun(int *x, int *y)
{
*x += 2 * (*y);
}
问两个函数是否等价,能否互换
解答:第一题的函数是交换。但假如考虑x, y都是指向同一个变量,结果是这个变量的值为0.
第二题的两个函数是有区别的,也考虑x,y是指向同一个变量.这样第一个函数的结果是这个变量的4倍.但第二个函数的结果是变量的3倍.
|
C++ placement new 用法举例zz
2009-12-17 16:16
在处理内存分配的时候,C++程序员会用new操作符(operator new)来分配内存,并用delete操作符(operator delete)来释放内存。这是一个new操作符的例子。
class CTest
{
/* 成员函数和成员数据 */
};
// . . . 代码
// 分配一个对象
CTest * pTest = new Test;
// 分配一个有十个对象的数组 (CTest 要有缺省构造函数(default constuctor))
CTest * p10Tests = new Test[ 10];
虽然这种写法在大多数时候都工作得很好,但还是有些情况下使用new是很烦人的,比如当你想重新分配一个数组或者当你想在预分配的内存上构造一个对象的时候。
比如第一种情况,重新分配一个数组效率是很低的:
// 分配一个有10个对象的数组
CTest * pTests = new Test[ 10];
// . . .
// 假设现在我们需要11个对象
CTest * pNewTests = new Test[ 11];
// . . . 我们必须把原来的对象拷贝到新分配的内存中
for ( int i = 0; i < 10; i++)
pNewTests[ i] = pTests[ i];
delete pTests;
pTests = pNewTests;
如果你想在预分配的内存上创建对象,用缺省的new操作符是行不通的。要解决这个问题,你可以用placement new构造。它允许你构造一个新对象到预分配的内存上:
// buffer 是一个void指针 (void *)
// 用方括号[] 括起来的部分是可选的
[CYourClass * pValue = ] new( buffer) CYourClass[( parameters)];
下面是一些例子:
#include <new>
class CTest
{
public:
CTest()
{}
CTest( int)
{}
/* 代码*/
};
int main(int argc, char* argv[])
{
// 由于这个例子的目的,我们不考虑内存对齐问题
char strBuff[ sizeof( CTest) * 10 + 100];
CTest * pBuffer = ( CTest *)strBuff;
// 缺省构造
CTest * pFirst = new(pBuffer) CTest;
// 缺省构造
CTest * pSecond = new(pBuffer + 1) CTest;
// 带参数的构造;
// 不理会返回的指针
new(pBuffer + 2) CTest( 5);
// 带参数的构造
CTest * pFourth = new( pBuffer + 3) CTest( 10);
// 缺省构造
CTest * pFifth = new(pBuffer + 4) CTest();
// 构造多个元素(缺省构造)
CTest * pMultipleElements = new(pBuffer + 5) CTest[ 5];
return 0;
}
当你有自己的内存缓冲区或者在你实现自己的内存分配策略的时候,placement new会很有用。事实上在STL中广泛使用了placement new来给容器分配内存;每个容器类都有一个模版参数说明了构造/析构对象时所用的分配器(allocator)。
在使用placement new的时候,你要记住以下几点:
- 加上头文件#include <new>
- 你可以用placement new构造一个数组中的元素。
- 要析构一个用placement new分配的对象,你应该手工调用析构函数(并不存在一个“placement delete”)。它的语法如下:
pFirst->~CTest();
pSecond->~CTest();
前段事件,我问过关于placement new的问题,一位仁兄讲了一些道理,他说道:
::栈上的对象(注意,是类对象,char类型就无需了,后面还会提到)保证放在对齐地址上.
但是,个人实验了一下,发现并不是这样
例如:
int main()
{
char c1 = 'A' ;
char c2 = 'B' ;
char c3 = 'C' ;
char c4 = 'D' ;
char c5 = 'E' ;
//-------- 验证这四个地址是否是 4 的倍数 --------------//
if ( ((int)(&c1)) % 4 == 0 )
cout << "c1:Yes" << endl ;
if ( ((int)(&c2)) % 4 == 0 )
cout << "c2:Yes" << endl ;
if ( ((int)(&c3)) % 4 == 0 )
cout << "c3:Yes" << endl ;
if ( ((int)(&c4)) % 4 == 0 )
cout << "c4:Yes" << endl ;
if ( ((int)(&c5)) % 4 == 0 )
cout << "c5:Yes" << endl ;
cout << (int)(&c1) << endl // 输出四个字符所在的地址(输出结果都是 4 的倍数)
<< (int)(&c2) << endl
<< (int)(&c3) << endl
<< (int)(&c4) << endl
<< (int)(&c5) << endl ;
}
-----------------------------
上面的执行结果在VC下运行都是 4 的倍数
--------------
--> 问题1:连栈上分配的空间地址都是 4 的倍数,那就说明系统分配的空间都是 4 的倍数吧???
--> 问题2:如果万一,如果放一个对象的地址不是4的倍数,那么会出现什么情况??可以给简单说一下吗?
--> 问题3:地址对齐的通用性???
-------------
程序1:
Class C1
{
int i ;
char c ;
} ;
cout << sizeof(C1) << endl ;// 输出结果: 8 (是 4 的倍数)
程序2:
class C2
{
char c1 ;
char c2 ;
} ;
cout << sizeof(C2) << endl ;// 输出结果:2 ( 上一个中char类型也给了4个字节,怎么这个地方都给了一个字节??)
--> 问题4:由上面的程序2 引出下面的程序
class C2// sizeof(C2) =2 ,在VC实验下的结果,不是 4
{
char c1 ;
char c2 ;
} ;
//----------用placement new方法建立对象----------------
void *ptr = operator new(100) ;// 分配内存
C2 *POINTER = (C2*)ptr ;// 类型转换
String *str1 = new (POINTER) C2() ;// 建立一C2对象
String *str2 = new (POINTER+1) C2() ;// 再建立一个对象
String *str3 = new (POINTER+2) C2() ;// 再建立一个对象
cout << (int)(str1) << endl// 结果:3608720( 是4的倍数)
<< (int)(str2) << endl // 结果:3608722(不是4的倍数)!!
<< (int)(str3) << endl ;// 结果:3608724(不是4的倍数)!!
|
很实用的word的高级用法总汇2009-04-23 16:26
任意放大/变小 字体
快捷键ctrl+] 放大 字体 ctrl+[ 缩小字体
把文字替换成图片
首先把图片复制到 剪贴板中,然后打开替换对话框,在“查找内容”框中输入将被替换的文字,接着在 “替换为”框中输入“^c”(注意:输入的一定要是半角字符,c要小写),单击替换 即可。说明:“^c”的意思就是指令Word XP以剪贴板中的内容替换“查找内容”框中的内 容。按此原理,“^c”还可替换包括回车符在内的任何可以复制到剪贴板的可视内容,甚至Excel表格。
三招去掉页眉那条横线
1、在页眉中,在“格式”-“边框和底纹”中设置表格和边框为“无”,应用于“段落”
2、同上,只是把边框的颜色设置为白色(其实并没有删的,只是看起来没有了,呵呵)
3、在“样式”栏里把“页眉”换成“正文”就行了——强烈推荐!
会多出--(两个横杠) 这是用户不愿看到的,又要多出一步作删除--
解决方法:替换时在前引号前加上一个空格 问题就解决了
插入日期和时间的快捷键
Alt+Shift+D:当前日期
Alt+Shift+T:当前时间
批量转换全角字符为半角字符
首先全选。然后“格式”→“更改大小写”,在对话框中先选中“半角”,确定即可
Word启动参数简介
单击“开始→运行”命令,然后输入Word所在路径及参数确定即可运行,如“C:\ PROGRAM FILES \MICROSOFT Office \Office 10\ WINWord.EXE /n”,这些常用的参数及功能如下:
/n:启动Word后不创建新的文件。
/a:禁止插件和通用模板自动启动。
/m:禁止自动执行的宏。
/w:启动一个新Word进程,独立与正在运行的Word进程。
/c:启动Word,然后调用Netmeeting。
/q:不显示启动画面。
另外对于常需用到的参数,我们可以在Word的快捷图标上单击鼠标右键,然后在“目标”项的路径后加上该参数即可。
快速打开最后编辑的文档
如果你希望Word在启动时能自动打开你上次编辑的文档,可以用简单的宏命令来完成:
(1)选择“工具”菜单中的“宏”菜单项,单击“录制新宏”命令打开“录制宏”对话框;
(2)在“录制宏”对话框中,在“宏名”输入框中输入“autoexec”,点击“确定”;
(3)从菜单中选择“文件”,点击最近打开文件列表中显示的第一个文件名;并“停止录制”。保存退出。下次再启动Word时,它会自动加载你工作的最后一个文档。
格式刷的使用
1、设定好文本1的格式。
2、将光标放在文本1处。
3、单击格式刷按钮。
4、选定其它文字(文本2),则文本2的格式与文本1 一样。
若在第3步中单击改为双击,则格式刷可无限次使用,直到再次单击格式刷(或按Esc键)为止。
删除网上下载资料的换行符(象这种“↓”)
在查找框内输入半角^l(是英文状态下的小写L不是数字1),在替换框内不输任何内容,单击全部替换,就把大量换行符删掉啦。
选择性删除文件菜单下的最近使用的文件快捷方式。
工具→选项→常规把“列出最近使用文件数改为0”可以全部删除,若要选择性删除,可以按ctrl+Alt+ -三个键,光标变为一个粗减号后,单击文件,再单击要删除的快捷方式就行了。
建立一个矩形选区:
一般的选区建立可用鼠标左键,或用shift键配合pgup、pgdn、home、end、箭头等功能键,当复制一个规则的矩形区域时,可先按住Alt键,然后用鼠标左键来选。我一般用此来删除段首多余的成块的空格。大家试一试*^_^*
将字体快速改为上标或下标的方法:
本人在一次无意间发现了这个方法,选定你要下标的字,然后在英文状态下按住Ctrl,再按一下BASKSPACE旁的+/=的键,就可以了。上标只要在按Ctrl的同时也按住Shift,大家可以试试。
让Word表格快速一分为二
将光标定位在分开的表格某个位置上,按下“Ctrl+Shift+Enter”组合键。这时你就会发现表格中间自动插入一个空行,这样就达到了将一个表格一分为二的目的。
用Word来拆字
首先点击“工具/自定义/命令/分解图片”,按住鼠标左键把它拖放到工具栏任意位置即可;然后点击“插入/图片/艺术字”,例如输入空心字“心”,选择该“心”字剪切,在选择性粘贴中选图片(Windows图元文件),选中该字,点击工具栏中的“分解图片”按钮,这样可以选择“心”中的任意笔画进行一笔一画的拆分了。
快速删除段前段后的任意多个空格
选定这些段段落,单击居中按钮,然后再单击原来的那种对齐方式按钮(如果原来是居中对齐的,先单击其它对齐方式按钮,再单击居中按钮就行了),是不是这些空格全不见了?
只要打开WORD新建一个空文档的时候,出现的不是空的文档,而是我以前打的一份文档
首先:将资源管理器设置为显示所有文件和文件夹;
然后:
C:\Documents and Settings\Administrator\Application Data\Microsoft\Templates文件夹下将所有Normal.doc文件删掉;
然后:OK(XP系统)
快速输入平方的方法
先输入2,然后选重后,按ctrl加shift加+就可以了.
WORD中表格的选择性录入
1.设置好表格,选定表格-视图-工具-窗体-插入下拉型窗体域
2.输入数据,完成
3.点击锁按钮,保护,输入完后再点击进行其它的输入.
标点符号的全角/半的转换用:Ctrl+.
数字字母的全角/半的转换用:Shift+空格
轻松了解工具栏按钮的作用
按下“shift+F1”键,鼠标指针旁多了一个“?”号,想知道哪个按钮
的作用,就用鼠标单击哪个。
要经常在文档中插入自己公司的信息
公司名称
公司住址
联系电话
联系人姓名
QQ号码
可以先选定这些内容,再单击工具→自动更正→在替换框中输入标记名称(如“公司信息”)→添加→确定,以后凡是在文档中要用到这个信息的地方键入“公司信息”(不要引号)这几个字后就自动替换成:
公司名称
公司住址
联系电话
联系人姓名
QQ号码
说明:有些输入法不支持这个功能,键入标记名称后要按一下空格才行。
快速换页的方法
双击某页的右下脚,光标即可定位在那里,然后按回车直到换页。ctrl+回车点插入按纽,分隔符,选中分页符,然后确认就OK了 !!!
表格的简单调整宽度
鼠标放在表格的右边框上带鼠标变成可以调整大小的时候
双击
根据表格内的内容调节表格大小
代替金山词霸
点工具——语言——翻译,在右边出现的搜索框中输入要查的单词,回车就可以翻译了。可以选择英语翻成中文或中文翻成英语。
第一次使用可能要安装。
[Alt]键实现标尺的精确定位
如果你经常使用水平标尺来精确定位标签、页边框、首字缩进及页面对象的位置,那么你点击标尺设置页边框或标签时,您只可以将其设置为1字符或2字符,但不能设为1.5字符!要想设置更为精确的度量单位(例如百分之几字符),在按住[Alt]键的同时,点击并移动标尺或边框,此时标尺将用数字精确显示出当前的位置为百分之几字符位置。
用“记事本”去除格式
网页上COPY下来的东西往往都是有网格的,如果直接粘贴在WORD中会杂乱无章。先粘贴到记事本当中,再粘贴到WORD中,就可以去除网格等格式,再全选选择清除格式,居中再取消居中即可取消所有格式。可以直接在WORD中进行:(菜单)编辑/选择性粘贴……/无格式文本/确定。这样省事多了。
快速将文档转换成图片
先把欲想转换的文档保存退出.如:保存在桌面
然后新建一个文件.把想转换的文档(鼠标左建按住该文档不放)直接施放在页面上
恢复office的默认设置
比如不小心把word设置乱了(如删了菜单栏等等).
查找normal.dot直接删除.
下一次启动word会恢复默认值.
让Word只粘贴网页中的文字而自动去除图形和版式
方法一、选中需要的网页内容并按“Ctrl+C”键复制,打开Word,选择菜单“编辑”→“选择性粘贴”,在出现的对话框中选择“无格式文本”。
方法二、选中需要的网页内容并按“Ctrl+C” 键复制,打开记事本等纯文本编辑工具,按“Ctrl+V”键将内容粘贴到这些文本编辑器中,然后再复制并粘贴到Word中。
ctrl+alt+f可以输入脚注
这个对于经常写论文的朋友应该有点帮助。
将阿拉伯数字转换成中文数字或序号
1、先输入阿拉伯数字(如1234),全选中,单击“插入/数字/数字类型(壹、贰……)/确定”,即变为大写数字(如壹仟贰佰叁拾肆),会计朋友非常适用。
2、其他像一千二百三十四,甲、乙……,子、丑……,罗马数字等的转换,可参考上法。
Word中的常用快捷键吧
“字体”对话框 Ctrl+D
选择框式工具栏中的“字体”框 Ctrl+Shift+F
加粗 Ctrl+B
倾斜 Ctrl+I
下划线Ctrl+U
“上标”效果 Ctrl+Shift+=
“下标”效果 Ctrl+=
“关闭”命令 Ctrl+W
Word快捷键一览表
序号 快捷键CTRL+ 代表意义
1…………Z…………撤消
2…………A…………全选
3…………X…………剪切
4…………C…………复制
5…………V…………粘贴
6…………S…………保存
7…………B…………加粗
8………… Q…………左对齐
9…………E…………据中
10…………R…………右对齐
11…………]…………放大
22…………[…………缩小
12…………N…………新建文档
13…………I…………字体倾斜
14…………W…………退出
15…………P…………打印
16…………U…………下划线
17…………O…………打开
18…………k…………插入超级连接
19…………F…………查找
20…………H…………替换
21…………G…………定位
23…Ctrl+Alt+L……带括号的编号
24…Ctrl+Alt+.________…
25…Alt+数字………区位码输入
26…Ctrl+Alt+Del………关机
27…Ctrl+Alt+Shift+?……¿
28…Ctrl+Alt+Shift+!……¡
29…Alt+Ctrl+E……………?
30…Alt+Ctrl+R……………®
31…Alt+Ctrl+T……………™
32…Alt+Ctrl+Ctrl…………©
33……Ctrl+D……………格式字体
34……Ctrl+Shift+= ………上标
35……Ctrl+=………………下标
36……Ctrl+Shift+>……放大字体
37……Ctrl+Shift+< ……缩小字体
38……Alt+Ctrl+I………打印预览
39……Alt+Ctrl+O………大刚示图
40……Alt+Ctrl+P………普通示图
41……Alt+Ctrl+M………插入批注
42……Alt+菜单上字母………打开该菜单
无级微调
打开“绘图”工具栏-点开下拉菜单-绘图网格...-将水平间距和垂直间距调到最小0.01-确定,这样你就可以无级微调
把work设置成在线打开,但不能修改‘只读’怎搞啊?
文件夹共享为只读
在WORD中输入三个等号然后回车。。。出来的是双横线哦。。。
同样的方法也可以做出波浪线单横线哦!~~~~~ ,
###为中间粗上下细的三线, ***为点线, ~~~为波浪线, ---为单线
输入拼音字母的音调怎么输入
用智能ABC,键入v9,然后自己挑选吧!
页码设置
1、打开页眉/页脚视图,点击插入页码按钮,将页码插入(此时所有的页码是连续编号的) 2、切换到页面视图,在需要从1计数的页面上插入连续分节符(插入--分隔符--分节符--连续) 3、再次换到页眉/页脚视图,点击设置页码格式按钮,将页码编排-起始页码设置为1
把Excel中的表格以图片形式复制到Word中
除了用抓图软件和全屏拷贝法外还有更简单的呢
先选定区域,按住Shift健点击"编辑"会出现"复制图片""粘贴图片",复制了后,在Word中选"粘贴图片"就可像处理图片一样处理Excel表格了!
Ctrl+鼠标滑轮(左右键中间的那个轮子)可以迅速调节显示比例的大小(100%)。向上滑扩大,向下滑缩小。
快速调整页眉横线长度
在word插入页眉后,会自动在此位置添加一条长横线。如果需要调整此线的长度及其水平位置,可以首先激活页眉,选择格式下的段落命令,调整一下左右缩进的字符值,确定可以看到最终效果了!
快速浏览图片
在WORD2003中,如果插入的图片过多,会影响打开和翻滚的速度。其实,我们可以通过改变图片的显示方式改变浏览速度。
工具--选项--视图--图片框
这样,先显示的是图片框,需要看的时候,停留,即可显示!
WORD 中如何输入分数
1、打开word,点击工具菜单栏的“插入”,在下拉菜单中点“域”。
2、在打开的复选框中的类别栏中“选等式公式”,域名中“EQ”。然后点击“选项”,在出现的菜单选项中选“F(,)”,接着点击“添加到域”并“确定”。
3、然后在输入F(,)数字,如要输入23 只需在F(,)输入F(2,3)就能得到2/3
怎样使WORD 文档只有第一页没有页眉,页脚
答:页面设置-页眉和页脚,选首页不同,然后选中首页页眉中的小箭头,格式-边框和底纹,选择无,这个只要在“视图”——“页眉页脚”,其中的页面设置里,不要整个文档,就可以看到一个“同前”的标志,不选,前后的设置情况就不同了
Word中双击鼠标的妙用
在Word的程序窗口中不同位置上双击,可以快速实现一些常用功能,我们归纳如下:
在标题栏或垂直滚动条下端空白区域双击,则窗口在最大化和原来状态之间切换;
将鼠标在标题栏最左边WORD文档标记符号处双击,则直接退出WORD(如果没有保存,会弹出提示保存对话框);
将鼠标移到垂直滚动条的上端成双向拖拉箭头时双击,则快速将文档窗口一分为二;
将鼠标移到两个窗口的分界线处成双向拖拉箭头时双击,则取消对窗口的拆分;
在状态栏上的“修订”上双击,则启动“修订”功能,并打开“审阅”工具栏。再次双击,则关闭该功能,但“审阅”工具栏不会被关闭;
在状态栏上的“改写”上双击,则转换为“改写”形式(再次“双击”,转换为“插入”形式);
如果文档添加了页眉(页脚),将鼠标移到页眉(页脚)处双击,则激活页眉(页脚)进入编辑状态,对其进行编辑;在空白文档处双击,则启动“即点即输”功能;
在标尺前端空白处双击,则启动“页面设置”对话框。
在word编辑中经常要调整字休大小来满足编辑要求
选中要修改的文字,按ctrl+]或ctrl+[来改变字体的大小!
这个方法可以微量改字体大小~
文本框的线条
1. 制作好文档后,通过“视图→页眉页脚”命令,调出“页眉页脚”工具栏,单击其中的“显示→隐藏文档正文文字”按钮,隐藏正文部分的文字内容。
2. 选择“插入”菜单中的“文本框”命令,在页眉的下方插入一个空文本框。
3. 在文本框内加入作为水印的文字、图形等内容,右击图片,选择快捷菜单中的“设置图片格式”命令,在对话框中“图片”选项卡下,通过“图像控制”改变图像的颜色,对比度和亮度,并手动调整图片的大小。
4. 通过“设置文本框格式”命令,把文本框的线条色改为无线条色。
5. 单击“页眉页脚”工具栏的“关闭”按钮,退出“页眉页脚”编辑。
每页添加水印的操作
1. 制作好文档后,通过“视图→页眉页脚”命令,调出“页眉页脚”工具栏,单击其中的“显示→隐藏文档正文文字”按钮,隐藏正文部分的文字内容。
2. 选择“插入”菜单中的“文本框”命令,在页眉的下方插入一个空文本框。
3. 在文本框内加入作为水印的文字、图形等内容,右击图片,选择快捷菜单中的“设置图片格式”命令,在对话框中“图片”选项卡下,通过“图像控制”改变图像的颜色,对比度和亮度,并手动调整图片的大小。
4. 通过“设置文本框格式”命令,把文本框的线条色改为无线条色。
5. 单击“页眉页脚”工具栏的“关闭”按钮,退出“页眉页脚”编辑。
6. 完成上述步骤的操作,水印制作得以完成,这样就为每一页都添加了相同的水印。
让Word页面快速一分为二
将光标定位在想分开的位置上,按下“Ctrl+Shift+Enter”组合键。
使Word中的字体变清晰
Word文档中使用 “仿宋” 字体很淡,可按以下方法使字体更清晰:
右击桌面,点 “属性”,点 “外观”,点 “效果”,选中“使用下列方式使屏幕字体的边缘平滑”选“清晰”,确定。
Word双面打印技巧
我们平时用电脑的时候可能都少不了打印材料,Word是我们平常用的最多的Office软件之一。有时我们要用Word打印许多页的文档,出于格式要求或为了节省纸张,会进行双面打印。
我们一般常用的操作方法是:选择“打印”对话框底部的“打印”下拉列表框中的“打印奇数页”或“打印偶数页”,来实现双面打印。我们设定为先打印奇数页。等奇数页打印结束后,将原先已打印好的纸反过来重新放到打印机上,选择该设置的“打印偶数页”,单击“确定”按钮。这样通过两次打印命令就可以实现双面打印。
我们也可以利用另一种更灵活的双面打印方式:打开“打印”对话框,选中“人工双面打印”,确定后就会出现一个“请将出纸器中已打印好的一面的纸取出并将其放回到送纸器中,然后‘确定’按键,继续打印”的对话框并开始打印奇数页,打完后将原先已打印好的纸反过来重新放到打印机上,然后按下该对话框的“确定”按键,Word就会自动再打印偶数页,这样只用一次打印命令就可以了。
两种方法对比,后者较前者更为方便。
|
字符串拆分的中文处理问题
容健行@2007年7月
转载请注明出处
原文出处:http://www.devdiv.net/home/space.php?uid=125&do=blog&id=365
概述:
拆分一个字符串在程序中使用非常广泛,特别是我们经常跟表格打交道的程序员们。所谓拆分字符串,就是将一个字符串中间以某个(或某些)字符为分隔,拆分成多个字符串。如 std::string s = "abc | ddd | 中国"; 如果以竖线“|”拆分,可以将这个字符串拆分成三个字符串。
当然字符串拆分还包括通过正则表达式来拆分,为了简化问题,我们以单个字符做分隔的拆分,因为这种拆分用得最多。代码使用C++来讲解。
问题:
问题来源于实际,是之前我们组和其他组都有遇上的。先看一个例子,使用"|"拆分以下字符串,看起来怎么数都是分为48列,但我看到好几个版本的字符串拆分函数却报有49列:
"AGZGY1000004|200|刘瓅||20100101||OPRT10|1|0||AAGZ0Y100|0|0|24|0|0|0|0||-1|20030101|0|20991231||AGZGK6172888|200|曾晓翔||20100101||OPRT10|1|0||AAGZ0K617|0|0|24|0|0|0|0||-1|20061215|1|20061215||"
原因分析:
让我们先把以上字符串放到UltraEdit中,并切换到16进制的编辑模式,看看它的编码。
原因是原来的字符串拆分函数只是简单的查找“|”(编码为0x7c),而没有考虑到中文的处理(源代码太多,且有好几个版本,这里略去)。
在boss中,c++程序使用的编码方式几乎全为ansi,而在ansi中,表示中文是用两个字符,且第一个字符是一个大于0x80的字符(字符的第一位为1),第二个字符为任意字符。这里引起一个问题:
当我们要分割字符串时,假如用"|"(0x7c)作为分割符,当分析上面这个字符遇到"瓅"(编码为0xad,0x7c)这个字符时,会把它第二个字符作为了分割符,结果就多出了一列。
解决方案:
问题原因找到了,重新写了一下字符串拆分函数-Split,这里使用的方法是:找到分隔符后,再向前查找字符看一下它前一个字符是否为东亚文字的第一个字符编码(编码大于0x80)。
考虑到以后支持unicode,这里使用了模板。以下可能不是最高效简单的实现,但如果以后遇上这种问题,可以参考一下。
#include "stdafx.h"
#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <fstream>
// unicode 分割策略
inline
bool __SplitPolicy(
const std::wstring& s,
const std::wstring& splitchar,
std::wstring::size_type& pos)
{
pos = s.find_first_of(splitchar, pos);
return pos != std::string::npos;
}
// ansi 分割策略
inline
bool __SplitPolicy(
const std::string& s,
const std::string& splitchar,
std::string::size_type& pos)
{
pos = s.find_first_of(splitchar, pos);
if (pos != std::string::npos)
{
// 如果前一个字符的第一位为1,且当前字符是在东亚文字的第二个字符,
// 则认为该字符是东亚字的其中一个字符,要跳过,不作为分割符。
std::string::size_type i = 1;
for (; i < pos; ++i)
{
if (!((char)(s[pos - i]) & 0x80)) // 判断第一位是否为1。(0x80的二进制为 10000000)
break;
}
if (!(i % 2)) // 看一下当前字符是否为东亚文字的第二个字符
{
++pos;
__SplitPolicy(s, splitchar, pos);
}
}
return pos != std::string::npos;
}
template<typename char_type> inline
int Split(
const std::basic_string<char_type>& s,
const std::basic_string<char_type>& splitchar,
std::vector<std::basic_string<char_type> >& vec)
{
typedef std::basic_string<char_type> string_t;
typedef typename string_t::size_type size_t;
string_t tmpstr;
size_t pos = 0, prev_pos = 0;
vec.clear();
while (__SplitPolicy(s, splitchar, pos))
{
tmpstr = s.substr(prev_pos, pos - prev_pos);
vec.push_back(tmpstr);
prev_pos = ++pos;
}
size_t len = s.length() - prev_pos;
if (len > 0)
vec.push_back(s.substr(prev_pos, len));
return static_cast<int>(vec.size());
}
// ansi版本测试
void testSplit()
{
std::vector<std::string> vec;
const std::string str = "AGZGY1000004|200|刘瓅瓅||20100101||OPRT10|1|0||AAGZ0Y100|0|0|24|0|0|0|0||-1|20030101|0|20991231||AGZGK6172888|200|曾晓翔||20100101||OPRT10|1|0||AAGZ0K617|0|0|24|0|0|0|0||-1|20061215|1|20061215||a";
const std::string sp = "|";
int count = Split(str, sp, vec);
for (std::vector<std::string>::const_iterator it = vec.begin(); it != vec.end(); ++it)
std::cout << *it << " ";
}
// unicode版本测试
void testSplitW()
{
std::vector<std::wstring> vec;
const std::wstring str = L"AGZGY1000004|200|刘瓅||20100101||OPRT10|1|0||AAGZ0Y100|0|0|24|0|0|0|0||-1|20030101|0|20991231||AGZGK6172888|200|曾晓翔||20100101||OPRT10|1|0||AAGZ0K617|0|0|24|0|0|0|0||-1|20061215|1|20061215||";
const std::wstring sp = L"|";
Split(str, sp, vec);
const char head[3] = {0xff, 0xfe, 0};
const wchar_t line[3] = L" ";
// 控制台输出不了unicode字符,使用输出到文件的方式
std::ofstream fileOut("C:/out.txt");
fileOut.write(head, 2);
for (std::vector<std::wstring>::iterator it = vec.begin(); it != vec.end(); ++it)
{
fileOut.write((const char*)it->c_str(), it->length() * 2);
fileOut.write((const char*)line, 2);
}
}
int main()
{
testSplit();
testSplitW();
}
参考:
1.http://unicode.org/
2.《谈谈Unicode编码,简要解释UCS、UTF、BMP、BOM等名词》
一 引入问题
代码 wchar_t a[3]=L”中国”,编译时出错,出错信息为:数组越界。但wchar_t 是一个宽字节类型,数组a的大小应为6个字节,而两个汉字的的unicode码占4个字节,再加上一个结束符,最多6个字节,所以应该不会越界。难道是编译器出问题了?
二 解决引入问题所需的知识
主要需两方面的知识,第一个为字符尤其是汉字的编码,以及语言和工具的支持情况,第二个是vc/c++中MutiByte Charater Set 和 Wide Character Set有关内存分配的情况.
三 汉字的编码方式及在vc/c++中的处理
1.汉字编码方式的介绍
对英文字符的处理,7位ASCII码字符集中的字符即可满足使用需求,且英文字符在计算机上的输入及输出也非常简单,因此,英文字符的输入、存储、内部处理和输出都可以只用同一个编码(如ASCII码)。
而汉字是一种象形文字,字数极多(现代汉字中仅常用字就有六、七千个,总字数高达5万个以上),且字形复杂,每一个汉字都有"音、形、义"三要素,同音字、异体字也很多,这些都给汉字的的计算机处理带来了很大的困难。要在计算机中处理汉字,必须解决以下几个问题:首先是汉字的输入,即如何把结构复杂的方块汉字输入到计算机中去,这是汉字处理的关键;其次,汉字在计算机内如何表示和存储?如何与西文兼容?最后,如何将汉字的处理结果从计算机内输出?
为此,必须将汉字代码化,即对汉字进行编码。对应于上述汉字处理过程中的输入、内部处理及输出这三个主要环节,每一个汉字的编码都包括输入码、交换码、内部码和字形码。在计算机的汉字信息处理系统中,处理汉字时要进行如下的代码转换:输入码→交换码→内部码→字形码。
(1)输入码: 作用是,利用它和现有的标准西文键盘结合来输入汉字。输入码也称为外码。主要归为四类:
a) 数字编码:数字编码是用等长的数字串为汉字逐一编号,以这个编号作为汉字的输入码。例如,区位码、电报码等都属于数字编码。
b) 拼音码:拼音码是以汉字的读音为基础的输入办法。
c) 字形码:字形码是以汉字的字形结构为基础的输入编码。例如,五笔字型码(王码)。
d) 音形码:音形码是兼顾汉字的读音和字形的输入编码。
(2)交换码:用于汉字外码和内部码的交换。交换码的国家标准代号为GB2312-80。
(3)内部码:内部码是汉字在计算机内的基本表示形式,是计算机对汉字进行识别、存储、处理和传输所用的编码。内部码也是双字节编码,将国标码两个字节的最高位都置为"1",即转换成汉字的内部码。
(4)字形码:字形码是表示汉字字形信息(汉字的结构、形状、笔划等)的编码,用来实现计算机对汉字的输出(显示、打印)。
2.VC中汉字的编码方式
vc/c++正是采用了GB2312内部码作为汉字的编码方式,因此vc/c++中的各种输入输出方法,如cin/wcin,cout/wcout,scanf/wsanf,printf/wprintf...都是基于GB2312的,如果汉字的内码不是这种编码方式,那么利用上述各种方法就不会正确的解析汉字。
仔细观察ASCII字符表,从第161个字符开始,后面的字符并不经常为用户所使用,负值也未使用。GB2312编码方式充分利用这一特性,将161-255(-95~-1)之间的数值空间作为汉字的标识码。既然255-161 = 94不能满足汉字容量的要求,就将每两个字符并在一块(即一个汉字占两个字节),显然,94* 94 =8836基本上已经满足了常用汉字个数的要求。计算机处理字符时,当连续处理到两个大与160(或-95~-1)的字节时,就认为这两个字节存放了一个汉字字符。可以用下面的Demo程序来模拟vc/c++中输出汉字字符的过程。
unsigned char input[50];
cin>>input;
int flag=0;
for(int i =0 ;i < 50 ;i++)
{
if(input[i] > 0xa0 && input[i] != 0)
{
if(flag == 1)
{
cout<<"chinese character"<<endl;
flag = 0;
}
else
{
flag++;
}
}
else if(input[i] == 0)
{
break;
}
else
{
cout<<"english character"<<endl;
}
}
输入:Hello中国 (“中国”对应的GB2312内码为:214 208,185 250)
输出:english character
english character
english character
english character
english character
chinese character
chinese character
vc/c++中的英文字符仍然采用ASCII编码方式。可以设想,其他国家程序员利用vc/c++编写程序输入本国字符时,vc/c++则会采用该国的字符编码方式来处理这些字符。
问题又产生了,韩国的vc/c++程序在中国的vc/c++上运行时,如果没有相应的内码库,则对韩语字符的显示有可能出现乱码。我个人猜测,vc安装程序中应该带有不同国家的内码库,这样一来肯定会占用很大的空间。如果所有的国家使用统一的编码方式,且所有的程序设计语言和开发工具都支持这种编码方式该多好!而现实中,确实已经有这种编码方式了,且许多新的语言也都支持这种编码方式,如Java、C#等,它就是下面的Unicode编码
3.新的内码标准---Unicode
Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。1990年开始研发,1994年正式公布。随着计算机工作能力的增强,Unicode也在面世以来的十多年里得到普及。最新版本的 Unicode 是 2005年3月31日推出的Unicode 4.1.0 。另外,5.0 Beta已于2005年12月12日推出,以供各会员评价。
Unicode 编码系统可分为编码方式和实现方式两个层次。
编码方式:Unicode 的编码方式与 ISO 10646 的通用字符集(Universal Character Set,UCS)概念相对应,目前的用于实用的 Unicode 版本对应于 UCS-2,使用16位的编码空间。也就是每个字符占用2个字节。这样理论上一共最多可以表示 216 个字符。基本满足各种语言的使用。实际上目前版本的 Unicode 尚未填充满这16位编码,保留了大量空间作为特殊使用或将来扩展。
实现方式:Unicode 的实现方式不同于编码方式。一个字符的 Unicode 编码是确定的。但是在实际传输过程中,由于不同系统平台的设计不一定一致,以及出于节省空间的目的,对 Unicode 编码的实现方式有所不同。Unicode 的实现方式称为Unicode转换格式(Unicode Translation Format,简称为 UTF)。如,UTF-8 编码,这是一种变长编码,它将基本7位ASCII字符仍用7位编码表示,占用一个字节(首位补0)。而遇到与其他 Unicode 字符混合的情况,将按一定算法转换,每个字符使用1-3个字节编码,并利用首位为0或1进行识别。
Java与C#语言都是采用Unicode编码方式,在这两种语言中定义一个字符,在内存中存放的就是这个字符的两字节Unicode码。如下所示:
char a='我'; => 内存中存放的Unicode码为:25105
4.内码的相互转换
(1)vc中的实现方法
利用Windows系统提供的API:::MultiByteToWideChar和::WideCharToMultiByte
::MultiByteToWideChar:实现当前码到Unicode码的转换;
::WideCharToMultiByte:实现Unicode码到当前码的转换;
(2)Java中的实现方法
String vcString=new String(javaString.getBytes("UTF-8"),"gb2312");
java的编码应该是UTF-8
(3)C#中的实现方法
??
四 vc中的MutiByte Charater Set 和 Wide Character Set
1.MultiByte Charater Set方式
这种方式以按字节为单位存放字符,即如果一个字符码为两字节,则在内存中占两字节,字符码为一字节,就占一字节。例如,字符串“中国abc”的编码为:中(0xd6、0xd0)、国(0xb9、0xfa)、a(0x61)、b(0x62)、c(0x63)、\0(0x00),就存为如下方式:
对应的类型,方法有:
char、scanf、printf、cin、cout …
2.Wide Character Set
这种方式是以两字节为单位存放字符,即如果一个字符码为两字节,则在内存中占四字节,字符码为一字节,就占两字节。例如,字符串“中国abc”就存为如下方式:
对应的类型,方法有:
wchar_t、wscanf、wprintf、wcin、wcout …
造成上面存储方式的根本原因在于,wchar_t类型其实是一个unsigned short 类型。如,存储上面字符串的数组的定义为:wchar_t buffer[8] 等价于unsigned short buffer[8].而所有以字母w开头的方法也都是以unsigned short类型,即两字节为单位来处理字符,因此,存储在wchar_t类型数组中的字符串无法用cout显示,只能用wcout方法来显示。
由于Unicode码也是采用两个字节,因此Wide Character Set方式能够很好的支持Unicode码的存储,但是在vc的环境下要将一个Unicode码存入两字节而不是四字节内存中,必须通过上面的API函数::MultiByteToWideChar。首先,将当前的编码转换为Unicode码,然后,将每个字符的Unicode码放入每一个wchar_t类型的变量中。以下是一个实例代码:
char input[50];
cin>>input;
int size;
size=::MultiByteToWideChar(CP_ACP,0,input,strlen(input)+1,NULL,0);
if(size==0)
return -1;
wchar_t *widebuff=new wchar_t[size];
::MultiByteToWideChar(CP_ACP,0,input,strlen(input)+1,widebuff,size);
输入:中国abc
Debug断点调试:
size==6
数组widebuff[0-size]占12字节,存放了6个字符的Unicode码,码值为:
中(0x4e2d) 国(0x56fd) a(0x0061) b(0x0062) c(0x0063) d(0x0000)
这时,数组的大小size等于输入的字符个数加上一个结束符,符合我们的想象。
五 引入问题的错误分析
(1) 没有理解编译器中的编码方式
虽然vc/c++中汉字的编码占两个字节,但并不是Unicode码,是GB2312码。
(2) 没有理解MutiByte Charater Set 和 Wide Character Set的存储原则;
在vc/c++中,“中国”按char[5]来对待,而wchar_t a[3]实际上是三个unsigned short类型的变量,因此赋值时会越界。
//gameloft 笔试题
/*
1、RGB值转灰度值对32位整数取R,G,B对应的8位并加权合成。
2、求一个字符串中出现频率最高的字符。字符范围并涡有说明,通常应
指ASCII字符集,可是当时考虑复杂了,于是想到了stl的map来做。
结果没有写完。就交了。
*/
#include<iostream>
using namespace std;
#define CHARNUM 256
//计算一个串最出现频率最高的字符
char mostFreq(const char* str)
{
int freq[CHARNUM]= {0};
int firstPos[CHARNUM] = {0};
int pos = 0;
const char* p = str;
while( *p != '\0')
{
if(freq[*p] == 0)
{
firstPos[*p] = pos;
}
freq[*p++]++;
pos++;
}
int maxF = -1;
int ch = '\0';
for(int i = 1;i < 256;i++)
{
if( freq[i] > maxF)
{
ch = i;
maxF = freq[i];
}
if( freq[i] == maxF)
{
if( firstPos[i] < firstPos[ch])
{
ch = i;
}
}
}
cout<<" maxF ="<<maxF<<endl;
return (char)ch;
}
int main()
{
int* a[9][4][5];
int b = a[5] - a[3];
cout<<"b = "<<b<<endl;
int* c[3];
char * str = "aabyebbdfdf 1`5454545$$$#$#$2788kldef";
char ch;
ch = mostFreq( str);
cout<<"ch = " <<ch<<endl;
}
4.给出一个CThing 类的源代码让分析,其中有三个语句要求解释语句作用。
一个填空,分析时有点忙了,应该一个函数一个函数的分析,或许会有清晰思路。
将各个类的名称和功能整理下会理出些思路。
5、给出strcpy的源代码让说明其功能,并指出参数设置上只少一人错误
6、给出一个将整数i转换为8进制的方法,要求对其进行改进。
src:
void count(int i, char* str)
{
map[
sorry, 记忆不清楚了
7、给几个名词让解释placement new,ARM, GCC, android, 还有一人??
8、英文解释题目。第一个还好。第二个说游戏加速的
increment ...update frame , ??这词词认识,放一起读不出来表示什么
意思
摘要: 1
2
3
4#include<cstdio>
5#include<iostream>
6#include<cstdlib>
7#include<typeinfo>&nbs... 阅读全文
摘要: 1
2
3// realize a SingleList class
4/**//*
5实现方法
6add()
7add2Head(dd);
8del
... 阅读全文
/**
* 实现测试:串匹配和词频统计功能
*/
public void largerTextExample()
{
String text = "你好abc,ac,abc,def,ac,okt, ac,dfdfe, ac , what is it 你好啊,bc";
String[] terms = {"你好","ac", "abc", "bc"};
for (int i = 0; i < terms.length; i++)
{
tree.add(terms[i].getBytes(), terms[i]);
System.out.println( terms[i]);
}
tree.prepare();
Set termsThatHit = new HashSet();
Iterator iter = tree.search(text.getBytes());
// 统计词频
Map<String, Integer> freqCount = new HashMap<String, Integer>();
for (; iter.hasNext();)
{
SearchResult result = (SearchResult) iter.next();
Set set = result.getOutputs();
System.out.println(set);
for(Iterator it = set.iterator();it.hasNext();)
{
String str = (String)it.next();
if( freqCount.get(str) == null)
freqCount.put(str, 1);
else
freqCount.put(str, freqCount.get(str)+1);
}
}
for(String key: freqCount.keySet())
{
System.out.println( "key = " + key + ", value "+ freqCount.get(key) );
}
------------结果-------------------------
你好
ac
abc
bc
[你好]
[abc, bc]
[ac]
[abc, bc]
[ac]
[ac]
[ac]
[你好]
[bc]
key = abc, value 2
key = 你好, value 2
key = ac, value 4
key = bc, value 3
从北大的WIBA课程中得知,这本中文名为《知道做到》的书,真正是我所需要的。
书的下载地址:Know and Do
以下是读书时的摘要笔记,书的语言本身已经能说明所讨论的问题了。所以并没有加上去多少自己的话。只是将重点进行了整理。
“在你的工作中,最让你感到失望的事情是什么?”
一个人行为的改变总是先从内心想法的转变开始,然后才逐渐由内而外变化的。
我的关注点一直集中在领导方法和领导行为上,却始终没有考虑过人们的大脑或内心到底在想些什么。
保罗为自己担任董事的一家大型跨国公司准备了一场主题演讲。演讲的题目是“缺失的一环:怎样才能把你从书本、录音带、电视录像或研讨班上学到的知识应用到实际工作中”。这就是《知道做到》创作的开始。
学会三样东西:
1、记笔记
2、24小时内重读笔记,整理学习内容和重点。
3、将学习内容传递给他人。
缺失的一环
1、信息过载
我们首先必须确定自己需要学什么,然后才能更有效率地去学这些东西
每个人,包括你和我的大脑总是在不断地处理一件或两件事,要么是学习新的东西,要么是遗忘。一旦忽视了某件事,我们很快就会将其遗忘。而当学会用间隔性重复来集中思考某件事时,我们就会记住它
2、消极过滤
3、缺少跟进
要想做到这点,关键就在于重复、重复、重复!这就是那缺失的一环.。
重复是克服所有知行差距的3个原因的关键。
重复的力量:这里的重复实际上是指间隔性重复
第五章 应用“少而精”哲学
知行鸿沟的存在,人们没能学以致用的原因
1:信息超载
◆对于那些只接触过一次的信息,我们通常只能记住其中一小部分。
◆我们应该少而精而非多而浅地去学习。
◆要想掌握某件事,我们必须首先选择一些关键点,隔段时间就重复一下,让自己完全沉浸其中,并不断提高自己的知识和技能。关键在于间隔性重复。
◆一旦真正透彻地掌握了自己的工作,人们就会变得更有创造性,甚至能够创造奇迹。
第六章 原因2:消极过滤
“在我们聊天的过程中,我想我明白了两件事。第一,一个对你充满信心的人可以改变你的人生;第二,我们完全可以选择自己去聆听什么。如果我总是在聆听那些否定我的人的话,我可能就会选择接受一个不是那么有挑战性的工作,对自己的期待也会变得非常有限。在爬出‘消极之匣’的过程中,我最最需要的,就是一句鼓励的话。”
第七章 积极聆听
聆听
不要带有任何偏见或先入为主;
带着一种学习的态度,对新的信息感到兴奋;
带着积极的期待;
手里拿支笔,准备做记录;
带着强烈的欲望,不仅要仔细聆听对方的讲话内容,还要努力激发出自己的形象力;
带着一种“我该如何应用这些”的态度。
企业家说:“有趣的是,呈现6次似乎正是间隔性重复秘诀。”
“为什么这么说呢?”
“我发现,当人们第一次接触时,他们会立刻拒绝,因为这个想法跟他们之前的想法有些冲突;第二次接触时,他们会抵制,因为他们仍然无法接受这个想法;第三次接触,他们会部分接受,但在实际应用的时候仍然会有所保留;第四次接触时,他们会完全接受,因为他们感觉这个想法跟自己一直以来的想法完全一致;第五次接触时,他们会将其应用到实际工作中,会部分吸收,将其转化为自己的想法;等到第六次接触时,他们会将其据为己有,完全吸收,并将其传播给其他人。”
通过自己的积极思维所体验到的积极经历越多,你就可以自动跨越这6个步骤,许多创造性的想法几乎会不知不觉地浮现出来。最终你就会像我一样成为一个反向偏执狂(inverted paranoid).
“什么是反向偏执狂?”作家问。
“反向偏执狂就是那些认为世界在合伙照顾自己的人。当一个人总是习惯进行积极思考时,他就容易成为一名反向偏执狂,但这需要一个过程。有时候人们在完成这个过程时需要帮助。”
第八章 使用绿灯思维
人们没能学以致用的原因2:消极过滤
由于在年少时并没有得到无条件的爱和支持,所以我们开始对自己和其他人产生怀疑。
自我怀疑让我们开始对所有的信息进行过滤,无论是从图书、录音带、录像、培训班,还是从谈话中获取的,在过滤的过程中,由于我们会犹豫不决,会封闭自己的观念,让自己带有先入之见,会带着批判的心态,甚至会产生一种恐惧心理,所有这一切都会让我们形成一种消极的思维方式。
消极思维会让我们,只能学到或利用自己接触到的一小部分信息;只能发挥自己的一小部分潜力;过早地拒绝大部分信息;
积极、开放的心态最有利于我们的成长,它会引发我们的创造力和应变力,最大限度地激发我们的灵感。
我们必须设法敞开自己的心胸。每次接触新信息时,我们不要总是琢磨这些信息错在哪里,而是成为绿灯思考者,积极发现其中的正确之处,并告诉自己,“我知道自己读到或听到的信息是有一定价值的,可它究竟在哪儿呢?”
将封闭、消极的心态变成开放而积极的心态并不是偶然事件。一旦下定决心要作出改变,你就需要制定一套清晰的策略,不断加强自己的新思维方式。
第九章 原因3:缺少跟进
作家点点头,“这让我想起了彼得?德鲁克(Peter Drucker)的话,‘没有什么好事是偶然发生的。’”
“一点没错,”菲尔说,“要想改变某个行为,得到自己预期的结果,你需要指导(structure)、支持(support)和问责(accountability)。当这三个要素同时具备时,你便可以制订一份出色的跟进计划。人们没有将知识转化为行动的第三个原因是缺少跟进,而这是所有障碍当中最难克服的,所以我们才需要制订一份周密的计划。”
“为什么说它是最难克服的呢?”作家问。
“这还是有一些历史背景的,”菲尔若有所思地回答,“我是从我父亲那里学到跟进策略的重要性的。他是来自德国的一名大师级木匠。他一再告诉我,除非你能得到名师指点,否则千万不要接受一份工作。”
练习,并不能帮你做到完美。
只有完美的练习才能帮你做到完美。
如何学习及订出计划。
强调积极面,帮人们取得成功
在每一位成功人士的生活中,都有一条贯穿始终的金线。那就是专注的金线,再加上坚持。所有有所成就的人都有一种独特的能力,他们能够像激光一样将自己的能量集中于一点,并在整个实现目标的过程中失重保持焦点集中。
“第一个例子,我们在公司里实行了一套一对一的学习系统,规定所有的管理者每两个星期都要跟自己的直接下属面对面地单独沟通,时间为每次15—30分钟。”
/** *//**
* 最小堆化,使用递归
*/
static void minHeapity(int[] a, int i, int size)
{
int left = (i << 1) + 1; // i * 2 + 1,当下标从0正式开始时
int right = (i << 1) + 2;
int t;
if (left < size && a[left] < a[i])
t = left;
else
t = i;
if (right < size && a[right] < a[t])
t = right;
if (t != i)
{
a[t] = a[i] + a[t] - (a[i] = a[t]);
minHeapity(a, t, size);
}
}
/** *//**
* 最小堆化,不使用递归,并且合并表示
* @param size
*/
static void minHeapityNOCur(int[] a, int i, int size)
{
int p = i;
while(p < size)
{
int q = p * 2 + 1;// q指向最小的孩子结点
if( q >= size) return;
if( q < (size-1) && a[q+1] < a[q])
q = q + 1;// q 指向右
if( a[q] < a[p])
{
a[q] = a[p] + a[q] - ( a[p] = a[q]);
p = q;
}
else break;//已经不用调整了
}
}
static void maxK( int k)
{
int[] maxKs = new int[k];
try
{
Scanner scan = new Scanner(new File("IntNums10K.txt"));
for (int i = 0; i < k; i++)
{
if (scan.hasNextInt())
{
maxKs[i] = scan.nextInt();
}
}
System.out.println("最初K个值"+ Arrays.toString(maxKs));
// builder the heap
int size = maxKs.length;
for (int i = (size - 1) / 2; i >= 0; i--)
minHeapity(maxKs, i, size);
System.out.println( "建堆后"+Arrays.toString(maxKs));
while(scan.hasNextInt())
{
int tmpN = scan.nextInt();
if( tmpN <= maxKs[0])
continue;
maxKs[0] = tmpN;
minHeapity(maxKs, 0, size);
}
System.out.println("得到最大的K个"+ Arrays.toString(maxKs));
} catch (FileNotFoundException e)
{
e.printStackTrace();
}
}
Java作为一门优秀的面向对象的程序设计语言,正在被越来越多的人使用。本文试图列出作者在实际开发中碰到的一些 Java语言的容易被人忽视的细节,希望能给正在学习Java语言的人有所帮助。
1,位移运算越界怎么处理
考察下面的代码输出结果是多少?
int a=5;
System.out.println(a < <33);
按照常理推测,把a左移33位应该将a的所有有效位都移出去了,那剩下的都是零啊,所以输出结果应该是0才对啊,可是执行后发现输出结果是10,为什么呢?因为Java语言对位移运算作了优化处理,Java语言对a < <b转化为a < <(b%32)来处理,所以当要移位的位数b超过32时,实际上移位的位数是b%32的值,那么上面的代码中a < <33相当于a < <1,所以输出结果是10。
2,可以让i!=i吗?
当你看到这个命题的时候一定会以为我疯了,或者Java语言疯了。这看起来是绝对不可能的,一个数怎么可能不等于它自己呢?或许就真的是Java语言疯了,不信看下面的代码输出什么?
double i=0.0/0.0;
if(i==i){
System.out.println("Yes i==i");
}else{
System.out.println("No i!=i");
}
上面的代码输出"No i!=i",为什么会这样呢?关键在0.0/0.0这个值,在IEEE 754浮点算术规则里保留了一个特殊的值用来表示一个不是数字的数量。这个值就是NaN("Not a Number"的缩写),对于所有没有良好定义的浮点计算都将得到这个值,比如:0.0/0.0;其实我们还可以直接使用Double.NaN来得到这个值。在IEEE 754规范里面规定NaN不等于任何值,包括它自己。所以就有了i!=i的代码。
3,怎样的equals才安全?
我们都知道在Java规范里定义了equals方法覆盖的5大原则:reflexive(反身性),symmetric(对称性),transitive(传递性),consistent(一致性),non-null(非空性)。那么考察下面的代码:
public class Student{
private String name;
private int age;
public Student(String name,int age){
this.name=name;
this.age=age;
}
public boolean equals(Object obj){
if(obj instanceof Student){
Student s=(Student)obj;
if(s.name.equals(this.name) && s.age==this.age){
return true;
}
}
return super.equals(obj);
}
}
你认为上面的代码equals方法的覆盖安全吗?表面看起来好像没什么问题,这样写也确实满足了以上的五大原则。但其实这样的覆盖并不很安全,假如Student类还有一个子类CollegeStudent,如果我拿一个Student对象和一个CollegeStudent对象equals,只要这两个对象有相同的name和age,它们就会被认为相等,但实际上它们是两个不同类型的对象啊。问题就出在instanceof这个运算符上,因为这个运算符是向下兼容的,也就是说一个CollegeStudent对象也被认为是一个Student的实例。怎样去解决这个问题呢?那就只有不用instanceof运算符,而使用对象的getClass()方法来判断两个对象是否属于同一种类型,例如,将上面的equals()方法修改为:
public boolean equals(Object obj){
if(obj.getClass()==Student.class){
Student s=(Student)obj;
if(s.name.equals(this.name) && s.age==this.age){
return true;
}
}
return super.equals(obj);
}
这样才能保证obj对象一定是Student的实例,而不会是Student的任何子类的实例。
4,浅复制与深复制
1)浅复制与深复制概念
⑴浅复制(浅克隆)
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
⑵深复制(深克隆)
被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。
2)Java的clone()方法
⑴clone方法将对象复制了一份并返回给调用者。一般而言,clone()方法满足:
①对任何的对象x,都有x.clone() !=x//克隆对象与原对象不是同一个对象
②对任何的对象x,都有x.clone().getClass()= =x.getClass()//克隆对象与原对象的类型一样
③如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。
⑵Java中对象的克隆
①为了获取对象的一份拷贝,我们可以利用Object类的clone()方法。
②在派生类中覆盖基类的clone()方法,并声明为public。
③在派生类的clone()方法中,调用super.clone()。
④在派生类中实现Cloneable接口。
请看如下代码:
class Student implements Cloneable{
String name;
int age;
Student(String name,int age){
this.name=name;
this.age=age;
}
public Object clone(){
Object obj=null;
try{
obj=(Student)super.clone();
//Object中的clone()识别出你要复制的是哪一个对象。
}
catch(CloneNotSupportedException e){
e.printStackTrace();
}
return obj;
}
}
public static void main(String[] args){
Student s1=new Student("zhangsan",18);
Student s2=(Student)s1.clone();
s2.name="lisi";
s2.age=20;
System.out.println("name="+s1.name+","+"age="+s1.age);//修改学生2
//后,不影响学生1的值。
}
说明:
①为什么我们在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?在运行时刻,Object中的clone()识别出你要复制的是哪一个对象,然后为此对象分配空间,并进行对象的复制,将原始对象的内容一一复制到新对象的存储空间中。
②继承自java.lang.Object类的clone()方法是浅复制。以下代码可以证明之。
class Teacher{
String name;
int age;
Teacher(String name,int age){
this.name=name;
this.age=age;
}
}
class Student implements Cloneable{
String name;
int age;
Teacher t;//学生1和学生2的引用值都是一样的。
Student(String name,int age,Teacher t){
this.name=name;
this.age=age;
this.t=t;
}
public Object clone(){
Student stu=null;
try{
stu=(Student)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
stu.t=(Teacher)t.clone();
return stu;
}
public static void main(String[] args){
Teacher t=new Teacher("tangliang",30);
Student s1=new Student("zhangsan",18,t);
Student s2=(Student)s1.clone();
s2.t.name="tony";
s2.t.age=40;
System.out.println("name="+s1.t.name+","+"age="+s1.t.age);
//学生1的老师成为tony,age为40。
}
}
那应该如何实现深层次的克隆,即修改s2的老师不会影响s1的老师?代码改进如下。
class Teacher implements Cloneable{
String name;
int age;
Teacher(String name,int age){
this.name=name;
this.age=age;
}
public Object clone(){
Object obj=null;
try{
obj=super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return obj;
}
}
class Student implements Cloneable{
String name;
int age;
Teacher t;
Student(String name,int age,Teacher t){
this.name=name;
this.age=age;
this.t=t;
}
public Object clone(){
Student stu=null;
try{
stu=(Student)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
stu.t=(Teacher)t.clone();
return stu;
}
}
public static void main(String[] args){
Teacher t=new Teacher("tangliang",30);
Student s1=new Student("zhangsan",18,t);
Student s2=(Student)s1.clone();
s2.t.name="tony";
s2.t.age=40;
System.out.println("name="+s1.t.name+","+"age="+s1.t.age);
//学生1的老师不改变。
}
3)利用串行化来做深复制
把对象写到流里的过程是串行化(Serilization)过程,Java程序员又非常形象地称为“冷冻”或者“腌咸菜(picking)”过程;而把对象从流中读出来的并行化(Deserialization)过程则叫做“解冻”或者“回鲜(depicking)”过程。应当指出的是,写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面,因此“腌成咸菜”的只是对象的一个拷贝,Java咸菜还可以回鲜。
在Java语言里深复制一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里(腌成咸菜),再从流里读出来(把咸菜回鲜),便可以重建对象。
如下为深复制源代码。
public Object deepClone(){
//将对象写到流里
ByteArrayOutoutStream bo=new ByteArrayOutputStream();
ObjectOutputStream oo=new ObjectOutputStream(bo);
oo.writeObject(this);
//从流里读出来
ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi=new ObjectInputStream(bi);
return(oi.readObject());
}
这样做的前提是对象以及对象内部所有引用到的对象都是可串行化的,否则,就需要仔细考察那些不可串行化的对象可否设成transient,从而将之排除在复制过程之外。上例代码改进如下。
class Teacher implements Serializable{
String name;
int age;
Teacher(String name,int age){
this.name=name;
this.age=age;
}
}
class Student implements Serializable
{
String name;//常量对象。
int age;
Teacher t;//学生1和学生2的引用值都是一样的。
Student(String name,int age,Teacher t){
this.name=name;
this.age=age;
this.p=p;
}
public Object deepClone() throws IOException,
OptionalDataException,ClassNotFoundException
{
//将对象写到流里
ByteArrayOutoutStream bo=new ByteArrayOutputStream();
ObjectOutputStream oo=new ObjectOutputStream(bo);
oo.writeObject(this);
//从流里读出来
ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi=new ObjectInputStream(bi);
return(oi.readObject());
}
}
public static void main(String[] args){
Teacher t=new Teacher("tangliang",30);
Student s1=new Student("zhangsan",18,t);
Student s2=(Student)s1.deepClone();
s2.t.name="tony";
s2.t.age=40;
System.out.println("name="+s1.t.name+","+"age="+s1.t.age);
//学生1的老师不改变。
}
佛经里的人生哲理
收藏
快乐使者 @ 2007-12-08 22:36:32
1、人之所以痛苦,在于追求错误的东西。
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、当你未学佛的时候,你看什么都不顺。当你学佛以后,你要看什么都很顺。
32、你要包容那些意见跟你不同的人,这样子日子比较好过。你要是一直想改变他,那样子你会很痛苦。要学学怎样忍受他才是。你要学学怎样包容他才是。
33、承认自己的伟大,就是认同自己的愚疑。
34、修行就是修正自己错误的观念。
35、医生难医命终之人,佛陀难渡无缘的众生。
36、一个人如果不能从内心去原谅别人,那他就永远不会心安理得。
37、心中装满着自己的看法与想法的人,永远听不见别人的心声。
38、毁灭人只要一句话,培植一个人却要千句话,请你多口下留情。
39、当你劝告别人时,若不顾及别人的自尊心,那么再好的言语都没有用的。
40、不要在你的智慧中夹杂着傲慢。不要使你的谦虚心缺乏智慧。
41、根本不必回头去看咒骂你的人是谁?如果有一条疯狗咬你一口,难道你也要趴下去反咬他一口吗?
42、忌妒别人,不会给自己增加任何的好处。忌妒别人,也不可能减少别人的成就。
43、永远不要浪费你的一分一秒,去想任何你不喜欢的人。
44、多少人要离开这个世间时,都会说出同一句话,这世界真是无奈与凄凉啊!
45、恋爱不是慈善事业,不能随便施舍的。感情是没有公式,没有原则,没有道理可循的。可是人们至死都还在执著与追求。
46、请你用慈悲心和温和的态度,把你的不满与委屈说出来,别人就容易接受。
47、创造机会的人是勇者。等待机会的人是愚者。
48、能说不能行,不是真智慧。
49、多用心去倾听别人怎么说,不要急着表达你自己的看法。
50、同样的瓶子,你为什么要装毒药呢?同样的心理,你为什么要充满着烦恼呢?
51、得不到的东西,我们会一直以为他是美好的,那是因为你对他了解太少,没有时间与他相处在一起。当有一天,你深入了解后,你会发现原不是你想像中的那么美好。
52、这个世间只有圆滑,没有圆满的。
53、修行要有耐性,要能甘于淡泊,乐于寂寞。
54、活着一天,就是有福气,就该珍惜。当我哭泣我没有鞋子穿的时候,我发现有人却没有脚。
55、多一分心力去注意别人,就少一分心力反省自己,你懂吗?
56、眼睛不要老是睁得那么大,我且问你,百年以后,那一样是你的。
57、欲知世上刀兵劫,但听屠门夜半声。不要光埋怨自己多病,灾祸横生,多看看横死在你刀下的众生又有多少?
58、憎恨别人对自己是一种很大的损失。
59、每一个人都拥有生命,但并非每个人都懂得生命,乃至于珍惜生命。不了解生命的人,生命对他来说,是一种惩罚。
60、自以为拥有财富的人,其实是被财富所拥有。
61、情执是苦恼的原因,放下情执,你才能得到自在。
62、随缘不是得过且过,因循苟且,而是尽人事听天命。
63、不要太肯定自己的看法,这样子比较少后悔。
64、当你对自己诚实的时候,世界上没有人能够欺骗得了你。
65、用伤害别人的手段来掩饰自己缺点的人,是可耻的。
66、世间的人要对法律负责任。修行的人要对因果负责任。
67、在你贫穷的时候,那你就用身体去布施,譬如说扫地、洒水、搬东西等,这也是一种布施。
68、内心充满忌妒,心中不坦白,言语不正的人,不能算是一位五官端正的人。
69、默默的关怀与祝福别人,那是一种无形的布施。
70、多讲点笑话,以幽默的态度处事,这样子日子会好过一点。
71、与人相处之道,在于无限的容忍。
72、不要刻意去猜测他人的想法,如果你没有智慧与经验的正确判断,通常都会有错误的。
73、要了解一个人,只需要看他的出发点与目的地是否相同,就可以知道他是否真心的。
74、人生的真理,只是藏在平淡无味之中。
75、不洗澡的人,硬擦香水是不会香的。名声与尊贵,是来自于真才实学的。有德自然香。
76、与其你去排斥它已成的事实,你不如去接受它,这个叫做认命。
77、佛菩萨只保佑那些肯帮助自己的人。
78、逆境是成长必经的过程,能勇于接受逆境的人,生命就会日渐的茁壮。
79、你要感谢告诉你缺点的人。
80、能为别人设想的人,永远不寂寞。
81、如果你能像看别人缺点一样,如此准确般的发现自己的缺点,那么你的生命将会不平凡。
82、原谅别人,就是给自己心中留下空间,以便回旋。
83、时间总会过去的,让时间流走你的烦恼吧!
84、你硬要把单纯的事情看得很严重,那样子你会很痛苦。
85、永远扭曲别人善意的人,无药可救。
86、人不是坏的,只是习气罢了,每个人都有习气,只是深浅不同罢了。只要他有向道的心,能原谅的就原谅他,不要把他看做是坏人。
87、说一句谎话,要编造十句谎话来弥补,何苦呢?
88、其实爱美的人,只是与自己谈恋爱罢了。
89、世界上没有一个永远不被毁谤的人,也没有一个永远被赞叹的人。当你话多的时候,别人要批评你,当你话少的时候,别人要批评你,当你沈默的时候,别人还是要批评你。在这个世界上,没有一个不被批评的。
90、夸奖我们,赞叹我们的,这都不是名师。会讲我们,指示我们的,这才是善知识,有了他们我们才会进步。
91、你目前所拥有的都将随着你的死亡而成为他人的,那为何不现在就布施给真正需要的人呢?
92、为了赞美而去修行,有如被践踏的香花美草。
93、白白的过一天,无所事事,就像犯了窃盗罪一样。
94、能够把自己压得低低的,那才是真正的尊贵。
95、广结众缘,就是不要去伤害任何一个人。
96、沈默是毁谤最好的答覆。
97、对人恭敬,就是在庄严你自己。
98、拥有一颗无私的爱心,便拥有了一切。
99、仇恨永远不能化解仇恨,只有慈悲才能化解仇恨,这是永恒的至理。
100、你认命比抱怨还要好,对于不可改变的事实,你除了认命以外,没有更好的办法了。
一个29岁总裁对大学生的16条忠告
上一篇 / 下一篇 2009-02-25 09:44:33 / 个人分类:SAP
一、读大学,究竟读什么?
大学生和非大学生最主要的区别绝对不在于是否掌握了一门专业技能……一个经过独立思考而坚持错误观点的人比一个不假思索而接受正确观点的人更值得肯定……草木可以在校园年复一年地生长,而我们却注定要很快被另外一群人替代……尽管每次网到鱼的不过是一个网眼,但要想捕到鱼,就必须要编织一张网……
二、人生规划:三岔路口的抉择
不走弯路就是捷径…… 仕途,商界,学术。在这人生的三岔路口,你将何去何从……与其跟一百个人去竞争五个职位,不如跟一个人去竞争一个职位……学术精神天然的应当与尘嚣和喧哗保持足够的距离……商场不忌讳任何神话。你也完全可能成为下一个传奇……
三、专业无冷热,学校无高低
没有哪个用人单位会认为你代表了你的学校或者你的专业……既然是概率,就存在不止一种可能性……如果是选择学术,冷门专业比热门专业更容易获得成就……跨专业几乎早已成为一种流行一种时尚……大学之间的实力之争到了考研考场和人才市场原来是那样的微不足道……
四、不可一业不专,不可只专一业
千招会,不如一招熟…… 十个百分之十并不是百分之百,而是零……在这个现实的社会,真正实现个人价值才是最体面最有面子最有尊严的事情……要想知道需要学什么,最好的方式就是留意招聘信息……很多专业因为不具备专长的有效性,所以成为了屠龙之术……为什么不将“买一送一”的促销思维运用到求职应聘的过程中来呢……
五、不逃课的学生不是好学生
什么课都不逃,跟什么课都逃掉没什么两样……读大学,关键是学会思考问题的方法……逃课没有错,但是不要逃错课……英语角绝对不是学英语的地方……为了英语丢了专业,那就舍本逐末了……招聘单位是用人才的地方,而不是培养人才的地方……既要逃课,又要让老师给高分……
六、勤工俭学的辩证法
对于贫困生来说,首先要做的不是挣钱,而是省钱……大部分女生将电脑当成了影碟机,大部分男生将电脑当成了游戏机……在这个处女膜都可以随意伪造的年代,还有什么值得轻易相信……态度决定一切……当学习下降到次要的地位,大学生就只能说是兼职的学生了……
七、做事不如做人,人脉决定成败
学问好不如做事好,做事好不如做人好……会说话,就能减少奋斗三十年……一个人有多少钱并不是指他拥有多少钱的所有权,而是指他拥有多少钱的使用权……一个人赚的钱,12.5%是靠自身的知识,87.5%则来自人脉关系……三十岁以前靠专业赚钱,三十岁以后拿人脉赚钱……你和世界上的任何一个人之间只隔着四个人……
八、互联网:倚天剑与达摩克利斯之剑
花两个小时就写出一篇天衣无缝的优秀毕业论文……在互联网领域创业的技术门槛并不高,关键的是市场眼光和营销能力……轻舞飞扬已经红颜薄命了,而痞子蔡却继续跟别的女孩发生着一次又一次的亲密接触……很多大学生的网友遍布祖国大江南北,可他们却从未主动向周围的人说一声:你好,我们可以聊聊吗……
九、考研:痛苦的安乐死
没有比浪费青春更失败的事情了……研究生扩招的速度是30%,也就意味着硕士学历贬值的速度是30%……同样是付出三年的努力,你可以让E1的值增加1,也可以让E2的值增加2甚至增加3……读完硕士或博士并不等于工作能力更强……面对13.54万的成本,你还会毫不犹豫地投资读研究生吗……努力就会有结果,但不一定是好结果……
十、留学:“海龟”变“海带”
月薪2500元的工作,居然引得三个“海归”硕士争相竞聘……对于某些专业而言,去美国留学和去埃塞俄比亚留学没什么两样……既然全世界的公司都想到中国的市场上来瓜分蛋糕,为什么中国人还要一门心思到国外去留学然后给外国人打工……
十一、非统招:养卑照样处优
她在中国信息产业界创下了几项纪录。她被称为中国的“打工皇后”。而她不过是一名自考大专生……要想把曾经输掉的东西赢回来,就必须把自己比别人少付出的努力补上来……非统招生不但要有一定的实力,而且必须掌握一定的技巧,做到扬长避短出奇制胜……路在脚下。好走,走好……
十二、毕业:十面埋伏的陷阱
母校不把自己当母亲,你又何必把自己当儿女……听辅导班不过是花钱买踏实……人才市场就是一个地雷阵……通过多种方式求职固然没有错,但是千万不要饥不择食……只要用人单位一说要你交钱,你掉头就走便是了……这年头立字尚且不足以为据,更何况一个口头约定……
十三、求职:做人不要太厚道
求职简历必须突出自己的核心竞争力……求职的时候大可不必像严守一那样“有一说一”……一个人说假话并不难,难的是把假话说到底,并且不露一丝破绽……在填写自己的特长时,一定要尽可能详细……一份求职简历只要用一张A4纸做个表格就足够了……面试其实是有规律的,每次面试的时候只要背标准答案就行了……
十四、骑一头能找千里马的驴
美国铁路两条铁轨之间的标准距离是4英尺8.5英寸,为什么呢?因为两匹马臀部之间的宽度是4英尺8.5英寸……垃圾是放错位置的人才……世界上最大的悲剧莫过于有太多的年轻人从来没有发现自己真正想做什么……中小型企业或许能够让你得到更充分的锻炼……从基层做起并不意味着可以从基层的每一个职位做起……要“钱途”,更要前途……
十五、写字楼政治:白领必修课
大公司是做人,小公司是做事……职员能否得到提升,很大程度不在于是否努力,而在于老板对你的赏识程度……公司的事情和秘密永远比你想象的还要复杂和深奥……在适当的时候装糊涂不但是必要的,而且是睿智的……就把你的同事当成一群你可以叫得出名字的陌生人好了……
十六、创业:29岁以前做富翁
瘦死的骆驼比马大……撑死胆大的,饿死胆小的……不再是“大鱼吃小鱼”,而是“快鱼吃慢鱼”……对于趋势的把握是一个创业者最重要的能力……高科技行业留给毕业生的空间已经很小……欲速则不达。在创业以前通过给别人打工而积累经验是非常必要的……市场永远比产品更重要……钱不够花,怎么办?第一,看菜吃饭;第二,借鸡生蛋……
嵌入式编程面试:
笔试题目大概如下:
1:关于指针长度,字符串长度的问题
2:进程间的同步的方式有几种?
3:什么是可重入代码?如何写可重入代码?
4:printf()等可变函数的实现机理
5:volatile 变量的用途?
6:写一个在双链表中插入节点和删除节点的程序。
7:将一个int型a 的第9位置1,将a的第9位置0;
第一关过去还剩下两个人。
然后是IQ测试:
就是网上的一个比较流行的flash测试 结果我的IQ 136,我都把自己下了一跳。
然后是诚信度测试:
也是回答问题,对一个问题翻过来翻过去的问,用好的方式以及不好的方式问你,看你前后的回答是否一致。
好像到这里就剩我一个人了。
同学的blog地址在: http://blog.szu.edu.cn/user/zdl1016
可以有机会自己去学习吧。有模式识别的笔记,还有图像处理和人脸识别的相关内容。
最后是:程序主管出来面试
问题1:
自己简单介绍一下:我就说 06毕业,工作两年了。做CPP。游戏开发。
对公司了解有多少:我没有投你们的简历,然后来的比较匆忙,了解不多。
那人说:我们公司以前只做什么接口转换器的,在赛格有个柜台,后来发展的比较好,招了一批人。然后又发展,就在中银租了一整层。现在工厂在关外梅林。
然后谈了一些技术:
1说使用什么math操作系统。。。
据说嵌入式操作系统中还有一个美国军方的小的七十年代用来控制导弹的嵌入式操作系统。
还说C里面都有自己的一套数据结构,vector等,都要自己实现。(说道这里,搞懂opencv里面的seq挺有用的一定!)
2说用arm7,arm9做平台。
谈待遇,那人说没经验给3000(的确,我没什么嵌入式经验,不过C用的还可以)
这是转载的东亮的笔记,原来他上课看书都会在博客里写笔记,我当时讲了最后一个线性分类器的分类能力。
模式识别理论 chapter 9 Algorithm-independent Machine Learning
| 浏览数(269) | 评论数(0) | 2008-06-26
本章是同学自己讲述,有些观点可能有些问题.
1: 没有免费的午餐: 对特定问题的先验认识的条件下, 没有最优的分类器.
2: 丑小鸭定理: 对特定问题的先验认识的条件下,没有最优的特征表达.
3: occam' razor: 杀鸡焉用牛刀? 小的剃须刀就可以了,干吗用电锯??? keep it simple,stupid. 简单就是美.
爱因斯坦:描述一个问题,解决一个问题,要尽可能的简单,但不要更简单.
杜达:长期的进化过程, 使我们自身的"模式识别仪器"面临强大的自然选择的压力---要求执行更简单的计算,需要更少的神经元,花费更短的时间,等等,导致我们的分类器趋向简单的方案.
沃伦.巴菲特:盖茨的成功不在于他做了什么,而在于他没做什么.
一个人要专注做一件事情,理想太多了, 变得没有理想了.
总之,我们的分类器要尽可能保持简单,因为,简单的通常是最有效的.这是经验!
4: 回归中的偏差和方差关系
4.1)
偏差小: 准确度高
方差小: 推广性好.
4.2)
曲线拟合的均方误差 = 偏差^2 + 方差. 与两者都有关系
5: 刀切法 和 自助法
由于现实中,获取样本往往是比较困难的,怎么充分的利用好手里的现有的样本???
刀切法: 降低样本中噪声的影响.每次统计模型的参数信息的时候, 去掉一部分样本.
自助法: 把样本分为多个独立的自助集.相当于多次重复里利用手里的样本.
6: bagging & boosting & 基于查询的学习
略去.
7:单个分割平面的能力
也就是说 线性分类面的能力???
一般位置: d维空间的点, 没有d+1个点落在d-1维子空间时,我们称这些点处于一般位置.
eg: d=1,一维空间的点. 如果没有2两个点落在0维子空间(也就是处在同一个点上.)
eg: d=2,2维空间的点. 如果没有3两个点落在1维子空间(也就是处在同一个线上.)
正是由于线性分类器的弱点,
---我们引入了非线性分类器 BP --- 改变分类面的线性关系为非线性
---我们引入了SVM --- 改变样本点的空间位置使之可以使用线性分类器.
一般位置:
あ隐 |
2009-10-31 15:23 |
一、前言
群P可能对于许多同学来说都是一个恶梦,因为对面试形式的不熟悉,因为紧张而讲话不清,甚至对讨论的题目毫无概念,小弟曾经也有这样的疑惑,不过一个学期走来,成功通过了北电、安永、爱立信、美的、瑞安建业、万科、雀巢、GE医疗等企业的群面,还是积累了一些经验,觉得相对单面来说,群面的技巧性还是相对多一些。个人感觉单面的不确定因素太多,很多时候都要靠面试官的喜好与心情来决定,而群面的评判标准相对多一点,也相对量化一些,所以应对之策会多一些。现在把自己的一点心得体会写出来,希望对仍为群面烦恼的兄弟姐妹以及后来人有所帮助。
二、群面的分类
1、广义的群P
只要面试官或面试者的人数多于1的面试多算群P,从面试者对面试官的角度来说,一般有1对多,多对1以及多对多:
1对多:
这种面试的实质还是单面,能够用的技巧与单面差不多,这里就不献丑了,主要要注意的是尽量照顾各位面试官的感受,在自我介绍与回答问题的时候尽量与所有的面试官都有眼神的交流,但转换不要太频繁,看着一个面试官说一段,下一段的时候看另一个面试官,尽可能表现自然。当然,在思考的时候,不一定始终看着某一个面试官。
多对1:
这种是最猥琐最受面试者鄙视的面试方式,产生根源是招聘企业的HR懒!!为了节省时间,面试官希望在短时间内从人群中挑出表现突出的人。一般的流程是,每个人轮流自我介绍,然后面试官提问。根据面试者人数与面试时长不同,面试官的提问方式有所不同,人多时间少,一般就面试官挑感兴趣的面试者进行提问。相反,人不多时间充足的话,则提出同样的问题,让面试者轮流回答。对于前者,关键就是自我介绍。除了要精心准备自己的自我介绍,学会扬长避短以外,更重要的是准备不同长度的版本,如5秒(可用于回答“请用一个词或一句话来介绍你自己”、“你最大的特点是什么”、“你身边的人是如何评价你的”等单面的问题)、30秒、1分钟、5分钟、10分钟。宗旨就是在指定的时间内尽可能突出自己(当然是优点啦),让面试官记住自己。过了自我介绍以后,后面基本同单面。对于后者,前面所说的自我介绍同样适用,因为这是表现自己的最好时机,但更重要的是后面问题回答。对于这个部分,虽然性质和单面差不多,但难度更大,应为面试官会有所对比。这就要求我们在面试前做好充分的准备,包括简历与开放性问题。对于简历,最好使用STAR法则来回答,而且努力使得自己的例子丰满,自己所做的每一个工作与决定都是经过严密的思考的。对于开放性问题,不仅要根据自己的实际情况来思考,还要想一下大部分的人会怎么回答,自己能够有怎样独到的见解呢。做好准备以后,就是面试时候回答的时机了,一般来说,面试官对不会限定面试者回答的顺序,而是倾向于是否有自愿的人。对于自己比较有把握的问题,或者有独到见解的问题,可以选择主动回答。而对于只能自能其说,毫无特色答案的问题,则一定要主动回答,抢占先机,把自己能想到的都说出来。最后对于毫无想法的问题,先听听别人的观点则是不错的选择,最后做一个有保留的同意性总结是一个折中的做法。当然,这些都没有绝对,即使所有问题你都很有把握,也可以适当收敛,让其他人先答,而不要表现得过于强势。
多对多:
这种面试是上面两种的综合版,但一般人数不会太多,需要注意的地方还是上面那些,前期准备、回答时机与照顾所有面试官。
2、狭义的群P
上面的主要还是与单面比较类似,现在讨论的才是真正的群面,比较常见的有无领导小组讨论、案例分析、角色扮演、辩论等方式,各有各的特点。下文所提到群面均是狭义的群面,以无领导小组讨论为主,其他方式的群面的不同点会另外提。
三、群面的形式
无论是那种方式的群面,其本的布局都差不多,多对多,一位面试官做开场白,包括面试流程与要求等。面试开始后,面试官不再发言,也不会参与到讨论当中,整个过程到结束全部有面试者自己掌握,面试官会分布在面试场地的不同角落观察各面试者的表现并做记录。当然面试过程是有限定时间的,结束的时候面试官会宣布时间到。
有些公司会在面试开始之前让面试者用白纸做个纸牌,上面写上自己的名字,方便面试官辨认。
对于面试者来说,大家都会坐到一起,而不会是并排,因为要方便讨论。而通常公司都会准备好相关的资料与纸笔。面试正式开始后,面试者花一小段时间独自阅读并思考,就最后小组所需要完成的任务思考自己的意见并做适当的记录。然后是各面试者轮流初步发表自己的想法。接着是自由讨论。最后根据具体要求来做总结陈述,一般在向面试官做最后的陈述之前,小组内应该先就总结的内容做一次汇总并达成共识或加以补充(这一步不一定有,北电的角色扮演就是了)。
面试结束后,公司需要回收所有的资料,包括草稿纸,所以一般会禁止面试者在资料上做笔记和记号,这个要注意。而对于草稿纸来说,是不是对面试结果有所影响的话很难说,不过养成一个良好的笔记习惯是没有坏处的,呵呵。
四、指导思想
说了那么多,还没有说什么技巧性的东西,这是为什么呢?其实个人认为,技巧永远都是用于加分的,而讨论的实质与内容才是关键,所以我们应该关注以及思考的重点应该放在讨论的问题上。
一般来说,群面的问题都是非专业的,主要考察面试者的分析能力、逻辑思维能力、创新能力以,解决问题能力以及临场反应等(其他的表达能力、团队合作精神等不在此部分讨论)。所谓的指导思想,其实没有别的,我们高中到大学一直所学的哲学就足够用了。辩证法,两分法、抓住主要矛盾,大局观,世界是不断变化发展的等等,这些都是大家学过并且很容易理解的道理,但是在平常的生活乃至面试里面,我们都难以运用这些道理来帮助我们分析问题。
在我的经历中,其实并不是所有的道理都会完全用到,只要抓住两个:大局观、纵横分析
1、大局观
很多同学在看完材料的时候,一发言就抓住最后要解决的问题不放,单纯地谈自己解决方案。我的做法是,先对材料做一个整体的分析,把几个问题理清:材料基于一个怎样的环境与前提,材料中最大的问题(不一定是需要我们讨论解决的问题,但有可能是所有问题的根源)是什么,问题产生的前因后果以及相互的逻辑关系是什么,我们应该订立一个什么样的标准去看待问题。有了逻辑分析与标准以后,我才会根据自己的分析与标准提出自己的观点。这样做的好处是,可以对问题有一个全局的了解,而不会捡了芝麻丢西瓜,同时也可以向面试官表现自己的各方面能力。
2、纵横分析
材料基本分析好以后,就要在论点或观点上见高下了。在面试的时候,大家的观点难免落于俗套,但还是有办法使得自己的观点尽可能丰满的。
横向分析:
这个是最容易的,尽量多想支持自己观点的例子,可以是从同类型的,也可以从不同类型的,下面举例说明。当然,小弟水平有限,不仅所举的例子与我要说的东西不一定相符,甚至我自己提的观点也是比较弱智,所以仅供参考,大牛们见笑了。
雀巢题:
辩论:选择越多,幸福是越多还是越少?
我方观点:选择越多,幸福越多
从生活出发,衣食住行四个方向找论据,校服、饭堂菜式、住房户型选择、出行交通工具等,都是选择越多越好。发散到平时的娱乐方式,如睡前听的音乐,电视节目的多样性等。结合当前找工,从招聘企业和应聘者出发,都是选择越多越好……
横向分析在辩论赛中非常有用,给以让自己的队友从不同方面来论证观点,从而让所有人都有话可说,有机会表现自己,而且对整个团队的表现都会给人一体的感觉。当时我们的反方所提的分论点并没有明显的逻辑关系,因此每个人起来发言的内容都差不多,重复性就很大了。另外一个好处是,自由辩论的时候,我们很容易主导话题,因为范围广,随便都能找到例子,可以从多点发起攻击。
纵向分析:
这个主要是意识问题,很容易被忽略。很多时候在发表观点的时候,把这个意识用在补充说明的话会给人思维严密的感觉。具体是指自己的观点只适用于局部的时间范围,因为所有东西都是不断发展变化的。
万科题:
小组讨论:成功的定义?在骂声中成名,算不算成功?背景资料:章子怡,胡戈
横向分析:成功的定义可以分成两个方面来讨论(定标准),个人价值与社会价值。
成功对于不同的人有不同的含义,即使是普通的老百姓,只要他对自己的工作、家庭和生活都感到满意,那么他就是成功了
纵向分析:一时与一生相结合,瞬间的辉煌不等于永恒。材料所提到的人物即使是成功,也是暂时的,还不能直接判断这个人的成功是一生的。
对于案例分析case study,其实一般是用在培训而不是招聘中的。而在面试中的案例分析,其实跟无领导小组讨论差别不大,主要是侧重点不同。案例分析会更加关注得出结论的思考过程与理由。
五、角色分工
终于谈到一点技巧性的问题了,首先不得不说的是,很多人都听说过群面一般都有不同的角色,包括时间控制time controller,leader,记录员,总结者等等,有些同学很喜欢在面试前就做好这个分工,指定好各人的角色。对于这种做法,我是比较反对的,首先一点,这些角色从来都不需要告诉面试官,面试官自己会有自己的判断。其次,除了time controller外,其他角色的确定都不利于小组各人的最终表现。首先是leader,这个东西根本不用明说,不然还有可能引起争抢,而最关键的是,在讨论结束前,大家都不知道谁有能力当好LEADER,因此还是通利合作好,只要大家有时间观念,不过分关注细节,注意完成讨论的所有要求,那么没有明确的leader又有什么所谓呢?然后是记录员,其实这个是最不好的,理想的做法是所有人都要做笔记,不仅是自己的观点,还有别人的观点。因为如果你的发言只是从自己的角度出发,将会非常片面。而只有你认真听取并记录了他人的意见的时候,才会有机会去分析别人的观点,从而提出反驳或者改善自己的观点。最后是总结者,通常来说,总结者需要比较清晰的思路,也就是我之前所说的大局观与逻辑思维,能够把众人的观点清晰地串起来,而这个通常都不会有记录员来做,而同样地,在讨论结束前是难以知道哪位最适合做这个总结的。
概括一下各种角色的职责吧:
Time controller:注意安排整个讨论的流程,每个环节需要多长时间,差不多到时的时候提醒所有成员。
Leader:这个职责比较模糊(本来就是无领导小组讨论嘛),一般就是主持整个讨论的进程,提醒成员不要离题、注意发言长度等,当然还有其他素质,后面会再提。
记录员:清楚记录所有人的观点与发言,并整理给总结者。这个需要清晰的笔记能力,尽量减低总结者的阅读困难。一般字不要太难看,各人观点层次分明,按点罗列,并做适当的着重标记。
总结者:把小组讨论的结果向面试官陈述,主要注意的是说话的逻辑性与条理性,最好能够把小组成员思考的过程说明一下。当然,有些陈述的量比较大的话,可以把分论点让给其他成员来扩展。
针对角色扮演这种方式,我就玩过一次,最大的感觉就是要充分融入角色,而且在看完材料后,第一时间和其他角色的成员进行交流。因为通常,一个角色所持有的材料不会有其他角色的内容,所以只有通过充分的交流才能了解到整个讨论的情况以及要实际要解决的问题。
六、技巧与注意事项
以下是小弟总结的一些小技巧,在群面上还是可以适当运用来给自己加分的,当然这个效果很难说,大家斟酌一下咯。
初级版:
1、抢做time controller
每次面试之前把手表或者手机拿在手里,在面试官说完面试流程与要求后,直接把计时的东西拍到桌子上,说上一句“现在是×点×分,我们有×分钟来做……,最后留×分钟做总结,也就是到×点×分,那么我们现在就开始做……吧”。一般来说,就不会有人跟你抢了。当然,抢到了还是要尽职尽责的啊。
2、在强势的人面前争取发言权
这个是很多同学都烦恼,这个讨论下来总是那几个人在说话,自己一句都没插上。主要是靠狠和抓住时机。一般来说,强势的人发言都比较有逻辑性和条理性。因此插嘴时机有二,一是当他解释自己观点的时候,说到一定时间我们就可以插嘴说,“我觉得××说得很有道理,但是由于时间有限,我们还是听一下下一位同学的意见吧”,或者“……(同前),我们还是先讨论下一个问题吧,我觉得……”;二是在对方阐述多个观点的时候用到“第一”、“第二”之类的,在他说完第三个要说第四的时候就插嘴,内容可以同前。
3、面试前相互认识,交换联系方式
虽然说不要提前分工,但提前认识还是有好处的。一是在讨论的时候,赞成或否定他人意见的时候可以加入对方的姓名,而不用只是说“这位同学”,“那位同学”的。二是可以拉上同路的人,在面试结束后有人一起走,并多一些交流的机会。三是可以互通消息,知道自己是否被BS了,而不用受漫长等待的折磨。
4、提反对观点
一般来说,标新立异的风险还是比较大的,但是如果有把握的话,还是可以适当提出反对意见。这个技巧主要是在说话的方式上,“我觉得大家的观点非常棒,但是如果从××角度来考虑的话,我觉得可以……,不知道大家有什么看法呢?”这里还隐含了一个小技巧,就是学会赞美别人,不管什么时候,这招都是很有用的,包括在辩论中。
5、注意材料的限定条件
在看材料的时候,很容易就一些大点直接进行分析,从而忽略了限定条件。如一个公司的沟通出现问题,究竟是个别同事之间,还是上司与下属之间,还是各个部门之间,这些对于我们考虑问题都是很重要的。我们要做的是,在大家都忽略这些的时候,适当提醒一下,但不要强求所有人都接受,只要说了,面试官是会注意到的。
6、发言的逻辑性与条理性
逻辑性主要是弄清楚各点的因果关系,最好能够把自己思考的过程简短说一下。条理性就是要按点来说,学会使用“第一”、“首先”、“最后”等过渡词。这个技巧一般是平时有意养成习惯,面试的时候就会得心应手了。当然要注意的是,分点说明前一定要清楚自己要讲多少点,不要只有“首先”,讲完之后就什么都没有了。
中级版:
1、尽量不要做最后向面试官陈述的人,而是之前在小组内做总结的人。
这样做是因为,最后做陈述的人还是会比较紧张的,即使之前总结的内容有多充分,要完美演出还是有一定难度的。但是怎么向面试官表现自己的总结能力呢?就是这个时候了,当差不多到点的时候,大家的意见都发表得差不多的时候,就可以说“其实大家的观点都非常好,我看时间快要到了,我自己稍稍总结了一下,看看大家有什么补充吧。首先……”。这样做,对于自己的好处是比较明显的,因为即使最后的总结者总结得好,也有你的功劳。但是,稍微有点损人品的是,如果最后的总结者并不够强的时候,很容易受到你思路的影响,从而表现失常。
2、留意并照顾没有或少发言的成员
这个技巧并不总有机会用,只有出现比较紧张,缺乏经验的成员的时候才可以用。在轮流发表观点甚至是自由讨论的时候,我们都要时刻关注比较沉默的成员,当要开始换话题的时候,我们可以说“不如我们先听一下××同学的意见吧”。之前不是说不要抢leader吗,这个动作就会让面试官觉得你有leader的素质了,因为照顾到所有的成员。
3、自由辩论时,没有必要与同一个人做持久的争执
当有人反驳或者质疑自己观点的时候,我们很容易忍不住跟对方争辩,然后两个人就一直站着你一言,我一句地吵,这个很明显就不好啦。其实我们没有必要起来回应他,同队的其他辩手会回应的。这样的好处是,避免把自由辩论变成个别的针锋相对,同时也表现了自己的冷静与团队合作精神。当然,如果队友没有人起来回应的话,还是要靠自己了。
4、做一个协调者
当小组成员出现意见相左的时候,如果人数比较平均,一般到最后还是采取投票比较省时。但如果一面倒的时候,我们可以以大多数人的意见为主,适当考虑另类意见作为补充,并且称赞提意见的同学“有创意”。这样同样是起到让面试官觉得你是一个leader的效果。
高级版:
研发ing……讨教中……
七、结束语
啊,终于搞定了……
一般公司都会采用群面来作为一面,考察的主要是综合素质,不同公司考察的要点以及标准都不会有太大的差异,因此作为应聘者,我们没有必要像单面那样“做好自己”。其实,小组讨论所考察的素质对于每个人来说都很值得去培养,特别是逻辑思维。所以,我们可以适当地把自己往这个方向靠,如果真的是想通过某次群面的话。
以上所有言论都是个人观点,仅供参考,因为最关键的是,从来都没有专业人士出来告诉我上面的东西是否正确有用,可能还有反作用。所以各位看官还是自己思考一下,特别是最后的技巧,要慎用啊……
找工是一个漫长的过程,同时也是一个成长的过程。在一个学期的找工经历当中,感觉自己学到的东西比前3年的还要多,当然不是指专业知识啦。还是那一句,现在什么都说人品,希望这点东西能够帮到有需要的人吧,为自己攒点人品。
最后,祝愿大家都能找到自己喜欢的工作,欢迎大家批评指教! |
|
整理者注:钱老去世以后,许多人问我们:钱老有什么遗言?并希望我们这些身边工作人员写一篇“钱学森在最后的日子”的文稿。我们已告诉大家,钱老去世时很平静安详,他没有什么最后的遗言。因为在钱老去世前的一段日子,他说话已经很困难了。我们可以向大家提供的,是钱老最后一次向我们作的系统谈话的一份整理稿:钱老谈科技创新人才的培养问题。那是于2005年3月29日下午在301医院谈的。后来钱老又多次谈到这个问题,包括在一些中央领导同志看望他时的谈话。那都是断断续续的,没有这一次系统而又全面。今天,我们把这份在保险柜里存放了好几年的谈话整理稿发表出来,也算是对广大读者,对所有敬仰、爱戴钱老的人的一个交代。
今天找你们来,想和你们说说我近来思考的一个问题,即人才培养问题。我想说的不是一般人才的培养问题,而是科技创新人才的培养问题。我认为这是我们国家长远发展的一个大问题。
今天,党和国家都很重视科技创新问题,投了不少钱搞什么“创新工程”、“创新计划”等等,这是必要的。但我觉得更重要的是要具有创新思想的人才。问题在于,中国还没有一所大学能够按照培养科学技术发明创造人才的模式去办学,都是些人云亦云、一般化的,没有自己独特的创新东西,受封建思想的影响,一直是这个样子。我看,这是中国当前的一个很大问题。
最近我读《参考消息》,看到上面讲美国加州理工学院的情况,使我想起我在美国加州理工学院所受的教育。
我是在上个世纪30年代去美国的,开始在麻省理工学院学习。麻省理工学院在当时也算是鼎鼎大名了,但我觉得没什么,一年就把硕士学位拿下了,成绩还拔尖。其实这一年并没学到什么创新的东西,很一般化。后来我转到加州理工学院,一下子就感觉到它和麻省理工学院很不一样,创新的学风弥漫在整个校园,可以说,整个学校的一个精神就是创新。在这里,你必须想别人没有想到的东西,说别人没有说过的话。拔尖的人才很多,我得和他们竞赛,才能跑在前沿。这里的创新还不能是一般的,迈小步可不行,你很快就会被别人超过。你所想的、做的,要比别人高出一大截才行。那里的学术气氛非常浓厚,学术讨论会十分活跃,互相启发,互相促进。我们现在倒好,一些技术和学术讨论会还互相保密,互相封锁,这不是发展科学的学风。你真的有本事,就不怕别人赶上来。我记得在一次学术讨论会上,我的老师冯·卡门讲了一个非常好的学术思想,美国人叫“goodidea”,这在科学工作中是很重要的。有没有创新,首先就取决于你有没有一个“goodidea”。所以马上就有人说:“卡门教授,你把这么好的思想都讲出来了,就不怕别人超过你?”卡门说:“我不怕,等他赶上我这个想法,我又跑到前面老远去了。”所以我到加州理工学院,一下子脑子就开了窍,以前从来没想到的事,这里全讲到了,讲的内容都是科学发展最前沿的东西,让我大开眼界。
我本来是航空系的研究生,我的老师鼓励我学习各种有用的知识。我到物理系去听课,讲的是物理学的前沿,原子、原子核理论、核技术,连原子弹都提到了。生物系有摩根这个大权威,讲遗传学,我们中国的遗传学家谈家桢就是摩根的学生。化学系的课我也去听,化学系主任L·鲍林讲结构化学,也是化学的前沿。他在结构化学上的工作还获得诺贝尔化学奖。以前我们科学院的院长卢嘉锡就在加州理工学院化学系进修过。L·鲍林对于我这个航空系的研究生去听他的课、参加化学系的学术讨论会,一点也不排斥。他比我大十几岁,我们后来成为好朋友。他晚年主张服用大剂量维生素的思想遭到生物医学界的普遍反对,但他仍坚持自己的观点,甚至和整个医学界辩论不止。他自己就每天服用大剂量维生素,活到93岁。加州理工学院就有许多这样的大师、这样的怪人,决不随大流,敢于想别人不敢想的,做别人不敢做的。大家都说好的东西,在他看来很一般,没什么。没有这种精神,怎么会有创新!
加州理工学院给这些学者、教授们,也给年轻的学生、研究生们提供了充分的学术权力和民主氛围。不同的学派、不同的学术观点都可以充分发表。学生们也可以充分发表自己的不同学术见解,可以向权威们挑战。过去我曾讲过我在加州理工学院当研究生时和一些权威辩论的情况,其实这在加州理工学院是很平常的事。那时,我们这些搞应用力学的,就是用数学计算来解决工程上的复杂问题。所以人家又管我们叫应用数学家。可是数学系的那些搞纯粹数学的人偏偏瞧不起我们这些搞工程数学的。两个学派常常在一起辩论。有一次,数学系的权威在学校布告栏里贴出了一个海报,说他在什么时间什么地点讲理论数学,欢迎大家去听讲。我的老师冯·卡门一看,也马上贴出一个海报,说在同一时间他在什么地方讲工程数学,也欢迎大家去听。结果两个讲座都大受欢迎。这就是加州理工学院的学术风气,民主而又活跃。我们这些年轻人在这里学习真是大受教益,大开眼界。今天我们有哪一所大学能做到这样?大家见面都是客客气气,学术讨论活跃不起来。这怎么能够培养创新人才?更不用说大师级人才了。
有趣的是,加州理工学院还鼓励那些理工科学生提高艺术素养。我们火箭小组的头头马林纳就是一边研究火箭,一边学习绘画,他后来还成为西方一位抽象派画家。我的老师冯·卡门听说我懂得绘画、音乐、摄影这些方面的学问,还被美国艺术和科学学会吸收为会员,他很高兴,说你有这些才华很重要,这方面你比我强。因为他小时候没有我那样的良好条件。我父亲钱均夫很懂得现代教育,他一方面让我学理工,走技术强国的路;另一方面又送我去学音乐、绘画这些艺术课。我从小不仅对科学感兴趣,也对艺术有兴趣,读过许多艺术理论方面的书,像普列汉诺夫的《艺术论》,我在上海交通大学念书时就读过了。这些艺术上的修养不仅加深了我对艺术作品中那些诗情画意和人生哲理的深刻理解,也学会了艺术上大跨度的宏观形象思维。我认为,这些东西对启迪一个人在科学上的创新是很重要的。科学上的创新光靠严密的逻辑思维不行,创新的思想往往开始于形象思维,从大跨度的联想中得到启迪,然后再用严密的逻辑加以验证。
像加州理工学院这样的学校,光是为中国就培养出许多著名科学家。钱伟长、谈家桢、郭永怀等等,都是加州理工学院出来的。郭永怀是很了不起的,但他去世得早,很多人不了解他。在加州理工学院,他也是冯·卡门的学生,很优秀。我们在一个办公室工作,常常在一起讨论问题。我发现他聪明极了。你若跟他谈些一般性的问题,他不满意,总要追问一些深刻的概念。他毕业以后到康奈尔大学当教授。因为卡门的另一位高才生西尔斯在康奈尔大学组建航空研究院,他了解郭永怀,邀请他去那里工作。郭永怀回国后开始在力学所担任副所长,我们一起开创中国的力学事业。后来搞核武器的钱三强找我,说搞原子弹、氢弹需要一位搞力学的人参加,解决复杂的力学计算问题,开始他想请我去。我说现在中央已委托我搞导弹,事情很多,我没精力参加核武器的事了。但我可以推荐一个人,郭永怀。郭永怀后来担任九院副院长,专门负责爆炸力学等方面的计算问题。在我国原子弹、氢弹问题上他是立了大功的,可惜在一次出差中因飞机失事牺牲了。那个时候,就是这样一批有创新精神的人把中国的原子弹、氢弹、导弹、卫星搞起来的。
今天我们办学,一定要有加州理工学院的那种科技创新精神,培养会动脑筋、具有非凡创造能力的人才。我回国这么多年,感到中国还没有一所这样的学校,都是些一般的,别人说过的才说,没说过的就不敢说,这样是培养不出顶尖帅才的。我们国家应该解决这个问题。你是不是真正的创新,就看是不是敢于研究别人没有研究过的科学前沿问题,而不是别人已经说过的东西我们知道,没有说过的东西,我们就不知道。所谓优秀学生就是要有创新。没有创新,死记硬背,考试成绩再好也不是优秀学生。
我在加州理工学院接受的就是这样的教育,这是我感受最深的。回国以后,我觉得国家对我很重视,但是社会主义建设需要更多的钱学森,国家才会有大的发展。
我说了这么多,就是想告诉大家,我们要向加州理工学院学习,学习它的科学创新精神。我们中国学生到加州理工学院学习的,回国以后都发挥了很好的作用。所有在那学习过的人都受它创新精神的熏陶,知道不创新不行。我们不能人云亦云,这不是科学精神,科学精神最重要的就是创新。
我今年已90多岁了,想到中国长远发展的事情,忧虑的就是这一点。
(涂元季 顾吉环 李 明整理)
-------------------start of 1
板书:
了解公司
去公司网站对其了解
去搜索引擎中了解对公司的评价
网上搜公司的人员,和他们聊天来了解
去IT公司速查手册查对公司的评价(如深圳软媒)
珠三角求职注意事项:深圳、广州、东莞。。。
简历
把自己的简历以纯文本的形式贴在邮件里,同时以Word文档(低版本)加在附件中。附件千万不能有病毒。
写简历的基本原则:简历是向用人单位推荐你、帮助用人单位了解你的一个工具!它不是公文流程化的表格,不是履历
表。不要什么都写。
要根据应聘职位的职位描述(Job Description)来个性化自己的简历,不要所有的职位都用一个简历,这是大忌,貌似
省事,实则大大降低了成功率。
简历中的项目经历尽量不要写:图书管理系统、网上商店之类的,看的头都疼了,第一反应是反感。不能跟别人雷同!
!!
简历注意事项
控制在两页之内
什么刀枪跟棍棒,都耍得有模有样,什么兵器最喜欢,双截棍柔中带刚。不要C、Java、C#、php、linux都懂!不要就是
一句:精通java就ok了,你用java写过什么?做过什么?有什么认识?
尽量压缩政治面貌、小学中学、大学获奖证书、小学三好学生等用人单位不关心的内容。
项目经历不要写太多,每个项目控制在5行左右,要重点突出项目人数、耗时、功能、系统架构等信息。突出:我在项目
做了什么!我不是打杂的,我不是端茶的。
如果和同学一起去应聘,不要两个人的简历一样
简历注意事项
可以多突出自己的特色,跟别人区隔开。简历上写的一定要经得起拷问(端茶倒水的),没把握的不要乱写,反感。面
试官一般都会按照就简历上写的进行提问:“看到你简历上写的。。。我想问你下你对。。。的看法”。
简历不用弄的太花哨,搞太高档的纸。面试官看的是内容,而不是纸!
人才库=垃圾桶
---------------------end of 1----------------------------------
-------------start of 2--------------
板书:
先介绍自己
禁忌的回答:我都写到简历里边了;我出生在陕北一个小山村,我有三个弟弟,我妈身体不好。。。;
无关的事情不要超过十几秒,因为简单介绍自己的时间最多2分钟。很快的将重点话题转到与工作有关的技能和经验上来
。
首先要把简历中写的总结一下(概述,不要全盘背出来),然后再以口语化的方式谈谈与这个工作、软件开发相关的话
题。
多主动说,不要总等着考官提问,那样会被动,但是也不能抢话说。聊天的效果!!和考官处于平等的地位。
当话说完了的时候要及时说“这就是我的看法。”,千万不能与主考官面面相觑。
说话不用太快,说话要稍微慢于思维,否则说话就不连贯了。
常见面试问题:
1、你的优点是什么,你的缺点是什么?
禁忌回答:我的优点是没有缺点(找抽!)
优点要讲与工作相关的,不要说“我篮球打得好”,不要吹的太厉害;谈优点的时候不能枚举形容词,要举实例。
缺点要是那种可以容忍的或者大家都有的小缺点,比如“当我注意力集中在工作上的时候,容易忽略别人说的话”(某
种程度来讲是优点);“当事情比较多的时候我会忘记一些事项,造成工作疏忽”。谈缺点的时候还要提到自己是怎么
改的“我随身带着笔记本,记下要做的事情,这样容易忘记事情的毛病已经改了很多了”
2、你还有什么问题吗?
不能答“没有了”,这说明你对这个工作根本没放在心上,也不能问太敏感的问题。要让别人感觉你是来做事业的,而
不是来找糊口的饭碗。不要问太多的待遇、补助、伙食、几个老板、公司销售额之类的问题,多关心公司的业务、产品
、发展以及个人进入公司以后的问题等等。问剩下的半年时间我该学些什么?
你为什么要来我们公司?不要回答“你们公司给的钱多”、“我看到了你们的招聘启示”。参考回答“我以前就对**有
了解,**是。。。,所以我一直向往在**工作,也希望能在这个行业中与**共同成长。”
3、你能说一下你的职业发展规划吗?
不要说“2年内成为技术骨干,5年内称为项目经理,8年内自己创业。。。”之类的。参考解答“我有非常强的工作能力
和积极性,而且我相信我一定能够为公司创造越来越多的价值,从而个人的能力也得到提升,由于我工作经验还是有限
的,而且对IT行业的发展也有待于逐步加深了解,所以我希望在初期能够服从公司的工作安排,完成公司交给公司的任
务,相信随着我经验的增长,我会对自己的职业发展规划更加明确,今后无论是做技术专家、业务专家还是管理人员,
我都能够找到适合自己发展的道路,与公司共同成长!”愿意在你这干一辈子。
4、你希望的月薪是多少?
这个问题很难回答,而且不同的面试官也有不同的喜好。不过总的原则是首先不要就月薪问题进行无意义的争论“你们
怎么能才给三千呀,我同学都四千,三千还不够在北京生存的呢,我还有八十岁的老母。。。”,而是说自己的优势、
对公司的价值。“我期望的月薪是四千,不过我知道每个公司都有自己的薪酬体系结构,我也充分尊重公司在考虑我个
人能力的基础上按照公司的规定给予我的报酬”。着眼发展!
1、简单介绍自己时:姓名专业,然后是专业相关的。谈到工作上和以口语话的方式聊一聊。
要主动的和考官聊,要主动的出击不能应对呀。可以互动,这样效果更好,也可以启发自己。聊天的效果最好。不能抢
话,一定要让人把话说完。陈述看法。要有个总结,这就是我的看法。说完了就说完了。一些和人交流的基本功。
说话不要快。快了容易出错。
你的优点是什么?缺点是什么?讲与工作相关的,不是谈别的。这个才是关键点。
你还有什么问题吗?这个工作要放在心上,对企业了解吗?对职业了解吗?不能问敏感的问题。要感觉是做事业的。
在这半年时间要学习些什么?******
你为什么来我们公司???以前就公司有所了解,
对自己的职业规划是不是明确。是不是和公司共同发展。??为公司创造价值,对IT行业的还有待了解,
与公司共同成长。
创业的人不安稳。
板书:
纸上写代码很土吗?
面试时的Code题通常有难度,有些题目就是想看你在遇到困难问题时候的应对能力。不要以答不对而懊恼
一时找不到解决方案的话,也不能看着天花板面无表情的发呆,而是要嘴里描述你的想法和思路。编写代码过程中随时对写的代码进行解释。“我要先创建一个HashMap,然后。。。”。
因为可能是在纸上写代码,所以不要拘泥于细节。
遇到一个小障碍,可以求助主考官,“这个只要使用String类的一个分割字符串的方法就可以,不过我忘了这个方法的名称。。。”。遇到难题就问。
如果一个题只会用最笨的方法解,那么也要写,并且解释“这种方式虽然可以实现,不过效率非常低,我虽然想通过发现其中的规律来优化,不过最终没有发现,如果我在工作中碰到类似的问题,我会寻求他人帮助”
怎么样及时无法完美的写的情况下也能的高分。比如我在中软笔试的时候考xml操作,那时候我只用delphi操作过xml,所以我没有按照题目要求用java写,而是按delphi写的,最后注明。。。企业面试、笔试没有严格的评分标准,不同于高考等考试。
代码要考虑边界条件,这是主考官非常注意的。(得高分的技巧)输入参数的合法性等等。
如果是在纸上Coding的话,代码书写一定要清晰;无论是机试还是“纸试”,都要适当的写注释;
机试由于是在不熟悉的机器中开发,所以不要慌,必要时寻求帮忙
着眼发展,要有平和的就业心态。
在一个公司要沉淀一段时间,不要频繁跳槽
工作中80%的时间是在干无聊的事情,因为你的工作不是创新大赛,老板是要你为他产生效益。
把看似无聊的80%的工作做的Perfect,把20%的时间用来创造!你就是未来的牛人!
注意学习不能停止!!!
xml特殊字符
2008-07-03 14:31
转义字符
不合法的XML字符必须被替换为相应的实体。
如果在XML文档中使用类似"<" 的字符, 那么解析器将会出现错误,因为解析器会认为这是一个新元素的开始。所以不应该象下面那样书写代码:
<message>if salary < 1000 then</message>
为了避免出现这种情况,必须将字符"<" 转换成实体,象下面这样:
<message>if salary < 1000 then</message>
下面是五个在XML文档中预定义好的实体:
< < 小于号
> > 大于号
& & 和
' ' 单引号
" " 双引号
实体必须以符号"&"开头,以符号";"结尾。
注意: 只有"<" 字符和"&"字符对于XML来说是严格禁止使用的。剩下的都是合法的,为了减少出错,使用实体是一个好习惯。
CDATA部件
在CDATA内部的所有内容都会被解析器忽略。
如果文本包含了很多的"<"字符和"&"字符——就象程序代码一样,那么最好把他们都放到CDATA部件中。
一个 CDATA 部件以"<![CDATA[" 标记开始,以"]]>"标记结束:
<script>
<![CDATA[
function matchwo(a,b)
{
if (a < b && a < 0) then
{
return 1
}
else
{
return 0
}
}
]]>
</script>
在前面的例子中,所有在CDATA部件之间的文本都会被解析器忽略。
CDATA注意事项:
CDATA部件之间不能再包含CDATA部件(不能嵌套)。如果CDATA部件包含了字符"]]>" 或者"<![CDATA[" ,将很有可能出错哦。
同样要注意在字符串"]]>"之间没有空格或者换行符。
|
MySql数据引擎简介与选择方法
2009-04-18 16:17
一、数据引擎简介
在MySQL 5.1中,MySQL AB引入了新的插件式存储引擎体系结构,允许将存储引擎加载到正在运新的MySQL服务器中。
使用MySQL插件式存储引擎体系结构,允许数据库专 业人员为特定的应用需求选择专门的存储引擎,完全不需要管理任何特殊的应用编码要求。采用MySQL服务器体系结构,由于在存储级别上提供了一致和简单的 应用模型和API,应用程序编程人员和DBA可不再考虑所有的底层实施细节。因此,尽管不同的存储引擎具有不同的能力,应用程序是与之分离的。
MySQL支持数个存储引擎作为对不同表的类型的处理器。MySQL存储引擎包括处理事务安全表的引擎和处理非事务安全表的引擎:
· MyISAM管理非事务表。它提供高速存储和检索,以及全文搜索能力。MyISAM在所有MySQL配置里被支持,它是默认的存储引擎,除非你配置MySQL默认使用另外一个引擎。
· MEMORY存储引擎提供“内存中”表。MERGE存储引擎允许集合将被处理同样的MyISAM表作为一个单独的表。就像MyISAM一样,MEMORY和MERGE存储引擎处理非事务表,这两个引擎也都被默认包含在MySQL中。
注释:MEMORY存储引擎正式地被确定为HEAP引擎。
· InnoDB和BDB存储引擎提供事务安全表。BDB被包含在为支持它的操作系统发布的MySQL-Max二进制分发版里。InnoDB也默认被包括在所有MySQL 5.1二进制分发版里,你可以按照喜好通过配置MySQL来允许或禁止任一引擎。
· EXAMPLE存储引擎是一个“存根”引擎,它不做什么。你可以用这个引擎创建表,但没有数据被存储于其中或从其中检索。这个引擎的目的是服务,在MySQL源代码中的一个例子,它演示说明如何开始编写新存储引擎。同样,它的主要兴趣是对开发者。
· NDB Cluster是被MySQL Cluster用来实现分割到多台计算机上的表的存储引擎。它在MySQL-Max 5.1二进制分发版里提供。这个存储引擎当前只被Linux, Solaris, 和Mac OS X 支持。在未来的MySQL分发版中,我们想要添加其它平台对这个引擎的支持,包括Windows。
· ARCHIVE存储引擎被用来无索引地,非常小地覆盖存储的大量数据。
· CSV存储引擎把数据以逗号分隔的格式存储在文本文件中。
· BLACKHOLE存储引擎接受但不存储数据,并且检索总是返回一个空集。
· FEDERATED存储引擎把数据存在远程数据库中。在MySQL 5.1中,它只和MySQL一起工作,使用MySQL C Client API。在未来的分发版中,我们想要让它使用其它驱动器或客户端连接方法连接到另外的数据源。
插件式存储引擎体系结构提供了标准的管理和支持服务集合,它们对所有的基本存储引擎来说是共同的。存储引擎本身是数据库服务器的组件,负责对在物理服务器层面上维护的基本数据进行实际操作。
这是一种高效的模块化体系结构,它为那些希望专注于特定应用需求的人员提供了巨大的便利和益处,这类特殊应用需求包括数据仓储、事务处理、高可用性情形等,同时还能利用独立于任何存储引擎的一组接口和服务。
应用程序编程人员和DBA通过位于存储引擎之上的连接器API和服务层来处理MySQL数据库。如果 应用程序的变化需要改变底层存储引擎,或需要增加1个或多个额外的存储引擎以支持新的需求,不需要进行大的编码或进程更改就能实现这类要求。MySQL服 务器体系结构提供了一致和易于使用的API,这类API适用于多种存储引擎,通过该方式,该结构将应用程序与存储引擎的底层复杂性隔离开来。
在下图中,以图形方式介绍了MySQL插件式存储引擎体系结构:
二、选择存储引擎
与MySQL一起提供的各种存储引擎在设计时考虑了不同的使用情况。为了更有效地使用插件式存储体系结构,最好了解各种存储引擎的优点和缺点。
在下面的表格中,概要介绍了与MySQL一起提供的存储引擎:
下述存储引擎是最常用的:
· MyISAM:默认的MySQL插件式存储引擎,它是在Web、数据仓储和其他应用环境下最常使用的存储引擎之一。注意,通过更改STORAGE_ENGINE配置变量,能够方便地更改MySQL服务器的默认存储引擎。
· InnoDB:用于事务处理应用程序,具有众多特性,包括ACID事务支持。
· BDB:可替代InnoDB的事务引擎,支持COMMIT、ROLLBACK和其他事务特性。
· Memory:将所有数据保存在RAM中,在需要快速查找引用和其他类似数据的环境下,可提供极快的访问。
· Merge:允许MySQL DBA或开发人员将一系列等同的MyISAM表以逻辑方式组合在一起,并作为1个对象引用它们。对于诸如数据仓储等VLDB环境十分适合。
· Archive:为大量很少引用的历史、归档、或安全审计信息的存储和检索提供了完美的解决方案。
· Federated:能够将多个分离的MySQL服务器链接起来,从多个物理服务器创建一个逻辑数据库。十分适合于分布式环境或数据集市环境。
· Cluster/NDB:MySQL的簇式数据库引擎,尤其适合于具有高性能查找要求的应用程序,这类查找需求还要求具有最高的正常工作时间和可用性。
· Other:其他存储引擎包括CSV(引用由逗号隔开的用作数据库表的文件),Blackhole(用于临时禁止对数据库的应用程序输入),以及Example引擎(可为快速创建定制的插件式存储引擎提供帮助)。
请记住,对于整个服务器或方案,你并不一定要使用相同的存储引擎,你可以为方案中的每个表使用不同的存储引擎,这点很重要。
三、将存储引擎指定给表
可以在创建新表时指定存储引擎,或通过使用ALTER TABLE语句指定存储引擎。
要想在创建表时指定存储引擎,可使用ENGINE参数:
CREATE TABLE engineTest(
id INT
) ENGINE = MyISAM;
也可以使用TYPE选项到CREATE TABLE语句来告诉MySQL你要创建什么类型的表。
CREATE TABLE engineTest(
id INT
) TYPE = MyISAM;
虽然TYPE仍然在MySQL 5.1中被支持,现在ENGINE是首选的术语。
如果你省略掉ENGINE或TYPE选项,默认的存储引擎被使用。一般的默认是MyISAM,但 你可以用--default-storage-engine或--default-table-type服务器启动选项来改变它,或者通过设置 storage_engine或table_type系统变量来改变。
要想更改已有表的存储引擎,可使用ALTER TABLE语句:
ALTER TABLEengineTestENGINE =ARCHIVE;
ALTER TABLE t ENGINE = MYISAM;
ALTER TABLE t TYPE = BDB;
如果你试着使用一个未被编译进MySQL的存储引擎,或者试着用一个被编译进MySQL但没有被 激活的存储引擎,MySQL取而代之地创建一个MyISAM类型的表。当你在支持不同存储引擎的MySQL服务器之间拷贝表的时候,上述的行为是很方便 的。(例如,在一个复制建立中,可能你的主服务器为增加安全而支持事务存储引擎,但从服务器为更快的速度而仅使用非事务存储引擎。)
在不可用的类型被指定时,自动用MyISAM表来替代,这会对MySQL的新用户造成混淆。无论何时一个表被自动改变之时,产生一个警告。
MySQL总是创建一个.frm文件来保持表和列的定义。表的索引和数据可能被存储在一个或多个文件里,这取决于表的类型。服务器在存储引擎级别之上创建.frm文件。单独的存储引擎创建任何需要用来管理表的额外文件。
一个数据库可以包含不同类型的表。
四、存储引擎和事务
下述存储引擎支持事务:
· InnoDB:通过MVCC支持事务,允许COMMIT、ROLLBACK和保存点。
· NDB:通过MVCC支持事务,允许COMMIT和ROLLBACK。
· BDB:支持事务,允许COMMIT和ROLLBACK。
事务安全表(TST) 比起非事务安全表 (NTST)有几大优势:
· 更安全。即使MySQL崩溃或遇到硬件问题,要么自动恢复,要么从备份加事务日志恢复,你可以取回数据。
· 你可以合并许多语句,并用COMMIT语句同时接受它们全部(如果autocommit被禁止掉)。
· 你可以执行ROLLBACK来忽略你的改变(如果autocommit被禁止掉)。
· 如果更新失败,你的所有改变都变回原来。(用非事务安全表,所有发生的改变都是永久的)。
· 事务安全存储引擎可以给那些当前用读得到许多更新的表提供更好的部署。
非事务安全表自身有几个优点,因为没有事务开支,所有优点都能出现:
· 更快
· 需要更少的磁盘空间
· 执行更新需要更少的内存
你可以在同一个语句中合并事务安全和非事务安全表来获得两者最好的情况。尽管如此,在autocommit被禁止掉的事务里,变换到非事务安全表依旧即时提交,并且不会被回滚。
虽然MySQL支持数个事务安全存储引擎,为获得最好结果,你不应该在一个事务那混合不同表类型。如果你混合表类型会发生问题,
五、插入搜索引擎
能够使用存储引擎之前,必须使用INSTALL PLUGIN语句将存储引擎plugin(插件)装载到mysql。例如,要想加载example引擎,首先应加载ha_example.so模块:
INSTALL PLUGINha_exampleSONAME 'ha_example.so';
文件.so必须位于MySQL服务器库目录下(典型情况下是installdir/lib)。
六、拔出存储引擎
要想拔出存储引擎,可使用UNINSTALL PLUGIN语句:
UNINSTALL PLUGINha_example;
如果拔出了正被已有表使用的存储引擎,这些表将成为不可访问的。拔出存储引擎之前,请确保没有任何表使用该存储引擎。
为了安装插件式存储引擎,plugin文件必须位于恰当的MySQL库目录下,而且发出INSTALL PLUGIN语句的用户必须具有SUPER权限。
创建table时可以通过engine关键字指定使用的存储引擎,如果省略则使用系统默认的存储引擎:
CREATE TABLE t (i INT) ENGINE = MYISAM;
查看系统中支持的存储引擎类型:
mysql> show engines;
标准安装程序中只提供部分引擎的支持,如果需要使用其他的存储引擎,需要使用源代码加不同的参数重新编译。其中DEFAULT表明系统的默认存储引擎,可以通过修改配置参数来变更:
default-storage-engine=MyISAM
查看某个存储引擎的具体信息
mysql> show engine InnoDB status\G;
|
如果我们把二叉树看成一个图,父子节点之间的连线看成是双向的,我们姑且定义“距
离”为两个节点之间边的个数。
写一个程序求一棵二叉树中相距最远的两个节点之间的距离。
如图 3-11 所示,粗箭头的边表示最长距离:
图 3-11
树中相距最远的两个节点 A,B
写书评,赢取《编程之美——微软技术面试心得》 www.ieee.org.cn/BCZM.asp
分析与解法
我们先画几个不同形状的二叉树,(如图 3-12 所示),看看能否得到一些启示。
图 3-12
几个例子
从例子中可以看出,相距最远的两个节点,一定是两个叶子节点,或者是一个叶子节点
到它的根节点。(为什么?)
【解法一】
根据相距最远的两个节点一定是叶子节点这个规律,我们可以进一步讨论。
对于任意一个节点,以该节点为根,假设这个根有 K 个孩子节点,那么相距最远的两
个节点 U 和 V 之间的路径与这个根节点的关系有两种情况:
1. 若路径经过根Root,则U和V是属于不同子树的,且它们都是该子树中到根节点最远
的节点,否则跟它们的距离最远相矛盾。这种情况如图3-13所示:
图 3-13
相距最远的节点在左右最长的子树中
写书评,赢取《编程之美——微软技术面试心得》 www.ieee.org.cn/BCZM.asp
2. 如果路径不经过Root,那么它们一定属于根的K个子树之一。并且它们也是该子树中
相距最远的两个顶点。如图3-14中的节点A:
图 3-14
相距最远的节点在某个子树下
因此,问题就可以转化为在子树上的解,从而能够利用动态规划来解决。
设第 K 棵子树中相距最远的两个节点:Uk 和 Vk,其距离定义为 d(Uk, Vk),那么节点
Uk 或 Vk 即为子树 K 到根节点 Rk 距离最长的节点。不失一般性,我们设 Uk 为子树 K 中到根
节点 Rk 距离最长的节点,其到根节点的距离定义为 d(Uk, R)。取 d(Ui, R)(1≤i≤k)中
最大的两个值 max1 和 max2,那么经过根节点 R 的最长路径为 max1+max2+2,所以树 R 中
相距最远的两个点的距离为:max{d(U1, V1), …, d(Uk, Vk),max1+max2+2}。
采用深度优先搜索如图 3-15,只需要遍历所有的节点一次,时间复杂度为 O(|E|)= O
(|V|-1),其中 V 为点的集合,E 为边的集合。
图 3-15
深度遍历示意图
示例代码如下,我们使用二叉树来实现该算法。
代码清单 3-11
// 数据结构定义
写书评,赢取《编程之美——微软技术面试心得》 www.ieee.org.cn/BCZM.asp
struct NODE
{
NODE* pLeft;
NODE* pRight;
int nMaxLeft;
int nMaxRight;
char chValue;
};
int nMaxLen = 0;
// 寻找树中最长的两段距离
void FindMaxLen(NODE* pRoot)
{
// 遍历到叶子节点,返回
if(pRoot == NULL)
{
return;
}
// 如果左子树为空,那么该节点的左边最长距离为0
if(pRoot -> pLeft == NULL)
{
pRoot -> nMaxLeft = 0;
}
// 如果右子树为空,那么该节点的右边最长距离为0
if(pRoot -> pRight == NULL)
{
pRoot -> nMaxRight = 0;
}
// 如果左子树不为空,递归寻找左子树最长距离
if(pRoot -> pLeft != NULL)
{
FindMaxLen(pRoot -> pLeft);
}
// 如果右子树不为空,递归寻找右子树最长距离
if(pRoot -> pRight != NULL)
{
FindMaxLen(pRoot -> pRight);
}
// 计算左子树最长节点距离
if(pRoot -> pLeft != NULL)
{
int nTempMax = 0;
if(pRoot -> pLeft -> nMaxLeft > pRoot -> pLeft -> nMaxRight)
{
nTempMax = pRoot -> pLeft -> nMaxLeft;
}
else
{
nTempMax = pRoot -> pLeft -> nMaxRight;
}
pRoot -> nMaxLeft = nTempMax + 1;
}
// 计算右子树最长节点距离
if(pRoot -> pRight != NULL)
//
//
//
//
//
左孩子
右孩子
左子树中的最长距离
右子树中的最长距离
该节点的值
写书评,赢取《编程之美——微软技术面试心得》 www.ieee.org.cn/BCZM.asp
{
int nTempMax = 0;
if(pRoot -> pRight -> nMaxLeft > pRoot -> pRight -> nMaxRight)
{
nTempMax = pRoot -> pRight -> nMaxLeft;
}
else
{
nTempMax = pRoot -> pRight -> nMaxRight;
}
pRoot -> nMaxRight = nTempMax + 1;
}
// 更新最长距离
if(pRoot -> nMaxLeft + pRoot -> nMaxRight > nMaxLen)
{
nMaxLen = pRoot -> nMaxLeft + pRoot -> nMaxRight;
}
}
扩展问题
在代码中,我们使用了递归的办法来完成问题的求解。那么是否有非递归的算法来解决
这个问题呢?
总结
对于递归问题的分析,笔者有一些小小的体会:
1. 先弄清楚递归的顺序。在递归的实现中,往往需要假设后续的调用已经完成,在此
基础之上,才实现递归的逻辑。在该题中,我们就是假设已经把后面的长度计算出
来了,然后继续考虑后面的逻辑;
2. 分析清楚递归体的逻辑,然后写出来。比如在上面的问题中,递归体的逻辑就是如
何计算两边最长的距离;
3. 考虑清楚递归退出的边界条件。也就说,哪些地方应该写return。
注意到以上 3 点,在面对递归问题的时候,我们将总是有章可循。
-----------------------------------------------------------------------------------
《编程之美》读书笔记:第3.8节“求二叉树中节点的最大距离”扩展问题 收藏
感谢azuryy为大家分享《编程之美》第3.8节扩展问题的答案:用非递归的算法求一颗二叉树中相距最远的两个节点之间的距离。(原博客地址:http://hi.baidu.com/azuryy/blog/item/30ad10ea192424d5d439c96d.html)
#include <stack>
#include <algorithm>
using namespace std;
struct Node
{
bool _visited;
Node* left;
Node* right;
int maxLeft;
int maxRight;
Node()
{
_visited = false;
maxLeft = 0;
maxRight = 0;
left = NULL;
right = NULL;
}
};
int maxLen = 0;
stack<Node*> nodeStack;
void findMaxLen( Node* root )
{
Node* node;
if ( root == NULL )
{
return ;
}
nodeStack.push( root );
while( !nodeStack.empty())
{
node = nodeStack.top();
if ( node->left == NULL && node->right == NULL )
{
nodeStack.pop();
node->_visited = true;
continue;
}
if ( node->left )
{
if ( !node->left->_visited )
{
nodeStack.push( node->left ) ;
}
else
{
node->maxLeft = max( node->left->maxLeft,node->left->maxRight ) + 1;
}
}
if ( ( !node->left || node->left->_visited ) && node->right )
{
if ( !node->right->_visited )
{
nodeStack.push( node->right ) ;
}
else
{
node->maxRight = max( node->right->maxLeft,node->right->maxRight ) + 1;
}
}
if (( !node->left || node->left->_visited ) && ( !node->right || node->right->_visited ))
{
maxLen = max( maxLen, node->maxLeft + node->maxRight );
node->_visited = true;
nodeStack.pop();
}
}
}
Immediate test case 1:
int main()
{
Node *tmp ;
Node* root = new Node();
tmp = new Node();
root->left = tmp ;
tmp = new Node();
root->right = tmp;
tmp = new Node();
root->right->right = tmp;
tmp = new Node();
root->right->right->right = tmp;
tmp = new Node();
root->right->right->right->left = tmp;
findMaxLen( root );
cout << maxLen << endl;
return 0;
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/bvbook/archive/2008/07/25/2710209.aspx
JDBC优化策略总结
相比Hibernate、iBatis、DBUtils等,理论上JDBC的性能都超过它们。JDBC提供更底层更精细的数据访问策略,这是Hibernate等框架所不具备的。
在一些高性能的数据操作中,越高级的框架越不适合使用。这里是我在开发中对JDBC使用过程中一些优化经验总结。
1、选择纯Java的JDBC驱动。
2、使用连接池--使用一个“池”来管理JDBC连接,并精心调试池配置的参数,目前可用的数据库连接池很多很多。
如何配置合适的参数呢,需要的是测试,而不是感觉。
3、重用Connection--最大限度使用每个数据库连接,得到了就不要轻易“丢弃”。
有时候在一个过程中,会多次操作数据库,而仅仅需要一个连接就够了,没必用一次就获取一个连接,用完后关闭或者入池。这样会增加“池”管理的成本,千万别以为你用了“池”就可以随便申请和归还连接,都是有代价的。如果是一个庞大循环块中操作数据库,更应该注意此问题!
4、重用Statement--对于一些预定义SQL,设置为静态常量,并尽可能重用预定义SQL产生的PreparedStatement对象。对于多次使用一种模式的SQL,使用预定义SQL可以获取更好的性能。
5、使用批处理SQL。
6、优化结果集ResultSet--查询时候,返回的结果集有不同的类型,优先选择只读结果集、不可滚动的属性。
这里是很容易出现问题的地方:
java.sql.ResultSet
static int CLOSE_CURSORS_AT_COMMIT
该常量指示调用 Connection.commit 方法时应该关闭 ResultSet 对象。
static int CONCUR_READ_ONLY
该常量指示不可以更新的 ResultSet 对象的并发模式。
static int CONCUR_UPDATABLE
该常量指示可以更新的 ResultSet 对象的并发模式。
static int FETCH_FORWARD
该常量指示将按正向(即从第一个到最后一个)处理结果集中的行。
static int FETCH_REVERSE
该常量指示将按反向(即从最后一个到第一个)处理结果集中的行处理。
static int FETCH_UNKNOWN
该常量指示结果集中的行的处理顺序未知。
static int HOLD_CURSORS_OVER_COMMIT
该常量指示调用 Connection.commit 方法时不应关闭 ResultSet 对象。
static int TYPE_FORWARD_ONLY
该常量指示指针只能向前移动的 ResultSet 对象的类型。
static int TYPE_SCROLL_INSENSITIVE
该常量指示可滚动但通常不受其他的更改影响的 ResultSet 对象的类型。
static int TYPE_SCROLL_SENSITIVE
该常量指示可滚动并且通常受其他的更改影响的 ResultSet 对象的类型。
说明下:
结果集分两种类型:只读和可更改,只读的话,更省内存,查询的结果集不能更改。如果结果集在查询后,更改了值又要保存,则使用可更改结果集。
结果集的游标也有两种类型:如果没必要让游标自由滚动,则选择单方向移动的游标类型。
对于是否并发操作:如果不需要考虑线程安全,则选择忽略并发的结果集类型,否则选择并发安全的类型。
另外,还要控制结果的大小,几乎所有的数据库都有查询记录条数控制的策略,可以海量数据进行分批处理,一次一批,这样不至于把系统搞死。
7、事物优化--如果数据库不支持事物,就不要写回滚代码,如果不考虑事物,就不要做事务的控制。
8、安全优化--管理好你的Connection对象,在异常时候能“入池”或者关闭。因此应该将Connection释放的代码写在异常处理的finally块中。
9、异常处理优化--不要轻易吞噬SQLException,对于DAO、Service层次的数据访问,一般在DAO中跑出异常,在Service中处理异常。但DAO中也可以处理异常,并做转义抛出,不要随便抛出RuntimeExeption,因为这是JVM抛出的,不需要你可以去抛出,因为RuntimeException往往会导致系统挂起。
10、代码高层优化--在以上的基础上,优化封装你的数据访问方式,尽可能让代码简洁好维护,如果你还觉得性能不行,那就该从整个系统角度考虑优化了,比如加上缓存服务器,集群、负载均衡、优化数据库服务器等等,以获取更好的系能。
本文出自 “熔 岩” 博客,请务必保留此出处http://lavasoft.blog.51cto.com/62575/225828
java代码优化编程(2)
17、不用new关键词创建类的实例
用new关键词创建类的实例时,构造函数链中的所有构造函数都会被自动调用。但如果一个对象实现了Cloneable接口,我们可以调用它的clone()方法。clone()方法不会调用任何类构造函数。
在使用设计模式(Design Pattern)的场合,如果用Factory模式创建对象,则改用clone()方法创建新的对象实例非常简单。例如,下面是Factory模式的一个典型实现:
public static Credit getNewCredit() {
return new Credit();
}
改进后的代码使用clone()方法,如下所示:
private static Credit BaseCredit = new Credit();
public static Credit getNewCredit() {
return (Credit) BaseCredit.clone();
}
上面的思路对于数组处理同样很有用。
18、乘法和除法
考虑下面的代码:
for (val = 0; val < 100000; val +=5) {
alterX = val * 8; myResult = val * 2;
}
用移位操作替代乘法操作可以极大地提高性能。下面是修改后的代码:
for (val = 0; val < 100000; val += 5) {
alterX = val << 3; myResult = val << 1;
}
修改后的代码不再做乘以8的操作,而是改用等价的左移3位操作,每左移1位相当于乘以2。相应地,右移1位操作相当于除以2。值得一提的是,虽然移位操作速度快,但可能使代码比较难于理解,所以最好加上一些注释。
19、在JSP页面中关闭无用的会话。
一个常见的误解是以为session在有客户端访问时就被创建,然而事实是直到某server端程序调用 HttpServletRequest.getSession(true)这样的语句时才被创建,注意如果JSP没有显示的使用 <%@page session="false"%> 关闭session,则JSP文件在编译成Servlet时将会自动加上这样一条语句HttpSession session = HttpServletRequest.getSession(true);这也是JSP中隐含的 session对象的来历。由于session会消耗内存资源,因此,如果不打算使用session,应该在所有的JSP中关闭它。
对于那些无需跟踪会话状态的页面,关闭自动创建的会话可以节省一些资源。使用如下page指令:<%@ page session="false"%>
20、JDBC与I/O
如果应用程序需要访问一个规模很大的数据集,则应当考虑使用块提取方式。默认情况下,JDBC每次提取32行数据。举例来说,假设我们要遍历一个5000行的记录集,JDBC必须调用数据库157次才能提取到全部数据。如果把块大小改成512,则调用数据库的次数将减少到10次。
[p][/p]21、Servlet与内存使用
许多开发者随意地把大量信息保存到用户会话之中。一些时候,保存在会话中的对象没有及时地被垃圾回收机制回收。从性能上看,典型的症状是用户感到系统周期性地变慢,却又不能把原因归于任何一个具体的组件。如果监视JVM的堆空间,它的表现是内存占用不正常地大起大落。
解决这类内存问题主要有二种办法。第一种办法是,在所有作用范围为会话的Bean中实现HttpSessionBindingListener接口。这样,只要实现valueUnbound()方法,就可以显式地释放Bean使用的资源。 另外一种办法就是尽快地把会话作废。大多数应用服务器都有设置会话作废间隔时间的选项。另外,也可以用编程的方式调用会话的setMaxInactiveInterval()方法,该方法用来设定在作废会话之前,Servlet容器允许的客户请求的最大间隔时间,以秒计。
22、使用缓冲标记
一些应用服务器加入了面向JSP的缓冲标记功能。例如,BEA的WebLogic Server从6.0版本开始支持这个功能,Open Symphony工程也同样支持这个功能。JSP缓冲标记既能够缓冲页面片断,也能够缓冲整个页面。当JSP页面执行时,如果目标片断已经在缓冲之中,则生成该片断的代码就不用再执行。页面级缓冲捕获对指定 URL的请求,并缓冲整个结果页面。对于购物篮、目录以及门户网站的主页来说,这个功能极其有用。对于这类应用,页面级缓冲能够保存页面执行的结果,供后继请求使用。
23、选择合适的引用机制
在典型的JSP应用系统中,页头、页脚部分往往被抽取出来,然后根据需要引入页头、页脚。当前,在JSP页面中引入外部资源的方法主要有两种:include指令,以及include动作。
include 指令:例如<%@ include file="copyright.html" %>。该指令在编译时引入指定的资源。在编译之前,带有 include指令的页面和指定的资源被合并成一个文件。被引用的外部资源在编译时就确定,比运行时才确定资源更高效。
include动作:例如<jsp:include page="copyright.jsp" />。该动作引入指定页面执行后生成的结果。由于它在运行时完成,因此对输出结果的控制更加灵活。但时,只有当被引用的内容频繁地改变时,或者在对主页面的请求没有出现之前,被引用的页面无法确定时,使用include 动作才合算。
24、及时清除不再需要的会话
为了清除不再活动的会话,许多应用服务器都有默认的会话超时时间,一般为30分钟。当应用服务器需要保存更多会话时,如果内存容量不足,操作系统会把部分内存数据转移到磁盘,应用服务器也可能根据“最近最频繁使用 ”(Most Recently Used)算法把部分不活跃的会话转储到磁盘,甚至可能抛出“内存不足”异常。在大规模系统中,串行化会话的代价是很昂贵的。当会话不再需要时,应当及时调用HttpSession.invalidate()方法清除会话。 HttpSession.invalidate()方法通常可以在应用的退出页面调用。
25、不要将数组声明为:public static final 。
26、HashMap的遍历效率讨论
经常遇到对HashMap中的key和value值对的遍历操作,有如下两种方法:Map<String, String[]> paraMap = new HashMap<String, String[]>();
................//第一个循环
Set<String> appFieldDefIds = paraMap.keySet();
for (String appFieldDefId : appFieldDefIds) {
String[] values = paraMap.get(appFieldDefId);
......
}
//第二个循环
for(Entry<String, String[]> entry : paraMap.entrySet()){
String appFieldDefId = entry.getKey();
String[] values = entry.getValue();
.......
}
第一种实现明显的效率不如第二种实现。
分析如下 Set<String> appFieldDefIds = paraMap.keySet(); 是先从HashMap中取得keySet
代码如下:
public Set<K> keySet() {
Set<K> ks = keySet;
return (ks != null ? ks : (keySet = new KeySet()));
}
private class KeySet extends AbstractSet<K> {
public Iterator<K> iterator() {
return newKeyIterator();
}
public int size() {
return size;
}
public boolean contains(Object o) {
return containsKey(o);
}
public boolean remove(Object o) {
return HashMap.this.removeEntryForKey(o) != null;
}
public void clear() {
HashMap.this.clear();
}
}
其实就是返回一个私有类KeySet, 它是从AbstractSet继承而来,实现了Set接口。
再来看看for/in循环的语法
for(declaration : expression)
statement
在执行阶段被翻译成如下各式
for(Iterator<E> #i = (expression).iterator(); #i.hashNext();){
declaration = #i.next();
statement
}
因此在第一个for语句for (String appFieldDefId : appFieldDefIds) 中调用了HashMap.keySet().iterator() 而这个方法调用了newKeyIterator()
Iterator<K> newKeyIterator() {
return new KeyIterator();
}
private class KeyIterator extends HashIterator<K> {
public K next() {
return nextEntry().getKey();
}
}
所以在for中还是调用了
在第二个循环for(Entry<String, String[]> entry : paraMap.entrySet())中使用的Iterator是如下的一个内部类
private class EntryIterator extends HashIterator<Map.Entry<K,V>> {
public Map.Entry<K,V> next() {
return nextEntry();
}
}
此时第一个循环得到key,第二个循环得到HashMap的Entry
效率就是从循环里面体现出来的第二个循环此致可以直接取key和value值
而第一个循环还是得再利用HashMap的get(Object key)来取value值
现在看看HashMap的get(Object key)方法
public V get(Object key) {
Object k = maskNull(key);
int hash = hash(k);
int i = indexFor(hash, table.length); //Entry[] table
Entry<K,V> e = table;
while (true) {
if (e == null)
return null;
if (e.hash == hash && eq(k, e.key))
return e.value;
e = e.next;
}
}
其实就是再次利用Hash值取出相应的Entry做比较得到结果,所以使用第一中循环相当于两次进入HashMap的Entry中
而第二个循环取得Entry的值之后直接取key和value,效率比第一个循环高。其实按照Map的概念来看也应该是用第二个循环好一点,它本来就是key和value的值对,将key和value分开操作在这里不是个好选择。
27、array(数组) 和 ArryList的使用
array([]):最高效;但是其容量固定且无法动态改变;
ArrayList:容量可动态增长;但牺牲效率;
基于效率和类型检验,应尽可能使用array,无法确定数组大小时才使用ArrayList!
ArrayList是Array的复杂版本
ArrayList内部封装了一个Object类型的数组,从一般的意义来说,它和数组没有本质的差别,甚至于ArrayList的许多方法,如Index、IndexOf、Contains、Sort等都是在内部数组的基础上直接调用Array的对应方法。
ArrayList存入对象时,抛弃类型信息,所有对象屏蔽为Object,编译时不检查类型,但是运行时会报错。
注:jdk5中加入了对泛型的支持,已经可以在使用ArrayList时进行类型检查。
从这一点上看来,ArrayList与数组的区别主要就是由于动态增容的效率问题了
28、尽量使用HashMap 和ArrayList ,除非必要,否则不推荐使用HashTable和Vector ,后者由于使用同步机制,而导致了性能的开销。
29、StringBuffer 和StringBuilder的区别:
java.lang.StringBuffer 线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。StringBuilder。与该类相比,通常应该优先使用 java.lang.StringBuilder类,因为它支持所有相同的操作,但由于它不执行同步,所以速度更快。为了获得更好的性能,在构造 StirngBuffer 或 StirngBuilder 时应尽可能指定它的容量。当然,如果你操作的字符串长度不超过 16 个字符就不用了。 相同情况下使用 StirngBuilder 相比使用 StringBuffer 仅能获得 10%-15% 左右的性能提升,但却要冒多线程不安全的风险。而在现实的模块化编程中,负责某一模块的程序员不一定能清晰地判断该模块是否会放入多线程的环境中运行,因此:除非你能确定你的系统的瓶颈是在 StringBuffer 上,并且确定你的模块不会运行在多线程模式下,否则还是用 StringBuffer 吧。
可供程序利用的资源(内存、CPU时间、网络带宽等)是有限的,优化的目的就是让程序用尽可能少的资源完成预定的任务。优化通常包含两方面的内容:减小代码的体积,提高代码的运行效率。本文讨论的主要是如何提高代码的效率。
在 Java程序中,性能问题的大部分原因并不在于Java语言,而是在于程序本身。养成好的代码编写习惯非常重要,比如正确地、巧妙地运用 java.lang.String类和java.util.Vector类,它能够显着地提高程序的性能。下面我们就来具体地分析一下这方面的问题。
1、 尽量指定类的final修饰符 带有final修饰符的类是不可派生的。在Java核心API中,有许多应用final的例子,例如 java.lang.String。为String类指定final防止了人们覆盖length()方法。另外,如果指定一个类为final,则该类所有的方法都是final。Java编译器会寻找机会内联(inline)所有的final方法(这和具体的编译器实现有关)。此举能够使性能平均提高 50% 。
2、 尽量重用对象。特别是String 对象的使用中,出现字符串连接情况时应用StringBuffer 代替。由于系统不仅要花时间生成对象,以后可能还需花时间对这些对象进行垃圾回收和处理。因此,生成过多的对象将会给程序的性能带来很大的影响。
3、 尽量使用局部变量,调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中,速度较快。其他变量,如静态变量、实例变量等,都在堆(Heap)中创建,速度较慢。另外,依赖于具体的编译器/JVM,局部变量还可能得到进一步优化。请参见《尽可能使用堆栈变量》。
4、 不要重复初始化变量 默认情况下,调用类的构造函数时, Java会把变量初始化成确定的值:所有的对象被设置成null,整数变量(byte、 short、int、long)设置成0,float和double变量设置成0.0,逻辑值设置成false。当一个类从另一个类派生时,这一点尤其应该注意,因为用new关键词创建一个对象时,构造函数链中的所有构造函数都会被自动调用。
5、 在JAVA + ORACLE 的应用系统开发中,java中内嵌的SQL语句尽量使用大写的形式,以减轻ORACLE解析器的解析负担。
6、 Java 编程过程中,进行数据库连接、I/O流操作时务必小心,在使用完毕后,即使关闭以释放资源。因为对这些大对象的操作会造成系统大的开销,稍有不慎,会导致严重的后果。
7、 由于JVM的有其自身的GC机制,不需要程序开发者的过多考虑,从一定程度上减轻了开发者负担,但同时也遗漏了隐患,过分的创建对象会消耗系统的大量内存,严重时会导致内存泄露,因此,保证过期对象的及时回收具有重要意义。JVM回收垃圾的条件是:对象不在被引用;然而,JVM的GC并非十分的机智,即使对象满足了垃圾回收的条件也不一定会被立即回收。所以,建议我们在对象使用完毕,应手动置成null。
8、 在使用同步机制时,应尽量使用方法同步代替代码块同步。
9、 尽量减少对变量的重复计算
例如:for(int i = 0;i < list.size; i ++) {
…
}
应替换为:
for(int i = 0,int len = list.size();i < len; i ++) {
…
}
10、尽量采用lazy loading 的策略,即在需要的时候才开始创建。
例如: String str = “aaa”;
if(i == 1) {
list.add(str);
}
应替换为:
if(i == 1) {
String str = “aaa”;
list.add(str);
}
11、慎用异常
异常对性能不利。抛出异常首先要创建一个新的对象。Throwable接口的构造函数调用名为fillInStackTrace()的本地(Native)方法,fillInStackTrace()方法检查堆栈,收集调用跟踪信息。只要有异常被抛出,VM就必须调整调用堆栈,因为在处理过程中创建了一个新的对象。 异常只能用于错误处理,不应该用来控制程序流程。
12、不要在循环中使用:
Try {
} catch() {
}
应把其放置在最外层。
13、StringBuffer 的使用:
StringBuffer表示了可变的、可写的字符串。
有三个构造方法 :
StringBuffer (); //默认分配16个字符的空间
StringBuffer (int size); //分配size个字符的空间
StringBuffer (String str); //分配16个字符+str.length()个字符空间
你可以通过StringBuffer的构造函数来设定它的初始化容量,这样可以明显地提升性能。这里提到的构造函数是 StringBuffer(int length),length参数表示当前的StringBuffer能保持的字符数量。你也可以使用 ensureCapacity(int minimumcapacity)方法在StringBuffer对象创建之后设置它的容量。首先我们看看 StringBuffer的缺省行为,然后再找出一条更好的提升性能的途径。
StringBuffer在内部维护一个字符数组,当你使用缺省的构造函数来创建StringBuffer对象的时候,因为没有设置初始化字符长度,StringBuffer的容量被初始化为16个字符,也就是说缺省容量就是16个字符。当StringBuffer达到最大容量的时候,它会将自身容量增加到当前的2倍再加2,也就是(2*旧值+2)。如果你使用缺省值,初始化之后接着往里面追加字符,在你追加到第16个字符的时候它会将容量增加到34(2*16+2),当追加到34个字符的时候就会将容量增加到 70(2*34+2)。无论何事只要StringBuffer到达它的最大容量它就不得不创建一个新的字符数组然后重新将旧字符和新字符都拷贝一遍――这也太昂贵了点。所以总是给StringBuffer设置一个合理的初始化容量值是错不了的,这样会带来立竿见影的性能增益。
StringBuffer初始化过程的调整的作用由此可见一斑。所以,使用一个合适的容量值来初始化StringBuffer永远都是一个最佳的建议。
14、合理的使用Java类 java.util.Vector。
简单地说,一个Vector就是一个java.lang.Object实例的数组。Vector与数组相似,它的元素可以通过整数形式的索引访问。但是,Vector类型的对象在创建之后,对象的大小能够根据元素的增加或者删除而扩展、缩小。请考虑下面这个向Vector加入元素的例子:
Object obj = new Object();
Vector v = new Vector(100000);
for(int I=0;
I<100000; I++) { v.add(0,obj); }
除非有绝对充足的理由要求每次都把新元素插入到Vector的前面,否则上面的代码对性能不利。在默认构造函数中,Vector的初始存储能力是10个元素,如果新元素加入时存储能力不足,则以后存储能力每次加倍。Vector类就象StringBuffer类一样,每次扩展存储能力时,所有现有的元素都要复制到新的存储空间之中。下面的代码片段要比前面的例子快几个数量级:
Object obj = new Object();
Vector v = new Vector(100000);
for(int I=0; I<100000; I++) { v.add(obj); }
同样的规则也适用于Vector类的remove()方法。由于Vector中各个元素之间不能含有“空隙”,删除除最后一个元素之外的任意其他元素都导致被删除元素之后的元素向前移动。也就是说,从Vector删除最后一个元素要比删除第一个元素“开销”低好几倍。
假设要从前面的Vector删除所有元素,我们可以使用这种代码:
for(int I=0; I<100000; I++)
{
v.remove(0);
}
但是,与下面的代码相比,前面的代码要慢几个数量级:
for(int I=0; I<100000; I++)
{
v.remove(v.size()-1);
}
从Vector类型的对象v删除所有元素的最好方法是:
v.removeAllElements();
假设Vector类型的对象v包含字符串“Hello”。考虑下面的代码,它要从这个Vector中删除“Hello”字符串:
String s = "Hello";
int i = v.indexOf(s);
if(I != -1) v.remove(s);
这些代码看起来没什么错误,但它同样对性能不利。在这段代码中,indexOf()方法对v进行顺序搜索寻找字符串“Hello”,remove(s)方法也要进行同样的顺序搜索。改进之后的版本是:
String s = "Hello";
int i = v.indexOf(s);
if(I != -1) v.remove(i);
这个版本中我们直接在remove()方法中给出待删除元素的精确索引位置,从而避免了第二次搜索。一个更好的版本是:
String s = "Hello"; v.remove(s);
最后,我们再来看一个有关Vector类的代码片段:
for(int I=0; I++;I < v.length)
如果v包含100,000个元素,这个代码片段将调用v.size()方法100,000次。虽然size方法是一个简单的方法,但它仍旧需要一次方法调用的开销,至少JVM需要为它配置以及清除堆栈环境。在这里,for循环内部的代码不会以任何方式修改Vector类型对象v的大小,因此上面的代码最好改写成下面这种形式:
int size = v.size(); for(int I=0; I++;I<size)
虽然这是一个简单的改动,但它仍旧赢得了性能。毕竟,每一个CPU周期都是宝贵的。
15、当复制大量数据时,使用System.arraycopy()命令。
16、代码重构:增强代码的可读性。
例如:
public class ShopCart {
private List carts ;
…
public void add (Object item) {
if(carts == null) {
carts = new ArrayList();
}
crts.add(item);
}
public void remove(Object item) {
if(carts. contains(item)) {
carts.remove(item);
}
}
public List getCarts() {
//返回只读列表
return Collections.unmodifiableList(carts);
}
//不推荐这种方式
//this.getCarts().add(item);
}
|
精华游戏算法整理 |
Author: 一滴蔚蓝色 | Date: 2007-05-17 | View: 8311 | 开发技术 - 程序设计 | Digg: 12 |
游戏算法整理 算法一:A*寻路初探
作者: Patrick Lester
译者:Panic 2005年3月18日
译者序:很久以前就知道了A*算法,但是从未认真读过相关的文章,也没有看过代码,只是脑子里有个模糊的概念。这次决定从头开始,研究一下这个被人推崇备至的简单方法,作为学习人工智能的开始。
这篇文章非常知名,国内应该有不少人翻译过它,我没有查找,觉得翻译本身也是对自身英文水平的锻炼。经过努力,终于完成了文档,也明白的A*算法的原理。毫无疑问,作者用形象的描述,简洁诙谐的语言由浅入深的讲述了这一神奇的算法,相信每个读过的人都会对此有所认识(如果没有,那就是偶的翻译太差了 --b)。
现在是2005年7月19日的版本,应原作者要求,对文中的某些算法细节做了修改。
原文链接:http://www.gamedev.net/reference/articles/article2003.asp
原作者文章链接:http://www.policyalmanac.org/games/aStarTutorial.htm
以下是翻译的正文。
会者不难,A*(念作A星)算法对初学者来说的确有些难度。
这篇文章并不试图对这个话题作权威的陈述。取而代之的是,它只是描述算法的原理,使你可以在进一步的阅读中理解其他相关的资料。
最后,这篇文章没有程序细节。你尽可以用任意的计算机程序语言实现它。如你所愿,我在文章的末尾包含了一个指向例子程序的链接。 压缩包包括C++和Blitz Basic两个语言的版本,如果你只是想看看它的运行效果,里面还包含了可执行文件。
我们正在提高自己。让我们从头开始。。。
序:搜索区域
假设有人想从A点移动到一墙之隔的B点,如下图,绿色的是起点A,红色是终点B,蓝色方块是中间的墙。
[图1]
你首先注意到,搜索区域被我们划分成了方形网格。像这样,简化搜索区域,是寻路的第一步。这一方法把搜索区域简化成了一个二维数组。数组的每一个元素是网格的一个方块,方块被标记为可通过的和不可通过的。路径被描述为从A到B我们经过的方块的集合。一旦路径被找到,我们的人就从一个方格的中心走向另一个,直到到达目的地。
这些中点被称为“节点”。当你阅读其他的寻路资料时,你将经常会看到人们讨论节点。为什么不把他们描述为方格呢?因为有可能你的路径被分割成其他不是方格的结构。他们完全可以是矩形,六角形,或者其他任意形状。节点能够被放置在形状的任意位置-可以在中心,或者沿着边界,或其他什么地方。我们使用这种系统,无论如何,因为它是最简单的。
开始搜索
正如我们处理上图网格的方法,一旦搜索区域被转化为容易处理的节点,下一步就是去引导一次找到最短路径的搜索。在A*寻路算法中,我们通过从点A开始,检查相邻方格的方式,向外扩展直到找到目标。
我们做如下操作开始搜索:
1,从点A开始,并且把它作为待处理点存入一个“开启列表”。开启列表就像一张购物清单。尽管现在列表里只有一个元素,但以后就会多起来。你的路径可能会通过它包含的方格,也可能不会。基本上,这是一个待检查方格的列表。
2,寻找起点周围所有可到达或者可通过的方格,跳过有墙,水,或其他无法通过地形的方格。也把他们加入开启列表。为所有这些方格保存点A作为“父方格”。当我们想描述路径的时候,父方格的资料是十分重要的。后面会解释它的具体用途。
3,从开启列表中删除点A,把它加入到一个“关闭列表”,列表中保存所有不需要再次检查的方格。
在这一点,你应该形成如图的结构。在图中,暗绿色方格是你起始方格的中心。它被用浅蓝色描边,以表示它被加入到关闭列表中了。所有的相邻格现在都在开启列表中,它们被用浅绿色描边。每个方格都有一个灰色指针反指他们的父方格,也就是开始的方格。
[图2]
接着,我们选择开启列表中的临近方格,大致重复前面的过程,如下。但是,哪个方格是我们要选择的呢?是那个F值最低的。
路径评分
选择路径中经过哪个方格的关键是下面这个等式:
F = G + H
这里:
* G = 从起点A,沿着产生的路径,移动到网格上指定方格的移动耗费。
* H = 从网格上那个方格移动到终点B的预估移动耗费。这经常被称为启发式的,可能会让你有点迷惑。这样叫的原因是因为它只是个猜测。我们没办法事先知道路径的长度,因为路上可能存在各种障碍(墙,水,等等)。虽然本文只提供了一种计算H的方法,但是你可以在网上找到很多其他的方法。
我们的路径是通过反复遍历开启列表并且选择具有最低F值的方格来生成的。文章将对这个过程做更详细的描述。首先,我们更深入的看看如何计算这个方程。
正如上面所说,G表示沿路径从起点到当前点的移动耗费。在这个例子里,我们令水平或者垂直移动的耗费为10,对角线方向耗费为14。我们取这些值是因为沿对角线的距离是沿水平或垂直移动耗费的的根号2(别怕),或者约1.414倍。为了简化,我们用10和14近似。比例基本正确,同时我们避免了求根运算和小数。这不是只因为我们怕麻烦或者不喜欢数学。使用这样的整数对计算机来说也更快捷。你不就就会发现,如果你不使用这些简化方法,寻路会变得很慢。
既然我们在计算沿特定路径通往某个方格的G值,求值的方法就是取它父节点的G值,然后依照它相对父节点是对角线方向或者直角方向(非对角线),分别增加14和10。例子中这个方法的需求会变得更多,因为我们从起点方格以外获取了不止一个方格。
H值可以用不同的方法估算。我们这里使用的方法被称为曼哈顿方法,它计算从当前格到目的格之间水平和垂直的方格的数量总和,忽略对角线方向。然后把结果乘以10。这被成为曼哈顿方法是因为它看起来像计算城市中从一个地方到另外一个地方的街区数,在那里你不能沿对角线方向穿过街区。很重要的一点,我们忽略了一切障碍物。这是对剩余距离的一个估算,而非实际值,这也是这一方法被称为启发式的原因。想知道更多?你可以在这里找到方程和额外的注解。
F的值是G和H的和。第一步搜索的结果可以在下面的图表中看到。F,G和H的评分被写在每个方格里。正如在紧挨起始格右侧的方格所表示的,F被打印在左上角,G在左下角,H则在右下角。
[图3]
现在我们来看看这些方格。写字母的方格里,G = 10。这是因为它只在水平方向偏离起始格一个格距。紧邻起始格的上方,下方和左边的方格的G值都等于10。对角线方向的G值是14。
H值通过求解到红色目标格的曼哈顿距离得到,其中只在水平和垂直方向移动,并且忽略中间的墙。用这种方法,起点右侧紧邻的方格离红色方格有3格距离,H值就是30。这块方格上方的方格有4格距离(记住,只能在水平和垂直方向移动),H值是40。你大致应该知道如何计算其他方格的H值了~。
每个格子的F值,还是简单的由G和H相加得到
继续搜索
为了继续搜索,我们简单的从开启列表中选择F值最低的方格。然后,对选中的方格做如下处理:
4,把它从开启列表中删除,然后添加到关闭列表中。
5,检查所有相邻格子。跳过那些已经在关闭列表中的或者不可通过的(有墙,水的地形,或者其他无法通过的地形),把他们添加进开启列表,如果他们还不在里面的话。把选中的方格作为新的方格的父节点。
6,如果某个相邻格已经在开启列表里了,检查现在的这条路径是否更好。换句话说,检查如果我们用新的路径到达它的话,G值是否会更低一些。如果不是,那就什么都不做。
另一方面,如果新的G值更低,那就把相邻方格的父节点改为目前选中的方格(在上面的图表中,把箭头的方向改为指向这个方格)。最后,重新计算F和G的值。如果这看起来不够清晰,你可以看下面的图示。
好了,让我们看看它是怎么运作的。我们最初的9格方格中,在起点被切换到关闭列表中后,还剩8格留在开启列表中。这里面,F值最低的那个是起始格右侧紧邻的格子,它的F值是40。因此我们选择这一格作为下一个要处理的方格。在紧随的图中,它被用蓝色突出显示。
[图4]
首先,我们把它从开启列表中取出,放入关闭列表(这就是他被蓝色突出显示的原因)。然后我们检查相邻的格子。哦,右侧的格子是墙,所以我们略过。左侧的格子是起始格。它在关闭列表里,所以我们也跳过它。
其他4格已经在开启列表里了,于是我们检查G值来判定,如果通过这一格到达那里,路径是否更好。我们来看选中格子下面的方格。它的G值是14。如果我们从当前格移动到那里,G值就会等于20(到达当前格的G值是10,移动到上面的格子将使得G值增加10)。因为G值20大于14,所以这不是更好的路径。如果你看图,就能理解。与其通过先水平移动一格,再垂直移动一格,还不如直接沿对角线方向移动一格来得简单。
当我们对已经存在于开启列表中的4个临近格重复这一过程的时候,我们发现没有一条路径可以通过使用当前格子得到改善,所以我们不做任何改变。既然我们已经检查过了所有邻近格,那么就可以移动到下一格了。
于是我们检索开启列表,现在里面只有7格了,我们仍然选择其中F值最低的。有趣的是,这次,有两个格子的数值都是54。我们如何选择?这并不麻烦。从速度上考虑,选择最后添加进列表的格子会更快捷。这种导致了寻路过程中,在靠近目标的时候,优先使用新找到的格子的偏好。但这无关紧要。(对相同数值的不同对待,导致不同版本的A*算法找到等长的不同路径。)
那我们就选择起始格右下方的格子,如图。
[图5]
这次,当我们检查相邻格的时候,发现右侧是墙,于是略过。上面一格也被略过。我们也略过了墙下面的格子。为什么呢?因为你不能在不穿越墙角的情况下直接到达那个格子。你的确需要先往下走然后到达那一格,按部就班的走过那个拐角。(注解:穿越拐角的规则是可选的。它取决于你的节点是如何放置的。)
这样一来,就剩下了其他5格。当前格下面的另外两个格子目前不在开启列表中,于是我们添加他们,并且把当前格指定为他们的父节点。其余3格,两个已经在关闭列表中(起始格,和当前格上方的格子,在表格中蓝色高亮显示),于是我们略过它们。最后一格,在当前格的左侧,将被检查通过这条路径,G值是否更低。不必担心,我们已经准备好检查开启列表中的下一格了。
我们重复这个过程,直到目标格被添加进关闭列表(注解),就如在下面的图中所看到的。
[图6]
注意,起始格下方格子的父节点已经和前面不同的。之前它的G值是28,并且指向右上方的格子。现在它的G值是20,指向它上方的格子。这在寻路过程中的某处发生,当应用新路径时,G值经过检查变得低了-于是父节点被重新指定,G和F值被重新计算。尽管这一变化在这个例子中并不重要,在很多场合,这种变化会导致寻路结果的巨大变化。
那么,我们怎么确定这条路径呢?很简单,从红色的目标格开始,按箭头的方向朝父节点移动。这最终会引导你回到起始格,这就是你的路径!看起来应该像图中那样。从起始格A移动到目标格B只是简单的从每个格子(节点)的中点沿路径移动到下一个,直到你到达目标点。就这么简单。
[图7]
A*方法总结
好,现在你已经看完了整个说明,让我们把每一步的操作写在一起:
1,把起始格添加到开启列表。
2,重复如下的工作:
a) 寻找开启列表中F值最低的格子。我们称它为当前格。
b) 把它切换到关闭列表。
c) 对相邻的8格中的每一个?
* 如果它不可通过或者已经在关闭列表中,略过它。反之如下。
* 如果它不在开启列表中,把它添加进去。把当前格作为这一格的父节点。记录这一格的F,G,和H值。
* 如果它已经在开启列表中,用G值为参考检查新的路径是否更好。更低的G值意味着更好的路径。如果是这样,就把这一格的父节点改成当前格,并且重新计算这一格的G和F值。如果你保持你的开启列表按F值排序,改变之后你可能需要重新对开启列表排序。
d) 停止,当你
* 把目标格添加进了关闭列表(注解),这时候路径被找到,或者
* 没有找到目标格,开启列表已经空了。这时候,路径不存在。
3.保存路径。从目标格开始,沿着每一格的父节点移动直到回到起始格。这就是你的路径。
(注解:在这篇文章的较早版本中,建议的做法是当目标格(或节点)被加入到开启列表,而不是关闭列表的时候停止寻路。这么做会更迅速,而且几乎总是能找到最短的路径,但不是绝对的。当从倒数第二个节点到最后一个(目标节点)之间的移动耗费悬殊很大时-例如刚好有一条河穿越两个节点中间,这时候旧的做法和新的做法就会有显著不同。)
题外话
离题一下,见谅,值得一提的是,当你在网上或者相关论坛看到关于A*的不同的探讨,你有时会看到一些被当作A*算法的代码而实际上他们不是。要使用 A*,你必须包含上面讨论的所有元素--特定的开启和关闭列表,用F,G和H作路径评价。有很多其他的寻路算法,但他们并不是A*,A*被认为是他们当中最好的。Bryan Stout在这篇文章后面的参考文档中论述了一部分,包括他们的一些优点和缺点。有时候特定的场合其他算法会更好,但你必须很明确你在作什么。好了,够多的了。回到文章。
实现的注解
现在你已经明白了基本原理,写你的程序的时候还得考虑一些额外的东西。下面这些材料中的一些引用了我用C++和Blitz Basic写的程序,但对其他语言写的代码同样有效。
1.其他单位(避免碰撞):如果你恰好看了我的例子代码,你会发现它完全忽略了其他单位。我的寻路者事实上可以相互穿越。取决于具体的游戏,这也许可以,也许不行。如果你打算考虑其他单位,希望他们能互相绕过,我建议你只考虑静止或那些在计算路径时临近当前单位的单位,把它们当前的位置标志为可通过的。对于临近的运动着的单位,你可以通过惩罚它们各自路径上的节点,来鼓励这些寻路者找到不同的路径(更多的描述见#2).
如果你选择了把其他正在移动并且远离当前寻路单位的那些单位考虑在内,你将需要实现一种方法及时预测在何时何地碰撞可能会发生,以便恰当的避免。否则你极有可能得到一条怪异的路径,单位突然转弯试图避免和一个已经不存在的单位发生碰撞。
当然,你也需要写一些碰撞检测的代码,因为无论计算的时候路径有多完美,它也会因时间而改变。当碰撞发生时,一个单位必须寻找一条新路径,或者,如果另一个单位正在移动并且不是正面碰撞,在继续沿当前路径移动之前,等待那个单位离开。
这些提示大概可以让你开始了。如果你想了解更多,这里有些你可能会觉得有用的链接:
* 自治角色的指导行为:Craig Reynold在指导能力上的工作和寻路有些不同,但是它可以和寻路整合从而形成更完整的移动和碰撞检测系统。
* 电脑游戏中的长短距指导:指导和寻路方面著作的一个有趣的考察。这是一个pdf文件。
* 协同单位移动:一个两部分系列文章的第一篇,内容是关于编队和基于分组的移动,作者是帝国时代(Age of Empires)的设计者Dave Pottinger.
* 实现协同移动:Dave Pottinger文章系列的第二篇。
2. 不同的地形损耗:在这个教程和我附带的程序中,地形只能是二者之-可通过的和不可通过的。但是你可能会需要一些可通过的地形,但是移动耗费更高-沼泽,小山,地牢的楼梯,等等。这些都是可通过但是比平坦的开阔地移动耗费更高的地形。类似的,道路应该比自然地形移动耗费更低。
这个问题很容易解决,只要在计算任何地形的G值的时候增加地形损耗就可以了。简单的给它增加一些额外的损耗就可以了。由于A*算法已经按照寻找最低耗费的路径来设计,所以很容易处理这种情况。在我提供的这个简单的例子里,地形只有可通过和不可通过两种,A*会找到最短,最直接的路径。但是在地形耗费不同的场合,耗费最低的路径也许会包含很长的移动距离-就像沿着路绕过沼泽而不是直接穿过它。
一种需额外考虑的情况是被专家称之为“influence mapping”的东西(暂译为影响映射图)。就像上面描述的不同地形耗费一样,你可以创建一格额外的分数系统,并把它应用到寻路的AI中。假设你有一张有大批寻路者的地图,他们都要通过某个山区。每次电脑生成一条通过那个关口的路径,它就会变得更拥挤。如果你愿意,你可以创建一个影响映射图对有大量屠杀事件的格子施以不利影响。这会让计算机更倾向安全些的路径,并且帮助它避免总是仅仅因为路径短(但可能更危险)而持续把队伍和寻路者送到某一特定路径。
另一个可能得应用是惩罚周围移动单位路径上得节点。A*的一个底限是,当一群单位同时试图寻路到接近的地点,这通常会导致路径交叠。以为一个或者多个单位都试图走相同或者近似的路径到达目的地。对其他单位已经“认领”了的节点增加一些惩罚会有助于你在一定程度上分离路径,降低碰撞的可能性。然而,如果有必要,不要把那些节点看成不可通过的,因为你仍然希望多个单位能够一字纵队通过拥挤的出口。同时,你只能惩罚那些临近单位的路径,而不是所有路径,否则你就会得到奇怪的躲避行为例如单位躲避路径上其他已经不在那里的单位。 还有,你应该只惩罚路径当前节点和随后的节点,而不应处理已经走过并甩在身后的节点。
3. 处理未知区域:你是否玩过这样的PC游戏,电脑总是知道哪条路是正确的,即使它还没有侦察过地图?对于游戏,寻路太好会显得不真实。幸运的是,这是一格可以轻易解决的问题。
答案就是为每个不同的玩家和电脑(每个玩家,而不是每个单位--那样的话会耗费大量的内存)创建一个独立的“knownWalkability”数组,每个数组包含玩家已经探索过的区域,以及被当作可通过区域的其他区域,直到被证实。用这种方法,单位会在路的死端徘徊并且导致错误的选择直到他们在周围找到路。一旦地图被探索了,寻路就像往常那样进行。
4. 平滑路径:尽管A*提供了最短,最低代价的路径,它无法自动提供看起来平滑的路径。看一下我们的例子最终形成的路径(在图7)。最初的一步是起始格的右下方,如果这一步是直接往下的话,路径不是会更平滑一些吗?
有几种方法来解决这个问题。当计算路径的时候可以对改变方向的格子施加不利影响,对G值增加额外的数值。也可以换种方法,你可以在路径计算完之后沿着它跑一遍,找那些用相邻格替换会让路径看起来更平滑的地方。想知道完整的结果,查看Toward More Realistic Pathfinding,一篇(免费,但是需要注册)Marco Pinter发表在Gamasutra.com的文章
5. 非方形搜索区域:在我们的例子里,我们使用简单的2D方形图。你可以不使用这种方式。你可以使用不规则形状的区域。想想冒险棋的游戏,和游戏中那些国家。你可以设计一个像那样的寻路关卡。为此,你可能需要建立一个国家相邻关系的表格,和从一个国家移动到另一个的G值。你也需要估算H值的方法。其他的事情就和例子中完全一样了。当你需要向开启列表中添加新元素的时候,不需使用相邻的格子,取而代之的是从表格中寻找相邻的国家。
类似的,你可以为一张确定的地形图创建路径点系统,路径点一般是路上,或者地牢通道的转折点。作为游戏设计者,你可以预设这些路径点。两个路径点被认为是相邻的如果他们之间的直线上没有障碍的话。在冒险棋的例子里,你可以保存这些相邻信息在某个表格里,当需要在开启列表中添加元素的时候使用它。然后你就可以记录关联的G值(可能使用两点间的直线距离),H值(可以使用到目标点的直线距离),其他都按原先的做就可以了。
Amit Patel 写了其他方法的摘要。另一个在非方形区域搜索RPG地图的例子,查看我的文章Two-Tiered A* Pathfinding。(译者注:译文: A*分层寻路)
6. 一些速度方面的提示:当你开发你自己的A*程序,或者改写我的,你会发现寻路占据了大量的CPU时间,尤其是在大地图上有大量对象在寻路的时候。如果你阅读过网上的其他材料,你会明白,即使是开发了星际争霸或帝国时代的专家,这也无可奈何。如果你觉得寻路太过缓慢,这里有一些建议也许有效:
* 使用更小的地图或者更少的寻路者。
* 不要同时给多个对象寻路。取而代之的是把他们加入一个队列,把寻路过程分散在几个游戏周期中。如果你的游戏以40周期每秒的速度运行,没人能察觉。但是当大量寻路者计算自己路径的时候,他们会发觉游戏速度突然变慢。
* 尽量使用更大的地图网格。这降低了寻路中搜索的总网格数。如果你有志气,你可以设计两个或者更多寻路系统以便使用在不同场合,取决于路径的长度。这也正是专业人士的做法,用大的区域计算长的路径,然后在接近目标的时候切换到使用小格子/区域的精细寻路。如果你对这个观点感兴趣,查阅我的文章Two-Tiered A* Pathfinding。(译者注:译文 :A*分层寻路)
* 使用路径点系统计算长路径,或者预先计算好路径并加入到游戏中。
* 预处理你的地图,表明地图中哪些区域是不可到达的。我把这些区域称作“孤岛”。事实上,他们可以是岛屿或其他被墙壁包围等无法到达的任意区域。A*的下限是,当你告诉它要寻找通往那些区域的路径时,它会搜索整个地图,直到所有可到达的方格/节点都被通过开启列表和关闭列表的计算。这会浪费大量的CPU时间。可以通过预先确定这些区域(比如通过flood-fill或类似的方法)来避免这种情况的发生,用某些种类的数组记录这些信息,在开始寻路前检查它。
* 在一个拥挤的类似迷宫的场合,把不能连通的节点看作死端。这些区域可以在地图编辑器中预先手动指定,或者如果你有雄心壮志,开发一个自动识别这些区域的算法。给定死端的所有节点可以被赋予一个唯一的标志数字。然后你就可以在寻路过程中安全的忽略所有死端,只有当起点或者终点恰好在死端的某个节点的时候才需要考虑它们。
7. 维护开启列表:这是A*寻路算法最重要的组成部分。每次你访问开启列表,你都需要寻找F值最低的方格。有几种不同的方法实现这一点。你可以把路径元素随意保存,当需要寻找F值最低的元素的时候,遍历开启列表。这很简单,但是太慢了,尤其是对长路径来说。这可以通过维护一格排好序的列表来改善,每次寻找F值最低的方格只需要选取列表的首元素。当我自己实现的时候,这种方法是我的首选。
在小地图。这种方法工作的很好,但它并不是最快的解决方案。更苛求速度的A*程序员使用叫做二叉堆的方法,这也是我在代码中使用的方法。凭我的经验,这种方法在大多数场合会快2~3倍,并且在长路经上速度呈几何级数提升(10倍以上速度)。如果你想了解更多关于二叉堆的内容,查阅我的文章,Using Binary Heaps in A* Pathfinding。(译者注:译文:在A*寻路中使用二叉堆)
另一个可能的瓶颈是你在多次寻路之间清除和保存你的数据结构的方法。我个人更倾向把所有东西都存储在数组里面。虽然节点可以以面向对象的风格被动态的产生,记录和保存,我发现创建和删除对象所增加的大量时间,以及多余的管理层次减慢的整个过程的速度。但是,如果你使用数组,你需要在调用之间清理数据。这中情形你想做的最后一件事就是在寻路调用之后花点时间把一切归零,尤其是你的地图很大的时候。
我通过使用一个叫做whichList(x,y)的二维数组避免这种开销,数组的每个元素表明了节点在开启列表还是在关闭列表中。尝试寻路之后,我没有清零这个数组。取而代之的是,我在新的寻路中重置onClosedList和onOpenList的数值,每次寻路两个都+5或者类似其他数值。这种方法,算法可以安全的跳过前面寻路留下的脏数据。我还在数组中储存了诸如F,G和H的值。这样一来,我只需简单的重写任何已经存在的值而无需被清除数组的操作干扰。将数据存储在多维数组中需要更多内存,所以这里需要权衡利弊。最后,你应该使用你最得心应手的方法。
8. Dijkstra的算法:尽管A*被认为是通常最好的寻路算法(看前面的“题外话”),还是有一种另外的算法有它的可取之处-Dijkstra算法。 Dijkstra算法和A*本质是相同的,只有一点不同,就是Dijkstra算法没有启发式(H值总是0)。由于没有启发式,它在各个方向上平均搜索。正如你所预料,由于Dijkstra算法在找到目标前通常会探索更大的区域,所以一般会比A*更慢一些。
那么为什么要使用这种算法呢?因为有时候我们并不知道目标的位置。比如说你有一个资源采集单位,需要获取某种类型的资源若干。它可能知道几个资源区域,但是它想去最近的那个。这种情况,Dijkstra算法就比A*更适合,因为我们不知道哪个更近。用A*,我们唯一的选择是依次对每个目标许路并计算距离,然后选择最近的路径。我们寻找的目标可能会有不计其数的位置,我们只想找其中最近的,而我们并不知道它在哪里,或者不知道哪个是最近的。
进一步的阅读
好,现在你对一些进一步的观点有了初步认识。这时,我建议你研究我的源代码。包里面包含两个版本,一个是用C++写的,另一个用Blitz Basic。顺便说一句,两个版本都注释详尽,容易阅读,这里是链接。
* 例子代码: A* Pathfinder (2D) Version 1.9
如果你既不用C++也不用Blitz Basic,在C++版本里有两个小的可执行文件。Blitz Basic可以在从Blitz Basic网站免费下载的Blitz Basic 3D(不是Blitz Plus)演示版上运行。Ben O'Neill提供一个联机演示可以在这里找到。
你也该看看以下的网页。读了这篇教程后,他们应该变得容易理解多了。
* Amit的 A* 页面:这是由Amit Patel制作,被广泛引用的页面,如果你没有事先读这篇文章,可能会有点难以理解。值得一看。尤其要看Amit关于这个问题的自己的看法。
* Smart Moves:智能寻路:Bryan Stout发表在Gamasutra.com的这篇文章需要注册才能阅读。注册是免费的而且比起这篇文章和网站的其他资源,是非常物有所值的。Bryan用Delphi写的程序帮助我学习A*,也是我的A*代码的灵感之源。它还描述了A*的几种变化。
* 地形分析:这是一格高阶,但是有趣的话题,Dave Pottinge撰写,Ensemble Studios的专家。这家伙参与了帝国时代和君王时代的开发。别指望看懂这里所有的东西,但是这是篇有趣的文章也许会让你产生自己的想法。它包含一些对 mip-mapping,influence mapping以及其他一些高级AI/寻路观点。对"flood filling"的讨论使我有了我自己的“死端”和“孤岛”的代码的灵感,这些包含在我Blitz版本的代码中。
其他一些值得一看的网站:
* aiGuru: Pathfinding
* Game AI Resource: Pathfinding
* GameDev.net: Pathfinding
我同样高度推荐下面这几本书, 里面有很多关于寻路和其他AI话题的文章。 它们也附带了实例代码的CD。这些书我都买了。另外,如果你通过下面的链接购买了它们,我会从Amazon得到几个美分。:)
好了,这就是全部。如果你刚好写一个运用这些观点的程序,我想拜读一下。你可以这样联系我:
现在,好运!
译者参考文献:
在A*寻路中使用二叉堆
A*分层寻
游戏算法整理 算法二:碰撞
1. 碰撞检测和响应
碰撞在游戏中运用的是非常广泛的,运用理论实现的碰撞,再加上一些小技巧,可以让碰撞检测做得非常精确,效率也非常高。从而增加游戏的功能和可玩性。
2D碰撞检测
2D的碰撞检测已经非常稳定,可以在许多著作和论文中查询到。3D的碰撞还没有找到最好的方法,现在使用的大多数方法都是建立在2D基础上的。
碰撞检测
碰撞的检测不仅仅是运用在游戏中,事实上,一开始的时候是运用在模拟和机器人技术上的。这些工业上的碰撞检测要求非常高,而碰撞以后的响应也是需要符合现实生活的,是需要符合人类常规认识的。游戏中的碰撞有些许的不一样,况且,更重要的,我们制作的东西充其量是商业级别,还不需要接触到纷繁复杂的数学公式。
图1
最理想的碰撞,我想莫过于上图,完全按照多边形的外形和运行路径规划一个范围,在这个范围当中寻找会产生阻挡的物体,不管是什么物体,产生阻挡以后,我们运动的物体都必须在那个位置产生一个碰撞的事件。最美好的想法总是在实现上有一些困难,事实上我们可以这么做,但是效率却是非常非常低下的,游戏中,甚至于工业中无法忍受这种速度,所以我们改用其它的方法来实现。
图2
最简单的方法如上图,我们寻找物体的中心点,然后用这个中心点来画一个圆,如果是一个3D的物体,那么我们要画的就是一个球体。在检测物体碰撞的时候,我们只要检测两个物体的半径相加是否大于这两个物体圆心的实际距离。
这个算法是最简单的一种,现在还在用,但是不是用来做精确的碰撞检测,而是用来提高效率的模糊碰撞检测查询,到了这个范围以后,再进行更加精密的碰撞检测。一种比较精密的碰撞检测查询就是继续这种画圆的思路,然后把物体细分,对于物体的每个部件继续画圆,然后再继续进行碰撞检测,直到系统规定的,可以容忍的误差范围以后才触发碰撞事件,进行碰撞的一些操作。
有没有更加简单的方法呢?2D游戏中有许多图片都是方方正正的,所以我们不必把碰撞的范围画成一个圆的,而是画成一个方的。这个正方形,或者说是一个四边形和坐标轴是对齐的,所以运用数学上的一些方法,比如距离计算等还是比较方便的。这个检测方法就叫AABBs(Axis-aligned Bounding Boxes)碰撞检测,游戏中已经运用的非常广泛了,因为其速度快,效率高,计算起来非常方便,精确度也是可以忍受的。
做到这一步,许多游戏的需求都已经满足了。但是,总是有人希望近一步优化,而且方法也是非常陈旧的:继续对物体的各个部分进行细分,对每个部件做AABB 的矩形,那这个优化以后的系统就叫做OBB系统。虽然说这个优化以后的系统也不错,但是,许多它可以运用到的地方,别人却不爱使用它,这是后面会继续介绍的地方。
John Carmack不知道看的哪本书,他早在DOOM中已经使用了BSP系统(二分空间分割),再加上一些小技巧,他的碰撞做得就非常好了,再加上他发明的 castray算法,DOOM已经不存在碰撞的问题,解决了这样的关键技术,我想他不再需要在什么地方分心了,只要继续研究渲染引擎就可以了。(Windows游戏编程大师技巧P392~P393介绍)(凸多边形,多边形退化,左手定律)SAT系统非常复杂,是SHT(separating hyperplane theorem,分离超平面理论)的一种特殊情况。这个理论阐述的就是两个不相关的曲面,是否能够被一个超平面所分割开来,所谓分割开来的意思就是一个曲面贴在平面的一边,而另一个曲面贴在平面的另一边。我理解的就是有点像相切的意思。SAT是SHT的特殊情况,所指的就是两个曲面都是一些多边形,而那个超平面也是一个多边形,这个超平面的多边形可以在场景中的多边形列表中找到,而超平面可能就是某个多边形的表面,很巧的就是,这个表面的法线和两个曲面的切面是相对应的。接下来的证明,我想是非常复杂的事情,希望今后能够找到源代码直接运用上去。而我们现在讲究的快速开发,我想AABB就足以满足了。
3D碰撞检测
3D的检测就没有什么很标准的理论了,都建立在2D的基础上,我们可以沿用AABB或者OBB,或者先用球体做粗略的检测,然后用AABB和OBB作精细的检测。BSP技术不流行,但是效率不错。微软提供了D3DIntersect函数让大家使用,方便了许多,但是和通常一样,当物体多了以后就不好用了,明显的就是速度慢许多。
碰撞反应
碰撞以后我们需要做一些反应,比如说产生反冲力让我们反弹出去,或者停下来,或者让阻挡我们的物体飞出去,或者穿墙,碰撞最讨厌的就是穿越,本来就不合逻辑,查阅了那么多资料以后,从来没有看到过需要穿越的碰撞,有摩擦力是另外一回事。首先看看弹性碰撞。弹性碰撞就是我们初中物理中说的动量守恒。物体在碰撞前后的动量守恒,没有任何能量损失。这样的碰撞运用于打砖块的游戏中。引入质量的话,有的物体会是有一定的质量,这些物体通常来说是需要在碰撞以后进行另外一个方向的运动的,另外一些物体是设定为质量无限大的,这些物体通常是碰撞墙壁。
当物体碰到质量非常大的物体,默认为碰到了一个弹性物体,其速度会改变,但是能量不会受到损失。一般在代码上的做法就是在速度向量上加上一个负号。
绝对的弹性碰撞是很少有的,大多数情况下我们运用的还是非弹性碰撞。我们现在玩的大多数游戏都用的是很接近现实的非弹性碰撞,例如Pain-Killer 中的那把吸力枪,它弹出去的子弹吸附到NPC身上时的碰撞响应就是非弹性碰撞;那把残忍的分尸刀把墙打碎的初始算法就是一个非弹性碰撞,其后使用的刚体力学就是先建立在这个算法上的。那么,是的,如果需要非弹性碰撞,我们需要介入摩擦力这个因素,而我们也无法简单使用动量守恒这个公式。
我们可以采取比较简单的方法,假设摩擦系数μ非常大,那么只要物体接触,并且拥有一个加速度,就可以产生一个无穷大的摩擦力,造成物体停止的状态。
基于别人的引擎写出一个让自己满意的碰撞是不容易的,那么如果自己建立一个碰撞系统的话,以下内容是无法缺少的:
– 一个能够容忍的碰撞系统
– 一个从概念上可以接受的物理系统
– 质量
– 速度
– 摩擦系数
– 地心引力
http://www.gamasutra.com/features/20000330/bobic_01.htm
http://www.gamasutra.com/features/20000330/bobic_02.htm
http://www.gamasutra.com/features/20000330/bobic_03.htm
这三篇是高级碰撞检测。
游戏算法整理 算法三:寻路算法新思维
目前常用寻路算法是A*方式,原理是通过不断搜索逼近目的地的路点来获得。
如果通过图像模拟搜索点,可以发现:非启发式的寻路算法实际上是一种穷举法,通过固定顺序依次搜索人物周围的路点,直到找到目的地,搜索点在图像上的表现为一个不断扩大的矩形。如下:
很快人们发现如此穷举导致搜索速度过慢,而且不是很符合逻辑,试想:如果要从(0,0)点到达(100,0)点,如果每次向东搜索时能够走通,那么干吗还要搜索其他方向呢?所以,出现了启发式的A*寻路算法,一般通过 已经走过的路程 + 到达目的地的直线距离 代价值作为搜索时的启发条件,每个点建立一个代价值,每次搜索时就从代价低的最先搜索,如下:
综上所述,以上的搜索是一种矩阵式的不断逼近终点的搜索做法。优点是比较直观,缺点在于距离越远、搜索时间越长。
现在,我提出一种新的AI寻路方式——矢量寻路算法。
通过观察,我们可以发现,所有的最优路线,如果是一条折线,那么、其每一个拐弯点一定发生在障碍物的突出边角,而不会在还没有碰到障碍物就拐弯的情况:如下图所示:
我们可以发现,所有的红色拐弯点都是在障碍物(可以认为是一个凸多边形)的顶点处,所以,我们搜索路径时,其实只需要搜索这些凸多边形顶点不就可以了吗?如果将各个顶点连接成一条通路就找到了最优路线,而不需要每个点都检索一次,这样就大大减少了搜索次数,不会因为距离的增大而增大搜索时间。
这种思路我尚未将其演变为算法,姑且提出一个伪程序给各位参考:
1.建立各个凸多边形顶点的通路表TAB,表示顶点A到顶点B是否可达,将可达的顶点分组保存下来。如: ( (0,0) (100,0) ),这一步骤在程序刚开始时完成,不要放在搜索过程中空耗时间。
2.开始搜索A点到B点的路线
3.检测A点可以直达凸多边形顶点中的哪一些,挑选出最合适的顶点X1。
4.检测与X1相连(能够接通)的有哪些顶点,挑出最合适的顶点X2。
5.X2是否是终点B?是的话结束,否则转步骤4(X2代入X1)
如此下来,搜索只发生在凸多边形的顶点,节省了大量的搜索时间,而且找到的路线无需再修剪锯齿,保证了路线的最优性。
这种方法搜索理论上可以减少大量搜索点、缺点是需要实现用一段程序得出TAB表,从本质上来说是一种空间换时间的方法,而且搜索时A*能够用的启发条件,在矢量搜索时依然可以使用。
游戏算法整理 算法四:战略游戏中的战争模型算法的初步探讨
《三国志》系列游戏相信大家都有所了解,而其中的(宏观)战斗时关于双方兵力,士气,兵种克制,攻击力,增援以及随战争进行兵力减少等数值的算法是十分值得研究的。或许是由于简单的缘故,我在网上几乎没有找到相关算法的文章。下面给出这个战争的数学模型算法可以保证游戏中战争的游戏性与真实性兼顾,希望可以给有需要这方面开发的人一些启迪。
假设用x(t)和y(t)表示甲乙交战双方在t时刻的兵力,如果是开始时可视为双方士兵人数。
假设每一方的战斗减员率取决于双方兵力和战斗力,用f(x,y)和g(x,y)表示,每一方的增援率是给定函数用u(t)和v(t)表示。
如果双方用正规部队作战(可假设是相同兵种),先分析甲方的战斗减员率f(x,y)。可知甲方士兵公开活动,处于乙方没一个士兵的监视和杀伤范围之内,一但甲方的某个士兵被杀伤,乙方的火力立即集中在其余士兵身上,所以甲方的战斗减员率只与乙方的兵力有关可射为f与y成正比,即f=ay,a表示乙方平均每个士兵对甲方士兵的杀伤率(单位时间的杀伤数),成为乙方的战斗有效系数。类似g= -bx
这个战争模型模型方程1为
x’(t)= -a*y(t)+u(t) x’(t)是x(t)对于t 的导数
y’(t)= -b*x(t)+v(t) y’(t)是y(t)对于t的导数
利用给定的初始兵力,战争持续时间,和增援兵力可以求出双方兵力在战争中的变化函数。
(本文中解法略)
如果考虑由于士气和疾病等引起的非战斗减员率(一般与本放兵力成正比,设甲乙双方分别为h,w)
可得到改进战争模型方程2:
x’(t)= -a*y(t)-h*x(t)+u(t)
y’(t)= -b*x(t)-w*y(t)+v(t)
利用初始条件同样可以得到双方兵力在战争中的变化函数和战争结果。
此外还有不同兵种作战(兵种克制)的数学模型:
模型1中的战斗有效系数a可以进一步分解为a=ry*py*(sry/sx),其中ry是乙方的攻击率(每个士兵单位的攻击次数),py是每次攻击的命中率。(sry/sx)是乙方攻击的有效面积sry与甲方活动范围sx之比。类似甲方的战斗有效系数b=rx*px*(srx/sy),rx和px是甲方的攻击率和命中率,(srx/sy)是甲方攻击的有效面积与乙方活动范围sy之比。由于增加了兵种克制的攻击范围,所以战斗减员率不光与对方兵力有关,而且随着己放兵力增加而增加。因为在一定区域内,士兵越多被杀伤的就越多。
方程
x’(t)= -ry*py*(sry/sx)*x(t)*y(t)-h*x(t)+u(t)
y’(t)= -rx*px*(srx/sy)*x(t)*y(t)-w*y(t)+u(t)
游戏算法整理 算法五:飞行射击游戏中的碰撞检测
在游戏中物体的碰撞是经常发生的,怎样检测物体的碰撞是一个很关键的技术问题。在RPG游戏中,一般都将场景分为许多矩形的单元,碰撞的问题被大大的简化了,只要判断精灵所在的单元是不是有其它的东西就可以了。而在飞行射击游戏(包括象荒野大镖客这样的射击游戏)中,碰撞却是最关键的技术,如果不能很好的解决,会影响玩游戏者的兴趣。因为飞行射击游戏说白了就是碰撞的游戏——躲避敌人的子弹或飞机,同时用自己的子弹去碰撞敌人。
碰撞,这很简单嘛,只要两个物体的中心点距离小于它们的半径之和就可以了。确实,而且我也看到很多人是这样做的,但是,这只适合圆形的物体——圆形的半径处处相等。如果我们要碰撞的物体是两艘威力巨大的太空飞船,它是三角形或矩形或其他的什么形状,就会出现让人尴尬的情景:两艘飞船眼看就要擦肩而过,却出人意料的发生了爆炸;或者敌人的子弹穿透了你的飞船的右弦,你却安然无恙,这不是我们希望发生的。于是,我们需要一种精确的检测方法。
那么,怎样才能达到我们的要求呢?其实我们的前辈们已经总结了许多这方面的经验,如上所述的半径检测法,三维中的标准平台方程法,边界框法等等。大多数游戏程序员都喜欢用边界框法,这也是我采用的方法。边界框是在编程中加进去的不可见的边界。边界框法,顾名思义,就是用边界框来检测物体是否发生了碰撞,如果两个物体的边界框相互干扰,则发生了碰撞。用什么样的边界框要视不同情况而定,用最近似的几何形状。当然,你可以用物体的准确几何形状作边界框,但出于效率的考虑,我不赞成这样做,因为游戏中的物体一般都很复杂,用复杂的边界框将增加大量的计算,尤其是浮点计算,而这正是我们想尽量避免的。但边界框也不能与准确几何形状有太大的出入,否则就象用半径法一样出现奇怪的现象。
在飞行射击游戏中,我们的飞机大多都是三角形的,我们可以用三角形作近似的边界框。现在我们假设飞机是一个正三角形(或等要三角形,我想如果谁把飞机设计成左右不对称的怪物,那他的审美观一定有问题),我的飞机是正着的、向上飞的三角形,敌人的飞机是倒着的、向下飞的三角形,且飞机不会旋转(大部分游戏中都是这样的)。我们可以这样定义飞机:中心点O(Xo,Yo),三个顶点P0(X0,Y0)、P1(X1,Y1)、P2(X2,Y2)。中心点为正三角形的中心点,即中心点到三个顶点的距离相等。接下来的问题是怎样确定两个三角形互相干扰了呢?嗯,现在我们接触到问题的实质了。如果你学过平面解析几何,我相信你可以想出许多方法解决这个问题。判断一个三角形的各个顶点是否在另一个三角形里面,看起来是个不错的方法,你可以这样做,但我却发现一个小问题:一个三角形的顶点没有在另一个三角形的里面,却可能发生了碰撞,因为另一个三角形的顶点在这个三角形的里面,所以要判断两次,这很麻烦。有没有一次判断就可以的方法?我们把三角形放到极坐标平面中,中心点为原点,水平线即X轴为零度角。我们发现三角形成了这个样子:在每个角度我们都可以找到一个距离,用以描述三角形的边。既然我们找到了边到中心点的距离,那就可以用这个距离来检测碰撞。如图一,两个三角形中心点坐标分别为(Xo,Yo)和 (Xo1,Yo1),由这两个点的坐标求出两点的距离及两点连线和X轴的夹角θ,再由θ求出中心点连线与三角形边的交点到中心点的距离,用这个距离与两中心点距离比较,从而判断两三角形是否碰撞。因为三角形左右对称,所以θ取-90~90度区间就可以了。哈,现在问题有趣多了,-90~90度区间正是正切函数的定义域,求出θ之后再找对应的边到中心点的距离就容易多了,利用几何知识,如图二,将三角形的边分为三部分,即图2中红绿蓝三部分,根据θ在那一部分而分别对待。用正弦定理求出边到中心点的距离,即图2中浅绿色线段的长度。但是,如果飞机每次移动都这样判断一次,效率仍然很低。我们可以结合半径法来解决,先用半径法判断是否可能发生碰撞,如果可能发生碰撞,再用上面的方法精确判断是不是真的发生了碰撞,这样基本就可以了。如果飞机旋转了怎么办呢,例如,如图三所示飞机旋转了一个角度α,仔细观察图三会发现,用(θ-α)就可以求出边到中心点的距离,这时你要注意边界情况,即(θ-α)可能大于90度或小于-90度。啰罗嗦嗦说了这么多,不知道大家明白了没有。我编写了一个简单的例程,用于说明我的意图。在例子中假设所有飞机的大小都一样,并且没有旋转。
/////////////////////////////////////////////////////////////////////
//example.cpp
//碰撞检测演示
//作者 李韬
/////////////////////////////////////////////////////////////////////
//限于篇幅,这里只给出了碰撞检测的函数
//define/////////////////////////////////////////////////////////////
#define NUM_VERTICES 3
#define ang_30 -0.5236
#define ang60 1.0472
#define ang120 2.0944
//deftype////////////////////////////////////////////////////////////
struct object
{
float xo, yo;
float radio;
float x_vel, y_vel;
float vertices[NUM_VERTICES][2];
}
//faction/////////////////////////////////////////////////////////////
//根据角度求距离
float AngToDis(struct object obj, float angle)
{
float dis, R;
R = obj.radius;
if (angle <= ang_30)
dis = R / (2 * sin(-angle));
else if (angle >= 0)
dis = R / (2 * sin(angle + ang60));
else dis = R / (2 * sin(ang120 - angle));
return dis;
}
//碰撞检测
int CheckHit(struct object obj1, struct object obj2)
{
float deltaX, deltaY, angle, distance, bumpdis;
deltaX = abs(obj1.xo - obj2.xo);
deltaY = obj1.yo - obj2.yo;
distance = sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance <= obj.radio)
{
angle = atan2(deltaY, deltaX);
bumpdis1 = AngToDis(obj1, angle);
return (distance <= 2 * bumpdis);
}
ruturn 0;
}
//End//////////////////////////////////////////////////////////////
上面程序只是用于演示,并不适合放在游戏中,但你应该明白它的意思,以便写出适合你自己的碰撞检测。游戏中的情况是多种多样的,没有哪种方法能适应所有情况,你一定能根据自己的情况找到最适合自己的方法。
游戏算法整理 算法六:关于SLG中人物可到达范围计算的想法
下面的没有经过实践,因此很可能是错误的,觉得有用的初学朋友读一读吧:)
希望高人指点一二 :)
简介:
在标准的SLG游戏中,当在一个人物处按下鼠标时,会以人物为中心,向四周生成一个菱形的可移动区范围,如下:
0
000
00s00
000
0
这个图形在刚开始学习PASCAL时就应该写过一个画图的程序(是否有人怀念?)。那个图形和SLG的扩展路径一样。
一、如何生成路径:
从人物所在的位置开始,向四周的四个方向扩展,之后的点再进行扩展。即从人物所在的位置从近到远进行扩展(类似广宽优先)。
二、扩展时会遇到的问题:
1、当扩展到一个点时,人物的移动力没有了。
2、当扩展的时候遇到了一个障碍点。
3、当扩展的时候这个结点出了地图。
4、扩展的时候遇到了一个人物正好站在这个点(与2同?)。
5、扩展的点已经被扩展过了。当扩展节点的时候,每个节点都是向四周扩展,因此会产生重复的节点。
当遇到这些问题的时候,我们就不对这些节点处理了。在程序中使用ALLPATH[]数组记录下每一个等扩展的节点,不处理这些问题节点的意思就是不把它们加入到ALLPATH[]数组中。我们如何去扩展一个结点周围的四个结点,使用这个结点的坐标加上一个偏移量就可以了,方向如下:
3
0 2
1
偏移量定义如下:
int offx[4] = { -1, 0, 1, 0 };
int offy[4] = { 0, 1, 0, -1 };
扩展一个节点的相邻的四个节点的坐标为:
for(int i=0; i<4; i )
{
temp.x = temp1.x offx[i];
temp.y = temp1.y offy[i];
}
三、关于地图的结构:
1、地图的二维坐标,用于确定每个图块在地图中的位置。
2、SLG中还要引入一个变量decrease表示人物经过这个图块后他的移动力的减少值。例如,一个人物现在的移动力为CurMP=5,与之相领的图块的decrease=2;这时,如果人物移动到这里,那它的移动力变成CurMP-decrease。
3、Flag域:宽度优先中好像都有这个变量,有了它,每一个点保证只被扩展一次。防止一个点被扩展多次。(一个点只被扩展一次真的能得到正确的结果吗?)
4、一个地图上的图块是否可以通过,我们使用了一个Block代表。1---不可以通过;0---可以通过。
这样,我们可以定义一个简单的地图结构数组了:
#define MAP_MAX_WIDTH 50
#define MAP_MAX_HEIGHT 50
typedef struct tagTILE{
int x,y,decrease,flag,block;
}TILE,*LPTILE;
TILE pMap[MAP_MAX_WIDTH][MAP_MAX_HEIGHT];
以上是顺序数组,是否使用动态的分配更好些?毕竟不能事先知道一个地图的宽、高。
四、关于路径:
SLG游戏中的扩展路径是一片区域(以人物为中心向四周扩展,当然,当人物移动时路径只有一个)。这些扩展的路径必须要存储起来,所有要有一个好的结构。我定义了一个结构,不是很好:
typedef struct tagNODE{
int x,y; //扩展路径中的一个点在地图中的坐标。
int curmp; //人物到了这个点以后的当前的移动力。
}NODE,*LPNODE;
上面的结构是定义扩展路径中的一个点的结构。扩展路径是点的集合,因此用如下的数组进行定义:
NODE AllPath[PATH_MAX_LENGTH];
其中的PATH_MAX_LENGTH代表扩展路径的点的个数,我们不知道这个扩展的路径中包含多少个点,因此定义一个大一点的数字使这个数组不会产生溢出:
#define PATH_MAX_LENGTH 200
上面的这个数组很有用处,以后的扩展就靠它来实现,它应该带有两个变量nodecount 代表当前的数组中有多少个点。当然,数组中的点分成两大部分,一部分是已经扩展的结点,存放在数组的前面;另一部分是等扩展的节点,放在数组的后面为什么会出现已扩展节点和待扩展节点?如下例子:
当前的人物坐标为x,y;移动力为mp。将它存放到AllPath数组中,这时的起始节点为等扩展的节点。这时我们扩展它的四个方向,对于合法的节点(如没有出地图,也没有障碍......),我们将它们存放入AllPath数组中,这时的新加入的节点(起始节点的子节点)就是等扩展结点,而起始节点就成了已扩展节点了。下一次再扩展节点的时候,我们不能再扩展起始节点,因为它是已经扩展的节点了。我们只扩展那几个新加入的节点(待扩展节点),之后的情况以此类推。那么我们如何知道哪些是已经扩展的结点,哪些是等扩展的节点?我们使用另一个变量cutflag,在这个变量所代表的下标以前的结点是已扩展节点,在它及它之后是待扩展结点。
五、下面是基本框架(只扩展一个人物的可达范围):
int nodecount = 0; //AllPath数组中的点的个数(包含待扩展节点和已经扩展的节点
int cutflag = 0; //用于划分已经扩展的节点和待扩展节点
NODE temp; //路径中的一个点(临时)
temp.x = pRole[cur] - >x; //假设有一个关于人物的类,代表当前的人物
temp.y = pRole[cur] - >y;
temp.curmp = pRole[cur] - >MP; //人物的最大MP
AllPath[nodecount] = temp; //起始点入AllPath,此时的起始点为等扩展的节点
while (curflag < nodecount) { //数组中还有待扩展的节点
int n = nodecount; //记录下当前的数组节点的个数。
for (int i = cutflag; i < nodecount; i) { //遍历待扩展节点
for (int j = 0; j < 4; j) { //向待扩展节点的四周各走一步
//取得相邻点的数据
temp.x = AllPath[i].x offx[j];
temp.y = AllPath[i].y offy[j];
temp.curmp = AllPath[i].curmp -
pMap[AllPath[i].x][AllPath[i].y].decrease;
//以下为检测是否为问题点的过程,如果是问题点,不加入AllPath数组,继续处理其它的点
if (pMap[temp.x][temp.y].block) {
continue; //有障碍,处理下一个节点
}
if (temp.curmp < 0) {
continue; //没有移动力了
}
if (temp.x < 0 || temp.x >= MAP_MAX_WIDTH || temp.y < 0 ||
temp.y >= MAP_MAX_HEIGHT) {
continue; //出了地图的范围
}
if (pMap[temp.x][temp.y].flag) {
continue; //已经扩展了的结点
}
//经过了上面几层的检测,没有问题的节点过滤出来,可以加入AllPath
AllPath[nodecount] = temp;
}
pMap[AllPath[i].x][AllPath[i].y].flag = 1; //将已经扩展的节点标记为已扩展节点
}
cutflag = n; //将已扩展节点和待扩展节点的分界线下标值移动到新的分界线
}
for (int i = 0; i < nodecount; i) {
pMap[AllPath[i].x][AllPath[i].y].bFlag = 0; //标记为已扩展节点的标记设回为待扩展节点。
}
游戏算法整理 算法七 无限大地图的实现
这已经不是什么新鲜的东西了,不过现在实在想不到什么好写,而且版面上又异常冷清,我再不说几句就想要倒闭了一样。只好暂且拿这个东西来凑数吧。
无限大的地图,听上去非常吸引人。本来人生活的空间就是十分广阔的,人在这么广阔的空间里活动才有一种自由的感觉。游戏中的虚拟世界由于受到计算机存储空间的限制,要真实地反映这个无限的空间是不可能的。而对这个限制最大的,就是内存的容量了。所以在游戏的空间里,我们一般只能在一个狭小的范围里活动,在一般的RPG中,从一个场景走到另一个场景,即使两个地方是紧紧相连的,也要有一个场景的切换过程,一般的表现就是画面的淡入淡出。
这样的场景切换给人一种不连续的感觉(我不知道可不可以把这种称作“蒙太奇”:o)),从城内走到城外还有情可缘,因为有道城墙嘛,但是两个地方明明没有界限,却偏偏在这一边看不到另外一边,就有点不现实了。当然这并不是毛病,一直以来的RPG都是遵循这个原则,我们(至少是我)已经习惯了这种走路的方式。我在这里说的仅仅是另外一种看起来更自然一点的走路方式,仅此而已。
当然要把整个城市的地图一下子装进内存,现在的确是不现实的,每一次只能放一部分,那么应该怎么放才是我们要讨论的问题。
我们在以前提到Tile方法构造地图时就谈到过Tile的好处之一就是节省内存,这里仍然可以借鉴Tile的思想。我们把整个大地图分成几块,把每一块称作一个区域,在同一时间里,内存中只保存相邻的四块区域。这里每个区域的划分都有一定的要求:每个区域大小应该相等这是一定的了,不然判断当前屏幕在哪个区域中就成了一个非常令人挠头的事;另外每个区域的大小都要大于屏幕的大小,也只有这样才能保证屏幕(就是图中那块半透明的蓝色矩形)在地图上荡来荡去的时候,最多同时只能覆盖四个区域(象左图中所表示的),内存里也只要保存四个区域就足够了;还有一点要注意的,就是地图上的建筑物(也包括树啦,大石头啦什么的)必须在一个区域内,这样也是为了画起来方便,当然墙壁——就是那种连续的围墙可以除外,因为墙壁本来就是一段一段拼起来的。
我们在程序中可以设定4个指针来分别指向这4个区域,当每次主角移动时,就判断当前滚动的屏幕是否移出了这四个区域,如果移出了这四个区域,那么就废弃两个(或三个)已经在目前的四个相邻区域中被滚出去的区域(说得很别扭,各位见谅),读入两个(或三个)新滚进来的区域,并重新组织指针。这里并不涉及内存区域的拷贝。
这样的区域划分方法刚好适合我们以前提到的Tile排列方法,只要每个区域横向Tile的个数是个偶数就行了,这样相邻的两个区域拼接起来刚好严丝合缝,而且每个区域块的结构完全一致,没有那些需要重复保存的Tile(这个我想我不需要再画图说明了,大家自己随便画个草图就看得出来了)。在文件中的保存方法就是按一个个区域分别保存,这样在读取区域数据时就可以直接作为一整块读入,也简化了程序。另外还有个细节就是,我们的整个地图可能不是一个规则的矩形,可能有些地方是无法达到的,如右图所示,背景是黑色的部分代表人物不能达到的地方。那么在整个地图中,这一部分区域(在图中蓝色的3号区域)就可以省略,表现在文件存储上就是实际上不存储这一部分区域,这样可以节省下不少存储空间。对于这种地图可以用一个稀疏矩阵来存储,大家也可以发挥自己的才智用其他对于编程来说更方便的形式来存储地图。
这就是对无限大地图实现的一种方法,欢迎大家提出更好的方法。也希望整个版面能够活跃一点。
|
天是09年1月1日,一个全新的开始,我要珍惜当下每一分一秒!让当下每个呼吸都是崭新的!
新的一年,我希望自已对人生、对生命,能够有一个全新的认识。谢谢陈爷爷前几天送我的那
套《康熙起居注》,最近也越来越认识到,要多读书,读好书的重要性,能够天天在家读书实
在也是一种很大的幸福,我要珍惜!乾隆皇帝十九岁就写下了《读书以明理为先》的文章,说
明读书对明理、对做人的重要性,立身以至诚为本,读书以明理为先!今年还有一个心愿就是
用小楷临摹一遍康熙皇帝抄写的<金刚经>,也终于明白了其实写字这个过程本身也是在训练一
种心境,所以写字是写的一种心境,而不在与字的美丑。一个有着强大心力的人,才可能真正
意义的永无不胜,学佛学道,无论学什么,其实最大的敌人就是自已认为的那颗狂燥不安的心,
黑暗中总有惺惺相惜的敌人!纯静朴素的大道,无时无刻都存在于我们身边,上达于天,下入于
地,化育万物。道法自然,或许真正获得了心灵上的自由,才能达到至人的境界:游于物之所不
得遁而皆存。遵循自然法则因缘和合,才是顺天行事,缘份就像一针一眼,谁也逃不了,如果这
辈子真有一个能把名和利都看的很淡的人,并且愿意和我过一种很简单的生活,我一定要让他成
为这世上第二幸福的人,因为最幸福的人是我!我要跟他一辈子不离不弃,看日出看日落,看北
斗星看流星雨,直到老!09年,让我牵着庄子的手,在轮回的战场中,做个勇敢的战士!
pku3233:Given a n × n matrix A and a positive integer k, find the sum S = A + A2 + A3 + … + Ak.
分析:矩阵相乘O(n^3), 有k次,则复杂度为n^3*k。
使用矩阵技巧,构造:
B= | A A |
| O I |
则B的乘方的结果其右上会是S,其他三个不变。此时化成了矩阵乘方问题,此时可以使用反复平方法,这样复杂度为(2n)^3*logk
反复平方法,迭代版的, 以整数a^m为例:
递归的可以不用变量Z,要简单些,但是要注意了递归的调用顺序和结果的存储。
/**//*Problem: 1509 User: Uriel
Memory: 144K Time: 16MS
Language: C Result: Accepted*/
#include<stdio.h>
#include<string.h>
int min(int a, int b)
{
return a <= b ? a : b;
}
int MinimumRepresentation(char *s, int l)
{
int i = 0, j = 1, k = 0, t;
while (i < l && j < l && k < l)
{
t = s[(i + k)%l] - s[(j + k)%l];
if (!t) ++ k;
else
{
if (t > 0) i = i + k + 1;
else j = j + k + 1;
if (i == j) ++j;
k = 0;
}
}
return min(i,j);
}
int x,len,i,t;
char str[10010];
int main()
{
scanf("%d",&t);
getchar();
while(t--)
{
memset(str,0x00,sizeof(str));
scanf("%s",str);
len=strlen(str);
x=MinimumRepresentation(str,len);
printf("%d\n",x+1);
}
return 0;
}
//串的同构是,在若干次循环位移后可以变成相同
static boolean isIsomorphism(String s1, String s2)
{
char[] u = (s1+s1).toCharArray();
char[] w = (s2+s2).toCharArray();
int i = 0;
int j = 0;
int len = s1.length();
while(i < u.length && j < w.length)
{
int k = 0;
while((i+k) < u.length && (j+k)<u.length && u[i+k] == w[j+k])k++;//&& k < len
System.out.println(k);
if(k >= len) return true;
if(u[i+k] > w[j+k])i = i+k+1;
else j = j+k+1;
}
return false;
}
在这篇文章里,我们从信息论的角度证明了,基于比较的排序算法需要的比较次数(在最坏情况下)至少为log2(n!),而log(n!)=Θ(nlogn),这给出了比较排序的一个下界。但那里我们讨论的只是最理想的情况。一个事件本身所含的信息量是有大小之分的。看到这篇文章之后,我的思路突然开阔了不少:信息论是非常强大的,它并不只是一个用来分析理论最优决策的工具。从信息论的角度来分析算法效率是一件很有趣的事,它给我们分析排序算法带来了一种新的思路。
假如你手里有一枚硬币。你希望通过抛掷硬币的方法来决定今天晚上干什么,正面上网反面看电影。投掷硬币所产生的结果将给你带来一些“信息”,这些信息的多少就叫做“信息量”。如果这个硬币是“公正”的,正面和反面出现的概率一样,那么投掷硬币后不管结果咋样,你都获得了1 bit的信息量。如果你事先就已经知道这个硬币并不是均匀的,比如出现正面的概率本来就要大得多,这时我们就说事件结果的不确定性比刚才更小。如果投掷出来你发现硬币果然是正面朝上,这时你得到的信息量就相对更小(小于1 bit);反之如果投掷出来居然反面朝上了,那你就得到了一个相对较大的信息量(大于1 bit)。但平均下来,我们得到的信息量是小于1 bit的,因为前者发生的可能性毕竟要大一些。最极端的情况就是,这是一枚被捣了鬼的魔术硬币,你怎么投都是正面。此时,你投了硬币等于没投,反正结果都是正面朝上,你得到的信息量永远为0。
这个理论是很符合生活实际的。昨天晚上我出去吃饭时,坐在我后面的那个人是男的还是女的?这种问题就比较有价值,因为大家都猜不到答案究竟是什么;但要问我昨天跟谁一起出去上自习去了,问题的答案所含的信息量就变小了,因为大家都知道如果我破天荒地跑去自习了的话多半是有MM陪着一起去的。如果有网友问我是男的还是女的,那就更不可思议了,因为我不但多次在这个Blog里提到我一直想找一个合适的MM,还在AboutMe里面发了我的照片。如果某人刚操完一个MM,突然扭过头去问“对了,你是男的还是女的呀”,那这个人绝对是一个不折不扣的大傻B,因为这个问题所能带来的信息量几乎为0。
总之,当每种结果出现的概率都相等,事件的不确定性达到最大,其结果最难预测时,事件的发生将会给我们带来最大的信息量。我们把一个事件的不确定程度叫做“熵”,熵越大表明这个事件的结果越难以预测,同时事件的发生将给我们带来越多的信息。如果在排序算法里每次比较的熵都是最大的,理论上来说这种(基于比较的)排序算法就应当是最优的。但我们一会儿将看到,我们已知的排序算法总是不完美的,每种算法都会或多或少地存在一些价值明显不大的比较。
首先我们来看三种经典的平方复杂度算法。它们的效率并不高,原因就在于算法过程中会出现越来越多概率严重不均的比较。随着冒泡排序的进行,整个序列将变得越来越有序,位置颠倒的泡泡将越来越少;选择排序的每一趟选择中,你都会不断得到越来越大的数,同时在以后的比较中找到更大的数的概率也越来越低;在插入排序中,你总是把新的数与已经排好的数按从大到小的顺序依次进行比较,可以想到新的数一开始就比前面所有的数中最大的那个还大的概率是相当小的。受此启发,我们可以很自然地想到一个插入排序的改进:处理一个新的数时,为何不一开始就与前面处理过的数中的中位数进行比较?这种比较的熵显然更大,能获取的信息量要大得多,明显更有价值一些。这就是插入排序的二分查找改进。
下面我们再来看一看几种O(nlogn)的排序算法。在快速排序算法中,比较的信息熵不会因为排序算法的进行而渐渐减小,这就是快速排序比上面几个排序算法更优秀的根本原因。仔细回顾快速排序算法的过程,我们立即看出,每次比较的两种结果出现的概率完全由这一趟划分过程所选择的基准关键字决定:选择的基准关键字刚好是当前处理的数字集合的中位数,则比较结果的不确定性达到最大;如果选择的基准关键字过大或过小,都会出现比较产生的结果不均等的情况,这使得每次比较平均带来的信息量大大减少。因此,快速排序算法是很看人品的:如果基准选的好,算法完全有可能达到理论上的最优;如果基准选的不好,复杂度很容易退化到O(n^2)。
堆排序所需要的比较次数更多,因为在堆的删除操作中有一种明显不平衡的比较。在删除操作中,我们把根节点用整个堆的最末一个节点来代替,然后不断下沉直到它的儿子都比它大。判断它的两个儿子是否比它大,其信息熵是相当小的,因为这个节点本身就来自堆的底部,除非这个节点已经沉到很底下了,否则儿子比它大的概率是很小的。因此,我们想到了一个堆排序的优化:反正堆建好了以后不需要再插入新元素了,为何不舍弃堆的完全二叉树性质?我们可以直接把根元素改成无穷大,让它沉到底,不用再考虑儿子比它大的问题了,也不再顾及堆的形状。这样的话,堆排序是否就完美了呢?仔细想想你会发现,改进之后的比较操作仍然是不对称的。这种不对称主要来自两个方面:左子树和右子树的节点个数不同,以及被删除的根节点原先是来自左子树还是右子树。比方说,根节点原本就是从右子树提上来的,现在删除了根节点后,左子树的最小值比右子树的最小值更小的概率就偏大一些;此时万一右子树节点本来就比左边少,这样的话这个比较的熵就更小了。
最后看一下归并排序。在有序队列的合并操作中,绝大多数情况下的比较操作都是比较平衡的。左边一半中的最小值和右边一半中的最小值进行比较,结果显然是等概率的。当然,随后将发生其中一边的最小值与另一边的次小值进行比较,这时的比较操作略微有了一些不平衡,并存在较小的可能使得比较操作变得更加不平衡(最小值与第三小的值相比)。有趣的是,比较越是不平衡,重新归于平衡的概率就越大,就好像归并排序中的信息熵会自动调整一样。这就是归并排序比平方复杂度的排序算法效率更高的原因。当然,完全有可能出现这样的情况:右边的数奇小无比,左边的最小值比右边的所有值都大。结果最后右边的队列都处理完了左边还没开始取数,此时合并操作提前结束,所花费的比较次数出人意料地少。从信息熵的角度来看,这种“比较提前结束”的现象是非常自然的:这种情况毕竟是“出人意料”的,事实越出人意料,获得的信息量就越大,因此算法就提前结束了。但这种情况毕竟是相当罕见的,平均情况下每次比较的信息量仍然不足1 bit。
最后,为什么线性排序的算法可以达到O(n)的复杂度?这是因为,线性排序算法并不是基于比较的。一次比较事件(假设没有相等的情况)所能产生的信息量最多1 bit,而一次Hash分类可以获得的信息量远远超过了1 bit,因为它可以一次确定出n种等概率的可能情况。
Matrix67原创,转贴请注明出处~~
传说中效率最高的最大流算法(Dinic)
呵呵,又从DK那偷代码了,好兴奋哈,以下是这个算法的简单介绍,不过我用它去解决HDU的1532 竟然TLE,郁闷.到时候再继续问问DK吧...so 烦躁.
哈哈 终于经过大牛的指点 原来本算法是从0开始标号的......
Dinic是个很神奇的网络流算法。它是一个基于“层次图”的时间效率优先的最大流算法。
层次图是什么东西呢?层次,其实就是从源点走到那个点的最短路径长度。于是乎,我们得到一个定理:从源点开始,在层次图中沿着边不管怎么走,经过的路径一定是终点在剩余图中的最短路。(摘自WC2007王欣上论文)注意,这里是要按照层次走。
那么,MPLA(最短路径增值)的一大堆复杂的证明我就略掉了,有兴趣的请自行参阅WC2007王欣上神牛的论文。
首先我们得知道,Dinic的基本算法步骤是,先算出剩余图,然后用剩余图算层次图,然后在层次图里找增广路。不知道你想到没有,这个层次图找增广路的方法,恰恰就是Ford-Fulkerson类算法的时间耗费最大的地方,就是找一个最短的增广路。所以呢,层次图就相当于是一个已经预处理好的增广路标志图。
如何实现Dinic呢?
首先我们必然要判一下有没有能到达终点的路径(判存在增广路与否),在这个过程中我们顺便就把层次图给算出来了(当然不用算完),然后就沿着层次图一层一层地找增广路;找到一条就进行增广(注意在沿着层次图找增广路的时候使用栈的结构,把路径压进栈);增广完了继续找,找不到退栈,然后继续找有没有与这个结点相连的下一层结点,直到栈空。如果用递归实现,这个东西就很好办了,不过我下面提供的程序是用了模拟栈,当然这样就不存在结点数过多爆栈的问题了……不过写起来也麻烦了一些,对于“继续找”这个过程我专门开了一个数组存当前搜索的指针。
上面拉拉杂杂说了一大堆,实际上在我的理解中,层次图就是一个流从高往低走的过程(这玩意儿有点像预流推进的标号法……我觉得),在一条从高往低的路径中,自然有些地方会有分叉;这就是Dinic模拟栈中退栈的精华。这就把BFS的多次搜索给省略了不说,时间效率比所谓的理论复杂度要高得多。
这里有必要说到一点,网络流的时间复杂度都是很悲观的,一般情况下绝对没有可能到达那个复杂度的。
#include<iostream>
using namespace std;
const long maxn=300;
const long maxm=300000;
const long inf=0x7fffffff;
struct node
{
long v,next;
long val;
}s[maxm*2];
long level[maxn],p[maxn],que[maxn],out[maxn],ind;
void init()
{
ind=0;
memset(p,-1,sizeof(p));
}
inline void insert(long x,long y,long z)
{
s[ind].v=y;
s[ind].val=z;
s[ind].next=p[x];
p[x]=ind++;
s[ind].v=x;
s[ind].val=0;
s[ind].next=p[y];
p[y]=ind++;
}
inline void insert2(long x,long y,long z)
{
s[ind].v=y;
s[ind].val=z;
s[ind].next=p[x];
p[x]=ind++;
s[ind].v=x;
s[ind].val=z;
s[ind].next=p[y];
p[y]=ind++;
}
long max_flow(long n,long source,long sink)
{
long ret=0;
long h=0,r=0;
while(1)
{
long i;
for(i=0;i<n;++i)
level[i]=0;
h=0,r=0;
level[source]=1;
que[0]=source;
while(h<=r)
{
long t=que[h++];
for(i=p[t];i!=-1;i=s[i].next)
{
if(s[i].val&&level[s[i].v]==0)
{
level[s[i].v]=level[t]+1;
que[++r]=s[i].v;
}
}
}
if(level[sink]==0)break;
for(i=0;i<n;++i)out[i]=p[i];
long q=-1;
while(1)
{
if(q<0)
{
long cur=out[source];
for(;cur!=-1;cur=s[cur].next)
{
if(s[cur].val&&out[s[cur].v]!=-1&&level[s[cur].v]==2)
{
break;
}
}
if(cur>=0)
{
que[++q]=cur;
out[source]=s[cur].next;
}
else
{
break;
}
}
long u=s[que[q]].v;
if(u==sink)
{
long dd=inf;
long index=-1;
for(i=0;i<=q;i++)
{
if(dd>s[que[i]].val)
{
dd=s[que[i]].val;
index=i;
}
}
ret+=dd;
//cout<<ret<<endl;
for(i=0;i<=q;i++)
{
s[que[i]].val-=dd;
s[que[i]^1].val+=dd;
}
for(i=0;i<=q;i++)
{
if(s[que[i]].val==0)
{
q=index-1;
break;
}
}
}
else
{
long cur=out[u];
for(;cur!=-1;cur=s[cur].next)
{
if(s[cur].val&&out[s[cur].v]!=-1&&level[u]+1==level[s[cur].v])
{
break;
}
}
if(cur!=-1)
{
que[++q]=cur;
out[u]=s[cur].next;
}
else
{
out[u]=-1;
q--;
}
}
}
}
return ret;
}
long m,n;
int main()
{
while(scanf("%ld %ld",&m,&n)!=EOF)
{
init();
for(int i=0;i<n;i++)
{
long from,to,cost;
scanf("%ld %ld %ld",&from,&to,&cost);
insert(--from,--to,cost);
}
long Start,End;
scanf("%ld %ld",&Start,&End);
printf("%ld\n",max_flow(n,--Start,--End));
}
return 0;
}
摘要: 最短路径 之 SPFA算法 (转载)(2009-05-06 20:41:51)
var $tag='spfa,杂谈';
var $tag_code='0c0816ca8a11d99e776ffbef47dd2fd0';
标签:spfa 杂谈
... 阅读全文
#include <stdio.h>
int add(int x,int y) {return x+y;}
int sub(int x,int y) {return x-y;}
int mul(int x,int y) {return x*y;}
int div(int x,int y) {return x/y;}
int (*func[])()={add,sub,mul,div};
int num,curch;
char chtbl[]="+-*/()=";
char corch[]="+-*/()=0123456789";
int getach() {
int i;
while(1) {
curch=getchar();
if(curch==EOF) return -1;
for(i=0;corch[i]&&curch!=corch[i];i++);
if(i<strlen(corch)) break;
}
return curch;
}
int getid() {
int i;
if(curch>='0'&&curch<='9') {
for(num=0;curch>='0'&&curch<='9';getach()) num=10*num+curch-'0';
return -1;
}
else {
for(i=0;chtbl[i];i++) if(chtbl[i]==curch) break;
if(i<=5) getach();
return i;
}
}
int cal() {
int x1,x2,x3,op1,op2,i;
i=getid();
if(i==4) x1=cal(); else x1=num;
op1=getid();
if(op1>=5) return x1;
i=getid();
if(i==4) x2=cal(); else x2=num;
op2=getid();
while(op2<=4) {
i=getid();
if(i==4) x3=cal(); else x3=num;
if((op1/2==0)&&(op2/2==1)) x2=(*func[op2])(x2,x3);
else {
x1=(*func[op1])(x1,x2);
x2=x3;
op1=op2;
}
op2=getid();
}
return (*func[op1])(x1,x2);
}
void main(void) {
int value;
printf("Please input an expression:\n");
getach();
while(curch!='=') {
value=cal();
printf("The result is:%d\n",value);
printf("Please input an expression:\n");
getach();
}
}
(一)简单的函数指针的应用。
//形式1:返回类型(*函数名)(参数表)
char (*pFun)(int);
char glFun(int a){ return;}
void main()
{
pFun = glFun;
(*pFun)(2);
}
第一行定义了一个指针变量pFun。首先我们根据前面提到的“形式1”认识到它是一个指向某种函数的指针,这种函数参数是一个int型,返回值是char类型。只有第一句我们还无法使用这个指针,因为我们还未对它进行赋值。
第二行定义了一个函数glFun()。该函数正好是一个以int为参数返回char的函数。我们要从指针的层次上理解函数——函数的函数名实际上就是一个指针,函数名指向该函数的代码在内存中的首地址。
然后就是可爱的main()函数了,它的第一句您应该看得懂了——它将函数glFun的地址赋值给变量pFun。main()函数的第二句中“*pFun”显然是取pFun所指向地址的内容,当然也就是取出了函数glFun()的内容,然后给定参数为2。
(二)使用typedef更直观更方便。
//形式2:typedef 返回类型(*新类型)(参数表)
typedef char (*PTRFUN)(int);
PTRFUN pFun;
char glFun(int a){ return;}
void main()
{
pFun = glFun;
(*pFun)(2);
}
typedef的功能是定义新的类型。第一句就是定义了一种PTRFUN的类型,并定义这种类型为指向某种函数的指针,这种函数以一个int为参数并返回char类型。后面就可以像使用int,char一样使用PTRFUN了。
第二行的代码便使用这个新类型定义了变量pFun,此时就可以像使用形式1一样使用这个变量了。
(三)在C++类中使用函数指针。
//形式3:typedef 返回类型(类名::*新类型)(参数表)
class CA
{
public:
char lcFun(int a){ return; }
};
CA ca;
typedef char (CA::*PTRFUN)(int);
PTRFUN pFun;
void main()
{
pFun = CA::lcFun;
ca.(*pFun)(2);
}
在这里,指针的定义与使用都加上了“类限制”或“对象”,用来指明指针指向的函数是那个类的这里的类对象也可以是使用new得到的。比如:
CA *pca = new CA;
pca->(*pFun)(2);
delete pca;
而且这个类对象指针可以是类内部成员变量,你甚至可以使用this指针。比如:
类CA有成员变量PTRFUN m_pfun;
void CA::lcFun2()
{
(this->*m_pFun)(2);
}
一句话,使用类成员函数指针必须有“->*”或“.*”的调用。
作者:csumck 更新日期:2004-11-07
来源:CSDN 浏览次数:
系统的可靠度计算公式 收藏
并联:1-(1-p1)(1-p2)
串联:p1p2
p1,p2分别为部件1和部件2的可靠度.
---------------------------------------------------------------------------
eg:
某计算机系统的可靠性结构是如下图所示的双重串并联结构,若所构成系统的每个部件的可靠度为0.9 ,即R=0.9 ,则系统的可靠度为()?
|---(R)————(R)---|
———| |--
|---(R)----(R)---|
类似于串两个电阻,在并两个电阻的图。问怎样计算?
最佳答案
串联的可靠度P1=R1×R1 =0.81
并联起来时可靠度P2=1-(1-P1)×(1-P1)=0.9639
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zwhfyy/archive/2009/04/02/4042513.aspx
摘要: 背包问题
1.引子
我们人类是一种贪婪的动物,如果给您一个容量一定的背包和一些大小不一的物品,裝到背包里面的物品就归您,遇到这种好事大家一定不会错过,用力塞不一定是最好的办法,用脑子才行,下面就教您如何解决这样的问题,以获得更多的奖品。
2.应用场景
在一个物品向量中找到一个子集满足条件如下 :
1)这个子集加起来的体积大小不能... 阅读全文
在今年的信息学冬令营上,陈启峰提出了一个自己创造的BST数据结构—Size Balanced Tree。这个平衡二叉树被全世界内的许多网站所讨论,大家讨论的主题也只有一个—SBT能够取代Treap吗?本文详细介绍SBT树的性质,以及一些常用的操作,最后证明SBT是一颗高度平衡的二分查找树。
一. 介绍
众所周知,BST能够快速的实现查找等动态操作。但是在某些情况下,比如将一个有序的序列依次插入到BST中,则BST会退化成为一条链,效率非常之低。由此引申出来很多平衡BST,比如AVL树,红黑树,treap树等。这些数据结构都是通过引入其他一些性质来保证BST的高度在最坏的情况下都保持在O(log n)。其中,AVL树和红黑树的很多操作都非常麻烦,因此实际应用不是很多。而treap树加入了一些随机化堆的性质,实际应用效果非常好,实现起来很简单,一直以来受到很多人的青睐。本文介绍一种新的平衡BST树,实现起来也是非常之简单,并且能够支持更多的操作,实际评测效率跟treap也不差上下。
在介绍SBT之前,先介绍一下BST以及在BST上的旋转操作。
1. Binary Search Tree
BST是一种高级的数据结构,它支持很多动态操作,包括查找,求最小值,最大值,前驱,后继,插入和删除,能够用于字典以及优先队列。
BST是一棵二叉树,每个结点最多有2个儿子。每个结点都有个键值,并且键值必须满足下面的条件:
如果x是BST中的一个结点。那么x的键值不小于其左儿子的键值,并且不大于其右儿子的键值。
对于每个结点t,用left[t]和right[t]分别来存放它的两个儿子,ket[t]存放该结点的键值。另外,在SBT中,要增加s[t],用来保存以t为根的子树中结点的个数。
2. 旋转
为了保证BST的平衡(不会退化成为一条链),通常通过旋转操作来改变BST的结构。旋转操作不会影响binary-search-tree的性质!
2.1右旋操作的伪代码
右旋操作必须保证左儿子存在
Right-Rotate(t)
k←left[t]
left[t]←right[k]
right[k]←t
s[k]←s[t]
s[t]←s[left[t]]+s[right[t]]+1
t←k
2.2 左旋操作的伪代码
左旋操作必须保证右儿子存在
Left-Rotate(t)
k←right[t]
right[t]←left[k]
left[k]←t
s[k]←s[t]
s[t]←s[left[t]]+s[right[t]]+1
t←k
二.Size Balanced Tree
Size Balanced Tree(简称SBT)是一种平衡二叉搜索树,它通过子树的大小s[t]来维持平衡性质。它支持很多动态操作,并且都能够在O(log n)的时间内完成。
Insert(t,v)
|
将键值为v的结点插入到根为t的树中
|
Delete(t,v)
|
在根为t的树中删除键值为v的结点
|
Find(t,v)
|
在根为t的树中查找键值为v的结点
|
Rank(t,v)
|
返回根为t的树中键值v的排名。也就是树中键值比v小的结点数+1
|
Select(t,k)
|
返回根为t的树中排名为k的结点。同时该操作能够实现Get-min,Get-max,因为Get-min等于Select(t,1),Get-max等于Select(t,s[t])
|
Pred(t,v)
|
返回根为t的树中比v小的最大的键值
|
Succ(t,v)
|
返回根为t的树中比v大的最小的键值
|
SBT树中的每个结点都有left,right,key以及前面提到的size域。SBT能够保持平衡性质是因为其必须满足下面两个条件:
对于SBT中的每个结点t,有性质(a)(b):
(a). s[right[t]]≥s[left[left[t]]],s[right[left[t]]]
(b). s[left[t]]≥s[right[right[t]]],s[left[right[t]]]
即在上图中,有s[A],s[B]≤s[R]&s[C],s[D] ≤s[L]
三. Maintain
假设我们要在BST中插入一个键值为v的结点,一般是用下面这个过程:
Simple-Insert(t,v)
If t=0 then
t←NEW-NODE(v)
Else
s[t]←s[t]+1
If v<key[t] then
Simple-Insert(left[t],v)
Else
Simple-Insert(right[t],v)
执行完操作Simple-Insert后,SBT的性质(a)和(b)就有可能不满足了,这是我们就需要修复(Maintain)SBT。
Maintain(t)用来修复根为t的SBT,使其满足SBT性质。由于性质(a)和(b)是对称的,下面仅讨论对性质(a)的修复。
Case 1:s[left[left[t]]]>s[right[t]]
这种情况下可以执行下面的操作来修复SBT
执行Right-Rotate(T)
有可能旋转后的树仍然不是SBT,需要再次执行Maintain(T)
由于L的右儿子发生了变化,因此需要执行Maintain(L)
Case 2:s[right[left[t]]]>s[right[t]]
这种情况如下图所示:
需要执行一下步骤来修复SBT:
执行Left-Rotate(L)。如下图所示
执行Right-Rotate(T)。如下图所示
当执行完(1)(2)后,树的结构变得不可预测了。但是幸运的是,在上图中,A,E,F,R子树仍然是SBT。因此我们可以执行Maintain(L)和Maintain(T)来修复B的子树。
Case 3:
这种情况和case 1是对称的
Case 4:
这种情况和case 2是对称的
Maintain操作的伪代码:
在Maintain过程中,用一个变量flag来避免额外的检查。当flag为false时,代表case 1和case 2需要被检查,否则case 3和case 4需要被检查。
Maintain (t,flag)
If flag=false then
If s[left[left[t]]>s[right[t]] then
Right-Rotate(t)
Elseif s[right[left[t]]>s[right[t]] then
Left-Rotate(left[t])
Right-Rotate(t)
Else exit
Elseif s[right[right[t]]>s[left[t]] then
Left-Rotate(t)
Elseif s[left[right[t]]>s[left[t]] then
Right-Rotate(right[t])
Left-Rotate(t)
Else exit
Maintain(left[t],false)
Maintain(right[t],true)
Maintain(t,false)
Maintain(t,true)
四.常用操作
插入操作
SBT和插入操作和BST的基本相同,只是在插入之后需要执行下Maintain操作。
Insert (t,v)
If t=0 then
t←NEW-NODE(v)
Else
s[t] ←s[t]+1
If v<key[t] then
Simple-Insert(left[t],v)
Else
Simple-Insert(right[t],v)
Maintain(t,v≥key[t])
删除操作
如果没有找到要删除的结点,那么就删除最后一个访问的结点并记录。
Delete (t,v)
If s[t]≤2 then
record←key[t]
t←left[t]+right[t]
Exit
s[t] ←s[t]-1
If v=key[t] then
Delete(left[t],v[t]+1)
Key[t] ←record
Maintain(t,true)
Else
If v<key[t] then
Delete(left[t],v)
Else
Delete(right[t],v)
Maintain(t,v<key[t])
另外,由于SBT的平衡性质是靠size域来维护的,而size域本身(子树所含节点个数)对于很多查询算法都特别有用,这样使得查询集合里面的譬如第n小的元素,以及一个元素在集合中的排名等操作都异常简单,并且时间复杂度都稳定在O(log n)。下面仅介绍下上表提到的select(t,k)操作和rank(t,v)操作。
由于SBT的性质(结点t的关键字比其左子树中所有结点的关键字都大,比其左子树中所有的关键字都小),理解下面的算法非常容易。
3.Select操作
Select(t,k)
If k=s[left[t]]+1 then
return key[t]
If k<=s[left[t]] then
return Select(left[t],k)
Else
return Select(right[t],k-1-s[left[t]])
4.Rank操作
Rank(t,v)
If t=0 then
return 1
If v<=key[t] then
return rank(left[t],v)
Else
return s[left[t]]+1+rank(right[t],v)
同样,求前驱结点的操作Pred和后继结点的操作都很容易通过size域来实现。
五.相关证明分析
显然Maintain操作是一个递归过程,可能你会怀疑它是否会结束。下面我们可以证明Maintain操作的平摊时间复杂度为O(1)。
1.关于树的高度的分析
设f[h]表示高度为h的SBT中结点数目的最小值,则有
1 (h=0)
f[h]= 2 (h=1)
f[h-1]+f[h-2]+1 (h>1)
a.证明:
(1) 很明显f[0]=1,f[1]=2。
(2) 首先,对于任意h>1,我们假设t是一颗高度为h的SBT的根结点,则这颗SBT包含一颗高度为h-1的子树。不妨假设t的左子树的高度为h-1,根据f[h]的定义,有
s[left[t] ]≥f[h-1],同样的,左子树中有一颗高度为h-2的子树,换句话说,左子树中含有一颗结点数至少为f[h-2]的子树。由SBT的性质(b),可知s[right[t]] ≥f[h-2]。因此我们有s[t]=s[left[t]]+s[right[t]]+1≥f[h-1]+f[h-2]+1。
另外一方面,我们可以构造一颗高度为h,并且结点数正好为f[h]的SBT,称这样的SBT为tree[t]。可以这样来构造tree[h]:
含有一个结点的SBT (h=0)
tree[h]= 含有2个结点的任意SBT (h=1)
左子树为tree[h-1],右子树为tree[h-2]的SBT (h>1)
由f[h]的定义可知f[h] ≤f[h-1]+f[h-2]+1(h>1)。因此f[h]的上下界都为f[h-1]+f[h-2]+1,因此有f[h]=f[h-1]+f[h-2]+1。
b.最坏情况下的高度
事实上f[h]是一个指数函数,通过f[h]的递推可以计算出通项公式。
定理:
含有n个结点的SBT在最坏情况下的高度是满足f[h] ≤n的最大的h值。
假设maxh为含有n个结点的SBT的最坏情况下的高度。由上面的定理,有
于是很明显SBT的高度为O(logn),是一颗高度平衡的BST!
2.对Maintain操作的分析
通过前面的计算分析我们能够很容易分析出Maintain操作是非常高效的。
首先,有一个非常重要的值来评价一颗BST的好坏:所有结点的平均深度。它是通过所有结点的深度之和SD除以结点个数n计算出来的。一般来说,这个值越小,这颗BST就越好。由于对于一颗BST来说,结点数n是一个常数,因此我们期望SD值越小越好。
现在我们集中来看SBT的SD值,它的重要性在于能够制约Maintain操作的执行时间。回顾先前提到的BST中的旋转操作,有个重要的性质就是:每次执行旋转操作后,SD值总是递减的!
由于SBT树的高度总是O(log n),因此SD值也总是保持在O(log n)。并且SD仅在插入一个结点到SBT后才增加,因此(T是Maintain操作中执行旋转的次数)
Maintain操作的次数等于T加上不需要旋转操作的Maintain操作的次数。由于后者为O(nlogn)+O(T),因此Maintain的平摊分析时间复杂度为:
对各个操作时间复杂度的分析
现在我们知道了SBT的高度为O(log n),并且 Maintain操作的平摊分析时间复杂度为O(1),因此对于所有的常用操作,时间复杂度都稳定在O(log n)!
摘要: 目前最快的数独求解程序 - 实现了Knuth的Dancing Links+Algorithm X算法
C++语言: 目前最快的数独求解程序 - 实现了Knuth的Dancing Links+Algorithm X算法
//from: http://code.google.com/p/klsudoku/source/checkout
//半瓶墨水修改于 2009 Sept 18
//R... 阅读全文
最大公约数和最小公倍数
语言: C, 标签: 无 2008/07/22发布 5个月前更新 更新记录
作者: 半瓶墨水, 点击5221次, 评论(0), 收藏者(0), , 打分: 登录以后才能打分, 目前平均0.0分,总分0, 共有0个用户参与打分
# 以下描述来自: http://baike.baidu.com/view/47637.htm
#
# 最大公约数(greatest common divisor,简写为gcd;
# 指某几个整数共有公约数中的最大一个
# 例: 在2、4、6中,2就是2,4,6的最大公约数。
#
# 重要性质:
# gcd(a,b)=gcd(b,a) (交换律)
# gcd(-a,b)=gcd(a,b)
# gcd(a,a)=|a|
# gcd(a,0)=|a|
# gcd(a,1)=1
# gcd(a,b)=gcd(b, a mod b)
# gcd(a,b)=gcd(b, a-b)
# 如果有附加的一个自然数m,
# 则: gcd(ma,mb)=m * gcd(a,b) (分配率)
# gcd(a+mb ,b)=gcd(a,b)
# 如果m是a和b的最大公约数,
# 则: gcd(a/m ,b/m)=gcd(a,b)/m
# 在乘法函数中有:
# gcd(ab,m)=gcd(a,m) * gcd(b,m)
# 两个整数的最大公约数主要有两种寻找方法:
# * 两数各分解质因子,然后取出同样有的项乘起来
# * 辗转相除法(扩展版)
# 和最小公倍数(lcm)的关系:
# gcd(a, b) * lcm(a, b) = ab
# a与b有最大公约数,但不一定有最小公倍数。
# 两个整数的最大公因子可用于计算两数的最小公倍数,或分数化简成最简分数。
# 两个整数的最大公因子和最小公倍数中存在分配律:
# * gcd(a, lcm(b, c)) = lcm(gcd(a, b), gcd(a, c))
# * lcm(a, gcd(b, c)) = gcd(lcm(a, b), lcm(a, c))
# 在坐标里,将点(0, 0)和(a, b)连起来,通过整数坐标的点的数目(除了(0, 0)一点之外)就是gcd(a, b)。
#
#
# 以下代码来自: http://bbs.bccn.net/thread-224663-1-1.html
#
int GCD(int a, int b)
{
if(b == 0) return a;
else return GCD(b, a % b);
}
int LCM(int a, int b)
{
return a * b / GCD(a,b);
}
/*以下代码来自:http://en.wikipedia.org/wiki/Binary_GCD_algorithm */
unsigned int gcd(unsigned int u, unsigned int v)
{
int shift;
/* GCD(0,x) := x */
if (u == 0 || v == 0)
return u | v;
/* Let shift := lg K, where K is the greatest power of 2
dividing both u and v. */
for (shift = 0; ((u | v) & 1) == 0; ++shift) {
u >>= 1;
v >>= 1;
}
while ((u & 1) == 0)
u >>= 1;
/* From here on, u is always odd. */
do {
while ((v & 1) == 0) /* Loop X */
v >>= 1;
/* Now u and v are both odd, so diff(u, v) is even.
Let u = min(u, v), v = diff(u, v)/2. */
if (u < v) {
v -= u;
} else {
unsigned int diff = u - v;
u = v;
v = diff;
}
v >>= 1;
} while (v != 0);
return u << shift;
}
摘要:
1package dwq.algo.sort;
2
3import java.util.Arrays;
4
5public class Sorting
6{
7
... 阅读全文
摘要: package com.dwq.algo;
import java.util.ArrayList;
public class LongestIncrementSubarray
{
public static void main(String[] arg... 阅读全文
召集)你能想到的最奇妙的算法题是什么?
http://www.matrix67.com/blog/archives/1850
DLX
http://sqybi.com/works/dlxcn/
OI最后的谢幕·18岁新的开始http://blog.sina.com.cn/s/blog_4a443fd701000bko.html
转]怎样做人
1、不要推卸责任,哪怕是别人的责任。无论发生任何事情,首先想到自己是不是做错了。如果自己没错(那是不可能的),那就站在对方的角度上,体验一下对方的感受。(本人将此点放在第一条是提醒自己永远都要带着责任心去做事)
2、要让自己适应环境,而不是让环境来适应你。哪怕这是一个非常痛苦的过程。新到一个地方不要急于融入到其中的哪一个圈子中去,等到了足够的时间和考验,属于你的圈子自然就会接纳你。(本人十几年跳到过的地方多不胜数,这是一条最宝贵的原则)
3、大方一点,不会大方就学大方一点。如果大方让你很心痛,你就装大方一点。(不怕大家笑话,我最大方)
4、低调一点,再低调一点,永远低调一点(要比临时工还要低调一点,可能在别人的眼光中你还不如一个新来的临时工呢,本人还没完全做的到)。
5、嘴甜且不吝惜自己的喝彩声,要会夸人,好的夸奖让人觉得很舒服,但不要过份让人反感。(呵呵,这点我就不太行了,不过还可以)
6、如果你觉得最近工作顺利的不得了,那你就要更加小心了。(顺境思危,本人自信做的还行吧
7、礼貌对待人,打招呼的时候要看着对方的眼睛。永远记着自己就是一个不者不扣的小字辈。(做人起码的原则)
8、言多必失,少说多做,人多的场合少说话。(本人吃的亏太多了,这个原则是用教训换来的)
9、不要把别人的好,当做理所当然,要知道感恩图报。(中国人的优秀传统不要忘记了)
10、手高眼低,要有平常心。(没有什么大不了的,好事呀往坏处想,坏事要往好处想,塞翁失马,祸福难测啊)
11、遵守时间,但不要期待别人同样遵守时间。(对自己永远严格要求不会错)
12、信守诺言,但不要轻易许诺,更不要把别人的对你的承诺记在心里并信以为真。(本人提醒大家就算要承诺也要承诺永远做不到的,呵呵)
13、不要向同事借钱,如果借了那就要准时还;不要借钱给同事,如果不得不借,就当作是送给他的好了。(呵呵,别把金钱看的太重,不过没钱万万不能)
14、如果你带领一个团队,在总结工作时要把错误揽在自己的身上,把功劳都记在下属的头上。当上司和下属同时在场的时候你要记得及时表扬你的下属。(批评人的时候一定要在只有你们两个人的情况下才能进行,保持团队的凝聚力最重要)
15、不要在一个同事面前不要说另外一个同事的坏话,要坚持说人的好话,别担心这好话传不到对方的耳中。如果有人在你面前说其他人的坏话,你要保持正常的微笑,不参与评论。(流言止于己,祸从口出是至理名言)
16、避免与同事公开对立,包括公开提出反对意见,激烈的更不可取。(两虎相争,必有一伤,坚持具备平衡的做人处事能力就会自然化解反对意见)
17、经常帮助别人,但是不要让对方觉得是你理所当然应该做的。(好心有时候不会有好结果,但不能因此而灰心,天长地久见人心,一句话:苦心人,天不误!)
18、说实在话会让你倒足八辈子的霉。(本人吃的亏就是一种财富,这是必须坚持的原则)
19、做事先做人,对事不对人;对事无情,同时对人要有情。(公平、公正、公开)
20、经常检查自己是不是又骄傲了,又自负了,又看不起别人了。(一个人再有天大的本事,如果没有别人的合作和帮助都是白搭)
21、忍耐是人生一辈子要修炼的一门功课,要用一辈子的时间去学。(张家名言:张公百忍,另有“百忍堂”为证)
22、尽量不要和同事发生有什么办公室恋情,如果实在避免不了的话,那就在办公室避免任何形式的接触,包括眼神。(兔子不吃窝边草,烦恼总是从身边开始的)
23、待上以敬,待下以宽。(要会拍上司的马屁,这是和上司沟通的重要途径之一,但千万不要弄脏了手)
24、资历非常重要,不要和老家伙们耍心眼斗法,否则你会死的很难看。(中国的社会传统,不会有错)
|
最长递增子序列的求法 LIS (转)
什么是最长递增子序列呢?
问题描述如下:
设L=<a1,a2,…,an>是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=<aK1,ak2,…,akm>,其中k1<k2<…<km且aK1<ak2<…<akm。求最大的m值。
对于这个问题有以下几种解决思路:
1、把a1,a2,...,an排序,假设得到a'1,a'2,...,a'n,然后求a的a'的最长公共子串,这样总的时间复杂度为o(nlg(n))+o(n^2)=o(n^2);
2、动态规划的思路:
另设一辅助数组b,定义b[n]表示以a[n]结尾的最长递增子序列的长度,则状态转移方程如下:b[k]=max(max(b[j]|a[j]<a[k],j<k)+1,1);
这个状态转移方程解释如下:在a[k]前面找到满足a[j]<a[k]的最大b[j],然后把a[k]接在它的后面,可得到a[k]的最长递增子序列的长度,或者a[k]前面没有比它小的a[j],那么这时a[k]自成一序列,长度为1.最后整个数列的最长递增子序列即为max(b[k] | 0<=k<=n-1);
实现代码如下:
#include <iostream>
using namespace std;
int main()
{
int i,j,n,a[100],b[100],max;
while(cin>>n)
{
for(i=0;i<n;i++)
cin>>a[i];
b[0]=1;//初始化,以a[0]结尾的最长递增子序列长度为1
for(i=1;i<n;i++)
{
b[i]=1;//b[i]最小值为1
for(j=0;j<i;j++)
if(a[i]>a[j]&&b[j]+1>b[i])
b[i]=b[j]+1;
}
for(max=i=0;i<n;i++)//求出整个数列的最长递增子序列的长度
if(b[i]>max)
max=b[i];
cout<<max<<endl;
}
return 0;
}
显然,这种方法的时间复杂度仍为o(n^2);
3、对第二种思路的改进:
第二种思路在状态转移时的复杂度为o(n),即在找a[k]前面满足a[j]<a[k]的最大b[j]时采用的是顺序查找的方法,复杂度为o(n).
设想如果能把顺序查找改为折半查找,则状态转移时的复杂度为o(lg(n)),这个问题的总的复杂度就可以降到nlg(n).
另定义一数组c,c中元素满足c[b[k]]=a[k],解释一下,即当递增子序列的长度为b[k]时子序列的末尾元素为c[b[k]]=a[k].
先给出这种思路的代码,然后再对其做出解释。
#include <iostream>
using namespace std;
int find(int *a,int len,int n)//若返回值为x,则a[x]>=n>a[x-1]
{
int left=0,right=len,mid=(left+right)/2;
while(left<=right)
{
if(n>a[mid]) left=mid+1;
else if(n<a[mid]) right=mid-1;
else return mid;
mid=(left+right)/2;
}
return left;
}
void fill(int *a,int n)
{
for(int i=0;i<=n;i++)
a[i]=1000;
}
int main()
{
int max,i,j,n,a[100],b[100],c[100];
while(cin>>n)
{
fill(c,n+1);
for(i=0;i<n;i++)
cin>>a[i];
c[0]=-1;// …………………………………………1
c[1]=a[0];// ……………………………………2
b[0]=1;// …………………………………………3
for(i=1;i<n;i++)// ………………………………4
{
j=find(c,n+1,a[i]);// ……………………5
c[j]=a[i];// ………………………………6
b[i]=j;//……………………………………7
}
for(max=i=0;i<n;i++)//………………………………8
if(b[i]>max)
max=b[i];
cout<<max<<endl;
}
return 0;
}
对于这段程序,我们可以用算法导论上的loop invariants来帮助理解.
loop invariant: 1、每次循环结束后c都是单调递增的。(这一性质决定了可以用二分查找)
2、每次循环后,c[i]总是保存长度为i的递增子序列的最末的元素,若长度为i的递增子序
列有多个,刚保存末尾元素最小的那个.(这一性质决定是第3条性质成立的前提)
3、每次循环完后,b[i]总是保存以a[i]结尾的最长递增子序列。
initialization: 1、进入循环之前,c[0]=-1,c[1]=a[0],c的其他元素均为1000,c是单调递增的;
2、进入循环之前,c[1]=a[0],保存了长度为1时的递增序列的最末的元素,且此时长度为1
的递增了序列只有一个,c[1]也是最小的;
3、进入循环之前,b[0]=1,此时以a[0]结尾的最长递增子序列的长度为1.
maintenance: 1、若在第n次循环之前c是单调递增的,则第n次循环时,c的值只在第6行发生变化,而由
c进入循环前单调递增及find函数的性质可知(见find的注释),
此时c[j+1]>c[j]>=a[i]>c[j-1],所以把c[j]的值更新为a[i]后,c[j+1]>c[j]>c[j-1]的性质仍然成
立,即c仍然是单调递增的;
2、循环中,c的值只在第6行发生变化,由c[j]>=a[i]可知,c[j]更新为a[i]后,c[j]的值只会变
小不会变大,因为进入循环前c[j]的值是最小的,则循环中把c[j]更新为更小的a[i],当
然此时c[j]的值仍是最小的;
3、循环中,b[i]的值在第7行发生了变化,因为有loop invariant的性质2,find函数返回值
为j有:c[j-1]<a[i]<=c[j],这说明c[j-1]是小于a[i]的,且以c[j-1]结尾的递增子序列有最大的
长度,即为j-1,把a[i]接在c[j-1]后可得到以a[i]结尾的最长递增子序列,长度为(j-1)+1=j;
termination: 循环完后,i=n-1,b[0],b[1],...,b[n-1]的值均已求出,即以a[0],a[1],...,a[n-1]结尾的最长递
增子序列的长度均已求出,再通过第8行的循环,即求出了整个数组的最长递增子序列。
仔细分析上面的代码可以发现,每次循环结束后,假设已经求出c[1],c[2],c[3],...,c[len]的值,则此时最长递增子序列的长度为len,因此可以把上面的代码更加简化,即可以不需要数组b来辅助存储,第8行的循环也可以省略。
#include <iostream>
using namespace std;
int find(int *a,int len,int n)//修改后的二分查找,若返回值为x,则a[x]>=n
{
int left=0,right=len,mid=(left+right)/2;
while(left<=right)
{
if(n>a[mid]) left=mid+1;
else if(n<a[mid]) right=mid-1;
else return mid;
mid=(left+right)/2;
}
return left;
}
int main()
{
int n,a[100],b[100],c[100],i,j,len;//新开一变量len,用来储存每次循环结束后c中已经求出值的元素的最大下标
while(cin>>n)
{
for(i=0;i<n;i++)
cin>>a[i];
b[0]=1;
c[0]=-1;
c[1]=a[0];
len=1;//此时只有c[1]求出来,最长递增子序列的长度为1.
for(i=1;i<n;i++)
{
j=find(c,len,a[i]);
c[j]=a[i];
if(j>len)//要更新len,另外补充一点:由二分查找可知j只可能比len大1
len=j;//更新len
}
cout<<len<<endl;
}
return 0;
}
|
最长递增部分序列 Longest Ordered Subsequence Extention hoj10027 poj2533
2007-08-21 20:19
求最长递增部分序列是一个比较常见的动态规划题。在导弹拦截等题中都有用到。一般来说就是用经典的O(n^2)的动态规划算法。
算法如下:
设A[i]表示序列中的第i个数,F[i]表示从1到i这一段中以i结尾的最长上升子序列的长度,初始时设F[i] = 0(i = 1, 2, ..., len(A))。则有动态规划方程:F[i] = max{1, F[j] + 1} (j = 1, 2, ..., i - 1, 且A[j] < A[i])。
然而在hoj10027中n的值达到了50000。显而易见经典算法是会超时滴。所以只有另谋出路了。
用一个变量len记录到目前为止所找出来的最长递增序列的长度。另外准备一个数组b[],用这个数组表示长度为j的递增序列中最后一个元素的值。在这里长度为j的递增序列不止一个,我们所要保存是那个最小的。为什么呢?因为最后一个元素越小,那么这个递增序列在往后被延长的机会越大。初始化b[0] = -1;len = 0;从第一个元素a[1]开始 a[i]( 1 <= i <= n)。如果这个元素比len长的序列的最大值大。则把这个元素直接添加到b数组的后面。如果这个元素比b数组的第一个元素还要小则把这个元素赋给b数组的第一个值。否则进行二分查找。当在b数组里面找到一个数比a[i]小,并且他的后面的数大于或等于a[i]则跳出。将a[i]添加到这个数的后面。输出len就可以了。
代码如下:
#include <stdio.h>
#include <string.h>
int main()
{
int a[50001], b[50001];
int i, j, l, r, len, n, mid;
while (scanf("%d", &n) != EOF)
{
for (i = 0; i < n; i++)
scanf("%d", &a[i]);
len = 0;
memset(b, 0, sizeof(int) * 50001);
b[0] = -1;
for (i = 0; i < n; i++)
{
if (a[i] > b[len])
b[++len] = a[i];
else if (a[i] < b[1] )
b[1] = a[i];
else
{
l = 1; r = len;
while (l <= r)
{
mid = (l + r)>>1;
if (a[i] > b[mid] && a[i] <= b[mid + 1])
{
j = mid;
break;
}
if (b[mid] > a[i])
{
r = mid - 1;
}
else
{
j = mid;
l = mid + 1;
}
}
b[j + 1] = a[i];
}
}
printf("%d\n", len);
}
return 0;
|
Java把内存划分成两种:一种是栈内存,一种是堆内存。
在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。
当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。
堆内存用来存放由new创建的对象和数组。
在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。
在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。
引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。
具体的说:
栈与堆都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。
Java的堆是一个运行时数据区,类的(对象从中分配空间。这些对象通过new、newarray、anewarray和multianewarray等 指令建立,它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时 动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。
栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本 类型的变量(,int, short, long, byte, float, double, boolean, char)和对象句柄。
栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义:
int a = 3;
int b = 3;
编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没找到,就将3存放进来,然后将a指向3。接着处理int b = 3;在创建完b的引用变量后,因为在栈中已经有3这个值,便将b直接指向3。这样,就出现了a与b同时均指向3的情况。这时,如果再令a=4;那么编译器 会重新搜索栈中是否有4值,如果没有,则将4存放进来,并令a指向4;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。要注意这 种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为这种情况a的修改并不会影响到b, 它是由编译器完成的,它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。
String是一个特殊的包装类数据。可以用:
String str = new String("abc");
String str = "abc";
两种的形式来创建,第一种是用new()来新建对象的,它会在存放于堆中。每调用一次就会创建一个新的对象。
而第二种是先在栈中创建一个对String类的对象引用变量str,然后查找栈中有没有存放"abc",如果没有,则将"abc"存放进栈,并令str指向“abc”,如果已经有“abc” 则直接令str指向“abc”。
比较类里面的数值是否相等时,用equals()方法;当测试两个包装类的引用是否指向同一个对象时,用==,下面用例子说明上面的理论。
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true可以看出str1和str2是指向同一个对象的。
String str1 =new String ("abc");
String str2 =new String ("abc");
System.out.println(str1==str2); // false用new的方式是生成不同的对象。每一次生成一个。
因此用第二种方式创建多个“abc”字符串,在内存中其实只存在一个对象而已. 这种写法有利与节省内存空间. 同时它可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str = new String("abc");的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。
另一方面, 要注意: 我们在使用诸如String str = "abc";的格式定义类时,总是想当然地认为,创建了String类的对象str。担心陷阱!对象可能并没有被创建!而可能只是指向一个先前已经创建的 对象。只有通过new()方法才能保证每次都创建一个新的对象。 由于String类的immutable性质,当String变量需要经常变换其值时,应该考虑使用StringBuffer类,以提高程序效率。
java中内存分配策略及堆和栈的比较
2.1 内存分配策略按照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的,栈式的,和堆式的.静态存储分配是指在编译时就能确定每个数据目标在运行时刻的存储空间需求,因而在编译时就可以给他们分配固定的内存空间.这种分配策略要求程序代码中不允 许有可变数据结构(比如可变数组)的存在,也不允许有嵌套或者递归的结构出现,因为它们都会导致编译程序无法计算准确的存储空间需求.栈式存储分配也可称为动态存储分配,是由一个类似于堆栈的运行栈来实现的.和静态存储分配相反,在栈式存储方案中,程序对数据区的需求在编译时是完全未知 的,只有到运行的时候才能够知道,但是规定在运行中进入一个程序模块时,必须知道该程序模块所需的数据区大小才能够为其分配内存.和我们在数据结构所熟知 的栈一样,栈式存储分配按照先进后出的原则进行分配。
静态存储分配要求在编译时能知道所有变量的存储要求,栈式存储分配要求在过程的入口处必须知道所有的存储要求,而堆式存储分配则专门负责在编译时或运行时 模块入口处都无法确定存储要求的数据结构的内存分配,比如可变长度串和对象实例.堆由大片的可利用块或空闲块组成,堆中的内存可以按照任意顺序分配和释 放.
2.2 堆和栈的比较
上面的定义从编译原理的教材中总结而来,除静态存储分配之外,都显得很呆板和难以理解,下面撇开静态存储分配,集中比较堆和栈:从堆和栈的功能和作用来通俗的比较,堆主要用来存放对象的,栈主要是用来执行程序的.而这种不同又主要是由于堆和栈的特点决定的:在编程中,例如C/C++中,所有的方法调用都是通过栈来进行的,所有的局部变量,形式参数都是从栈中分配内存空间的。实际上也不是什么分配,只是从栈顶 向上用就行,就好像工厂中的传送带(conveyor belt)一样,Stack Pointer会自动指引你到放东西的位置,你所要做的只是把东西放下来就行.退出函数的时候,修改栈指针就可以把栈中的内容销毁.这样的模式速度最快, 当然要用来运行程序了.需要注意的是,在分配的时候,比如为一个即将要调用的程序模块分配数据区时,应事先知道这个数据区的大小,也就说是虽然分配是在程 序运行时进行的,但是分配的大小多少是确定的,不变的,而这个"大小多少"是在编译时确定的,不是在运行时.堆是应用程序在运行的时候请求操作系统分配给自己内存,由于从操作系统管理的内存分配,所以在分配和销毁时都要占用时间,因此用堆的效率非常低.但是堆的 优点在于,编译器不必知道要从堆里分配多少存储空间,也不必知道存储的数据要在堆里停留多长的时间,因此,用堆保存数据时会得到更大的灵活性。事实上,面 向对象的多态性,堆内存分配是必不可少的,因为多态变量所需的存储空间只有在运行时创建了对象之后才能确定.在C++中,要求创建一个对象时,只需用 new命令编制相关的代码即可。执行这些代码时,会在堆里自动进行数据的保存.当然,为达到这种灵活性,必然会付出一定的代价:在堆里分配存储空间时会花 掉更长的时间!这也正是导致我们刚才所说的效率低的原因,看来列宁同志说的好,人的优点往往也是人的缺点,人的缺点往往也是人的优点.
2.3 JVM中的堆和栈JVM是基于堆栈的虚拟机.JVM为每个新创建的线程都分配一个堆栈.也就是说,对于一个Java程序来说,它的运行就是通过对堆栈的操作来完成的。堆栈以帧为单位保存线程的状态。JVM对堆栈只进行两种操作:以帧为单位的压栈和出栈操作。
我们知道,某个线程正在执行的方法称为此线程的当前方法.我们可能不知道,当前方法使用的帧称为当前帧。当线程激活一个Java方法,JVM就会在线程的 Java堆栈里新压入一个帧。这个帧自然成为了当前帧.在此方法执行期间,这个帧将用来保存参数,局部变量,中间计算过程和其他数据.这个帧在这里和编译 原理中的活动纪录的概念是差不多的.从Java的这种分配机制来看,堆栈又可以这样理解:堆栈(Stack)是操作系统在建立某个进程时或者线程(在支持多线程的操作系统中是线程)为这个线程建立的存储区域,该区域具有先进后出的特性。
每一个Java应用都唯一对应一个JVM实例,每一个实例唯一对应一个堆。应用程序在运行中所创建的所有类实例或数组都放在这个堆中,并由应用所有的线程 共享.跟C/C++不同,Java中分配堆内存是自动初始化的。Java中所有对象的存储空间都是在堆中分配的,但是这个对象的引用却是在堆栈中分配,也 就是说在建立一个对象时从两个地方都分配内存,在堆中分配的内存实际建立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的指针(引用)而已。
在《编程珠玑》中有详细的讨论。主要出于性能方向改进。
- 二分法很简单吧 ,但要想 一次写对 也不容易吧 ,更何况他的一些扩展应用呢 ,我这里扩展了四种,<P> </P><P>基础知识 还是牢靠的好</P><P> </P>
二分法很简单吧 ,但要想 一次写对 也不容易吧 ,更何况他的一些扩展应用呢 ,我这里扩展了四种,
基础知识 还是牢靠的好
-
-
-
-
-
-
- public class BinarySearch {
-
-
-
-
- public static int b1(int[] array, int v) {
- int left = 0;
- int right = array.length - 1;
- while (left <= right) {
- int middle = (left + right) / 2;
- if (array[middle] == v) return middle;
- if (array[middle] > v)
- right = middle - 1;
- else
- left = middle + 1;
- }
-
- return -1;
-
- }
-
-
-
-
- public static int b2(int[] array, int v) {
- int left = 0;
- int right = array.length - 1;
- while (left < right) {
- int middle = (left + right + 1) / 2;
- if (array[middle] > v)
- right = middle - 1;
- else
- left = middle;
- }
-
- if (array[left] == v)
- return left;
-
- return -1;
-
- }
-
-
-
-
-
- public static int b3(int[] array, int v) {
- int left = 0;
- int right = array.length - 1;
- while (left < right) {
- int middle = (left + right) / 2;
- if (array[middle] < v)
- left = middle + 1;
- else
- right = middle;
- }
-
- if (array[right] == v)
- return right;
-
- return -1;
-
- }
-
-
-
-
-
-
- public static int b4(int[] array, int v, int flag) {
- int left = 0;
- int right = array.length - 1;
- while (left < right) {
- int middle = (left + right) / 2;
- if (array[middle] < v)
- left = middle + 1;
- else
- right = middle;
- }
-
-
- if (array[right] == v)
- return right;
- System.out.println(right - 1 + " -- " + left);
- return -1;
-
- }
-
-
- public static void main(String[] args) {
-
- int[] array = new int[]{1, 2, 3, 4, 10, 16, 16, 16, 16, 16, 16, 18, 110};
-
-
- System.out.println(b1(array, 16));
- System.out.println(b2(array, 16));
- System.out.println(b3(array, 16));
- System.out.println(b4(array, 6, 1));
-
-
- }
- }
/**
* Author: yiminghe
* Date: 2008-10-13
* Time: 23:50:48
* Any problem ,contact yiminghe@fudan.edu.cn.
*/
public class BinarySearch {
//返回中间一个数
//12345666689
// 6 不确定返回哪个6
public static int b1(int[] array, int v) {
int left = 0;
int right = array.length - 1;
while (left <= right) {
int middle = (left + right) / 2;
if (array[middle] == v) return middle;
if (array[middle] > v)
right = middle - 1;
else
left = middle + 1;
}
return -1;
}
//返回重复元素的最后一个数
//123456667
//最后一个6位置返回
public static int b2(int[] array, int v) {
int left = 0;
int right = array.length - 1;
while (left < right) {
int middle = (left + right + 1) / 2;
if (array[middle] > v)
right = middle - 1;
else
left = middle;
}
if (array[left] == v)
return left;
return -1;
}
//返回重复元素的最前一个数
//123456667
//最前一个6位置返回
public static int b3(int[] array, int v) {
int left = 0;
int right = array.length - 1;
while (left < right) {
int middle = (left + right) / 2;
if (array[middle] < v)
left = middle + 1;
else
right = middle;
}
if (array[right] == v)
return right;
return -1;
}
//返回重复元素的最前一个数
//1234566689
//最前一个6位置返回 ,若找不到,显示 比他小的离它最大位置,比它小的离它最小位置
//如 找 7 ,则 输出 最后一个6的位置 和 8 的位置
public static int b4(int[] array, int v, int flag) {
int left = 0;
int right = array.length - 1;
while (left < right) {
int middle = (left + right) / 2;
if (array[middle] < v)
left = middle + 1;
else
right = middle;
}
if (array[right] == v)
return right;
System.out.println(right - 1 + " -- " + left);
return -1;
}
public static void main(String[] args) {
// 0, 1, 2, 3 4 5 6 7
int[] array = new int[]{1, 2, 3, 4, 10, 16, 16, 16, 16, 16, 16, 18, 110};
//array = new int[]{0, 6};
//array = new int[]{6, 7};
System.out.println(b1(array, 16));
System.out.println(b2(array, 16));
System.out.println(b3(array, 16));
System.out.println(b4(array, 6, 1));
}
}
Java AIO初探(异步网络IO)
按照《Unix网络编程》的划分,IO模型可以分为:阻塞IO、非阻塞IO、IO复用、信号驱动IO和异步IO,按照POSIX标准来划分只分为两类:同步IO和异步IO.如何区分呢?首先一个IO操作其实分成了两个步骤:发起IO请求和实际的IO操作,同步IO和异步IO的区别就在于第二个步骤是否阻塞,如果实际的IO读写阻塞请求进程,那么就是同步IO,因此阻塞IO、非阻塞IO、IO服用、信号驱动IO都是同步IO,如果不阻塞,而是操作系统帮你做完IO操作再将结果返回给你,那么就是异步IO.阻塞IO和非阻塞IO的区别在于第一步,发起IO请求是否会被阻塞,如果阻塞直到完成那么就是传统的阻塞IO,如果不阻塞,那么就是非阻塞IO.
Java nio 2.0的主要改进就是引入了异步IO(包括文件和网络),这里主要介绍下异步网络IO API的使用以及框架的设计,以TCP服务端为例。首先看下为了支持AIO引入的新的类和接口:
java.nio.channels.AsynchronousChannel标记一个channel支持异步IO操作。
java.nio.channels.AsynchronousServerSocketChannel ServerSocket的aio版本,创建TCP服务端,绑定地址,监听端口等。
java.nio.channels.AsynchronousSocketChannel面向流的异步socket channel,表示一个连接。
java.nio.channels.AsynchronousChannelGroup异步channel的分组管理,目的是为了资源共享。一个AsynchronousChannelGroup绑定一个线程池,这个线程池执行两个任务:处理IO事件和派发CompletionHandler.AsynchronousServerSocketChannel创建的时候可以传入一个AsynchronousChannelGroup,那么通过AsynchronousServerSocketChannel创建的AsynchronousSocketChannel将同属于一个组,共享资源。
java.nio.channels.CompletionHandler异步IO操作结果的回调接口,用于定义在IO操作完成后所作的回调工作。AIO的API允许两种方式来处理异步操作的结果:返回的Future模式或者注册CompletionHandler,我更推荐用CompletionHandler的方式,这些handler的调用是由AsynchronousChannelGroup的线程池派发的。显然,线程池的大小是性能的关键因素。AsynchronousChannelGroup允许绑定不同的线程池,通过三个静态方法来创建:public static AsynchronousChannelGroup withFixedThreadPool(int nThreads,
ThreadFactory threadFactory)
throws IOException
public static AsynchronousChannelGroup withCachedThreadPool(ExecutorService executor,
int initialSize)
public static AsynchronousChannelGroup withThreadPool(ExecutorService executor)
throws IOException
需要根据具体应用相应调整,从框架角度出发,需要暴露这样的配置选项给用户。
在介绍完了aio引入的TCP的主要接口和类之后,我们来设想下一个aio框架应该怎么设计。参考非阻塞nio框架的设计,一般都是采用Reactor模式,Reacot负责事件的注册、select、事件的派发;相应地,异步IO有个Proactor模式,Proactor负责CompletionHandler的派发,查看一个典型的IO写操作的流程来看两者的区别:
Reactor: send(msg) -> 消息队列是否为空,如果为空 -> 向Reactor注册OP_WRITE,然后返回 -> Reactor select -> 触发Writable,通知用户线程去处理 ->先注销Writable(很多人遇到的cpu 100%的问题就在于没有注销),处理Writeable,如果没有完全写入,继续注册OP_WRITE.注意到,写入的工作还是用户线程在处理。
Proactor: send(msg) -> 消息队列是否为空,如果为空,发起read异步调用,并注册CompletionHandler,然后返回。 -> 操作系统负责将你的消息写入,并返回结果(写入的字节数)给Proactor -> Proactor派发CompletionHandler.可见,写入的工作是操作系统在处理,无需用户线程参与。事实上在aio的API中,AsynchronousChannelGroup就扮演了Proactor的角色。
CompletionHandler有三个方法,分别对应于处理成功、失败、被取消(通过返回的Future)情况下的回调处理:
public interface CompletionHandler {
void completed(V result, A attachment);
void failed(Throwable exc, A attachment);
void cancelled(A attachment);
}
其中的泛型参数V表示IO调用的结果,而A是发起调用时传入的attchment.
在初步介绍完aio引入的类和接口后,我们看看一个典型的tcp服务端是怎么启动的,怎么接受连接并处理读和写,这里引用的代码都是yanf4j 的aio分支中的代码,可以从svn checkout,svn地址: http://yanf4j.googlecode.com/svn/branches/yanf4j-aio
第一步,创建一个AsynchronousServerSocketChannel,创建之前先创建一个AsynchronousChannelGroup,上文提到AsynchronousServerSocketChannel可以绑定一个AsynchronousChannelGroup,那么通过这个AsynchronousServerSocketChannel建立的连接都将同属于一个AsynchronousChannelGroup并共享资源:this.asynchronousChannelGroup = AsynchronousChannelGroup。withCachedThreadPool(Executors.newCachedThreadPool(),this.threadPoolSize);然后初始化一个AsynchronousServerSocketChannel,通过open方法:this.serverSocketChannel = AsynchronousServerSocketChannel。open(this.asynchronousChannelGroup);通过nio 2.0引入的SocketOption类设置一些TCP选项:this.serverSocketChannel。setOption(StandardSocketOption.SO_REUSEADDR,true);this.serverSocketChannel。setOption(StandardSocketOption.SO_RCVBUF,16*1024);
绑定本地地址:
this.serverSocketChannel。bind(new InetSocketAddress("localhost",8080), 100);其中的100用于指定等待连接的队列大小(backlog)。完了吗?还没有,最重要的监听工作还没开始,监听端口是为了等待连接上来以便accept产生一个AsynchronousSocketChannel来表示一个新建立的连接,因此需要发起一个accept调用,调用是异步的,操作系统将在连接建立后,将最后的结果——AsynchronousSocketChannel返回给你:
public void pendingAccept(){
if (this.started this.serverSocketChannel.isOpen()) { this.acceptFuture = this.serverSocketChannel.accept(null,
new AcceptCompletionHandler());
} else {
throw new IllegalStateException("Controller has been closed");
}
注意,重复的accept调用将会抛出PendingAcceptException,后文提到的read和write也是如此。accept方法的第一个参数是你想传给CompletionHandler的attchment,第二个参数就是注册的用于回调的CompletionHandler,最后返回结果Future.你可以对future做处理,这里采用更推荐的方式就是注册一个CompletionHandler.那么accept的CompletionHandler中做些什么工作呢?显然一个赤裸裸的AsynchronousSocketChannel是不够的,我们需要将它封装成session,一个session表示一个连接(mina里就叫IoSession了),里面带了一个缓冲的消息队列以及一些其他资源等。在连接建立后,除非你的服务器只准备接受一个连接,不然你需要在后面继续调用pendingAccept来发起另一个accept请求:
private final class AcceptCompletionHandler implements
CompletionHandler {
@Override
public void cancelled(Object attachment){
logger.warn("Accept operation was canceled");
}
@Override
public void completed(AsynchronousSocketChannel socketChannel,
Object attachment){
try {
logger.debug("Accept connection from " + socketChannel.getRemoteAddress());
configureChannel(socketChannel);
AioSessionConfig sessionConfig = buildSessionConfig(socketChannel);
Session session = new AioTCPSession(sessionConfig,AioTCPController.this.configuration。getSessionReadBufferSize(),AioTCPController.this.sessionTimeout);session.start();
registerSession(session);
} catch(Exception e){
e.printStackTrace();logger.error("Accept error", e);
notifyException(e);
} finally {
pendingAccept();
}
@Override
public void failed(Throwable exc, Object attachment) { logger.error("Accept error", exc);
try {
notifyException(exc);
} finally {
pendingAccept();
}
注意到了吧,我们在failed和completed方法中在最后都调用了pendingAccept来继续发起accept调用,等待新的连接上来。有的同学可能要说了,这样搞是不是递归调用,会不会堆栈溢出?实际上不会,因为发起accept调用的线程与CompletionHandler回调的线程并非同一个,不是一个上下文中,两者之间没有耦合关系。要注意到,CompletionHandler的回调共用的是AsynchronousChannelGroup绑定的线程池,因此千万别在回调方法中调用阻塞或者长时间的操作,例如sleep,回调方法最好能支持超时,防止线程池耗尽。
连接建立后,怎么读和写呢?回忆下在nonblocking nio框架中,连接建立后的第一件事是干什么?注册OP_READ事件等待socket可读。异步IO也同样如此,连接建立后马上发起一个异步read调用,等待socket可读,这个是Session.start方法中所做的事情:
public class AioTCPSession {
protected void start0(){
pendingRead();
}
protected final void pendingRead(){
if (!isClosed() this.asynchronousSocketChannel.isOpen()) { if (!this.readBuffer.hasRemaining()) { this.readBuffer = ByteBufferUtils。increaseBufferCapatity(this.readBuffer);
}
this.readFuture = this.asynchronousSocketChannel.read(this.readBuffer, this, this.readCompletionHandler);
} else {
throw new IllegalStateException(
"Session Or Channel has been closed");
}
}
AsynchronousSocketChannel的read调用与AsynchronousServerSocketChannel的accept调用类似,同样是非阻塞的,返回结果也是一个Future,但是写的结果是整数,表示写入了多少字节,因此read调用返回的是Future,方法的第一个参数是读的缓冲区,操作系统将IO读到数据拷贝到这个缓冲区,第二个参数是传递给CompletionHandler的attchment,第三个参数就是注册的用于回调的CompletionHandler.这里保存了read的结果Future,这是为了在关闭连接的时候能够主动取消调用,accept也是如此。现在可以看看read的CompletionHandler的实现:
public final class ReadCompletionHandler implements
CompletionHandler {
private static final Logger log = LoggerFactory
。getLogger(ReadCompletionHandler.class);
protected final AioTCPController controller;
public ReadCompletionHandler(AioTCPController controller){
this.controller = controller;
}
@Override
public void cancelled(AbstractAioSession session){
log.warn("Session(" + session.getRemoteSocketAddress()
+ ")read operation was canceled");
}
@Override
public void completed(Integer result, AbstractAioSession session) { if (log.isDebugEnabled())
log.debug("Session(" + session.getRemoteSocketAddress()
+ ")read +" + result + " bytes");
if(result 0){
session.updateTimeStamp();session.getReadBuffer()。flip();session.decode();session.getReadBuffer()。compact();
}
} finally {
try {
session.pendingRead();
} catch(IOException e){
session.onException(e);session.close();
}
controller.checkSessionTimeout();
}
@Override
public void failed(Throwable exc, AbstractAioSession session) { log.error("Session read error", exc);session.onException(exc);session.close();
}
}
如果IO读失败,会返回失败产生的异常,这种情况下我们就主动关闭连接,通过session.close()方法,这个方法干了两件事情:关闭channel和取消read调用:if (null != this.readFuture) { this.readFuture.cancel(true);
}
this.asynchronousSocketChannel.close(); 在读成功的情况下,我们还需要判断结果result是否小于0,如果小于0就表示对端关闭了,这种情况下我们也主动关闭连接并返回。如果读到一定字节,也就是result大于0的情况下,我们就尝试从读缓冲区中decode出消息,并派发给业务处理器的回调方法,最终通过pendingRead继续发起read调用等待socket的下一次可读。可见,我们并不需要自己去调用channel来进行IO读,而是操作系统帮你直接读到了缓冲区,然后给你一个结果表示读入了多少字节,你处理这个结果即可。而nonblocking IO框架中,是reactor通知用户线程socket可读了,然后用户线程自己去调用read进行实际读操作。这里还有个需要注意的地方,就是decode出来的消息的派发给业务处理器工作最好交给一个线程池来处理,避免阻塞group绑定的线程池。
IO写的操作与此类似,不过通常写的话我们会在session中关联一个缓冲队列来处理,没有完全写入或者等待写入的消息都存放在队列中,队列为空的情况下发起write调用:
protected void write0(WriteMessage message){
boolean needWrite = false;
synchronized (this.writeQueue) { needWrite = this.writeQueue.isEmpty();this.writeQueue.offer(message);
}
if(needWrite){
pendingWrite(message);
}
protected final void pendingWrite(WriteMessage message){
message = preprocessWriteMessage(message);
if (!isClosed() this.asynchronousSocketChannel.isOpen()) { this.asynchronousSocketChannel.write(message.getWriteBuffer(),this, this.writeCompletionHandler);
} else {
throw new IllegalStateException(
"Session Or Channel has been closed");
}
write调用返回的结果与read一样是一个Future,而write的CompletionHandler处理的核心逻辑大概是这样:
@Override
public void completed(Integer result, AbstractAioSession session) { if (log.isDebugEnabled())
log.debug("Session(" + session.getRemoteSocketAddress()
+ ")writen " + result + " bytes");
WriteMessage writeMessage;
Queue writeQueue = session.getWriteQueue();
synchronized(writeQueue){
writeMessage = writeQueue.peek();if (writeMessage.getWriteBuffer() == null || !writeMessage.getWriteBuffer()。hasRemaining()) { writeQueue.remove();if (writeMessage.getWriteFuture() != null) { writeMessage.getWriteFuture()。setResult(Boolean.TRUE);
}
try {
session.getHandler()。onMessageSent(session,writeMessage.getMessage());
} catch(Exception e){
session.onException(e);
}
writeMessage = writeQueue.peek();
}
if (writeMessage != null) {
try {
session.pendingWrite(writeMessage);
} catch(IOException e){
session.onException(e);session.close();
}
compete方法中的result就是实际写入的字节数,然后我们判断消息的缓冲区是否还有剩余,如果没有就将消息从队列中移除,如果队列中还有消息,那么继续发起write调用。
重复一下,这里引用的代码都是yanf4j aio分支中的源码,感兴趣的朋友可以直接check out出来看看: http://yanf4j.googlecode.com/svn/branches/yanf4j-aio.在引入了aio之后,java对于网络层的支持已经非常完善,该有的都有了,java也已经成为服务器开发的首选语言之一。java的弱项在于对内存的管理上,由于这一切都交给了GC,因此在高性能的网络服务器上还是Cpp的天下。java这种单一堆模型比之erlang的进程内堆模型还是有差距,很难做到高效的垃圾回收和细粒度的内存管理。
这里仅仅是介绍了aio开发的核心流程,对于一个网络框架来说,还需要考虑超时的处理、缓冲buffer的处理、业务层和网络层的切分、可扩展性、性能的可调性以及一定的通用性要求。
Eclipse下的重构:
什么是重构
重构是指在保持程序的全部功能的基础上改变程序结构的过程。重构的类型有很多,如更改类名,改变方法名,或者提取代码到方法中。每一次重构,都要执行一系列的步骤,这些步骤要保证代码和原代码相一致。
重构的理由:为整理,为扩展,为优雅。
在Eclipse下的重构:
重构会关联多个文件,在一次重构时,不可再修改并保存文件,重构无法撤销或重做。
Eclipse中的重构类型
如果你看一下Eclipse的重构菜单,可以看到四部分。第一部分是撤销和重做。其他的三部分包含Eclipse提供的三种类型的重构。
第一种类型的重构改变代码的物理结构,像Rename和Move。第二种是在类层次上改变代码结构,例如Pull Up和Push Down。第三种是改变类内部的代码,像Extract Method和Encapsulate Field。这三部分的重构列表如下。
类型1 物理结构
l Rename
l Move
l Change Method signature
l Convert Anonymous Class to Nested
l Convert Member Type to New File:内部类提出一个单独类。
类型2 类层次结构
l Push Down:将父类中方法或成员移到子类。
l Push Up
l Extract Interface
l Generalize Type (Eclipse 3)
l User Supertype Where Possible
类型3 类内部结构
l Inline
l Extract Method
l Extract Local Variable
l Extract Constant
l Introduce Parameter:引进参数替换local var
l Introduce Factory
l Encapsulate Field
表从Eclipse帮助中提取,列出了各种重构支持的Java资源类型,对应的快捷键。
名字
|
可应用的Java元素
|
快捷键
|
Undo
|
在一次重构后可执行
|
Alt + Shift + Z
|
Redo
|
在一次撤销重构后可执行
|
Alt + Shift + Y
|
Rename
|
对方法,成员变量,局部变量,方法参数,对象,类,包,源代码目录,工程可用。
|
Alt + Shift + R
|
Move
|
对方法,成员变量,局部变量,方法参数,对象,类,包,源代码目录,工程可用。
|
Alt + Shift + V
|
Change Method Signature
|
对方法可用。
|
Alt + Shift + C
|
Convert Anonymous Class to Nested
|
对匿名内部类可用。
|
|
Move Member Type to New File
|
对嵌套类可用。
|
|
Push Down
|
对同一个类中成员变量和方法可用。
|
|
Pull Up
|
对同一个类中成员变量和方法,嵌套类可用。
|
|
Extract Interface
|
对类可用。
|
|
Generalize Type
|
对对象的声明可用。
|
|
Use Supertype Where Possible
|
对类可用。
|
|
Inline
|
对方法,静态final类,局部变量可用。
|
Alt + Shift + I
|
Extract Method
|
对方法中的一段代码可用。
|
Alt + Shift + M
|
Extract Local Variable
|
对选中的与局部变量相关的代码可用。
|
Alt + Shift + L
|
Extract Constant
|
对静态final类变量,选中的与静态final类变量相关的代码可用。
|
|
Introduce Parameter
|
对方法中对成员变量和局部变量的引用可用。
|
|
Introduce Factory
|
对构造方法可用。
|
|
Convert Local Variable to Field
|
对局部变量可用。
|
Alt + Shift +
|
学习一项知识,必须问自己三个重要问题:1. 它的本质是什么。2. 它的第一原则是什么。3. 它的知识结构是怎样的。
pongba的 知其所以然地学习(以算法学习为例)
中他提出了现有算法类书的讲授者是自顶向下思维,理论和知道点都摆出来,再做个细的推理与低阶的知道做个衔接。但是都没有讲算法的思想是怎么发展而来的,数据思维的过程是怎样的。“如果问题求解是一部侦探小说, 那么算法只是结局而已,而思考过程才是情节。”
那到底什么样的才算是授人以渔的呢?波利亚的《如何解题》绝对算是一本,他的《数学的发现》也值得一看。具体到算法书,那就不是光看text book就足够的了,为了深入理解一个算法的来龙去脉前因后果,从一个算法中领悟尽量深刻的东西,则需要做到三件事情:
寻找该算法的原始出处:TAOCP作为一个资料库是绝对优秀的,基础的算法只要你能想到的,几乎都可以在上面找到原始出处。查到原始出处之后(譬如一篇paper),就可以去网上搜来看了。因为最初的作者往往对一个方案的诞生过程最为了解。比如经典数据结构中的红黑树是出了名的令人费解的结构之一,但它的作者Sedgewick一张PPT,给你讲得通通透透,比算法导论上的讲法强上数倍。
原始的出处其实也未必就都推心置腹地和你讲得那么到位:前面说过,算法设计出来了之后人们几乎是不会去回顾整个的思维过程细节的,只把直指目标的那些东西写出来。结果就又是一篇欧几里德式的文章了。于是你就迷失在一大堆“定义”、“引理”、“定理”之中了。这种文章看上去整个写得井井有条,其实是把发明的过程整个给颠倒过来了,我一直就想,如果作者们能够将整个的思路过程写出来,哪怕文字多上十倍,我也绝对会比看那一堆定义定理要容易理解得多。话说回来,怎么办?可以再去网上找找,牛人讲得未必比经典教材上的差。那倘若实在找不出好的介绍呢,就只能自己揣摩了。揣摩的重要性,是怎么说都不为过的。揣摩的一些指导性的问题有:为什么要这样(为什么这是好的)?为什么不是那样(有其它做法吗?有更好的做法吗?)?这样做是最好的吗?(为什么?能证明吗?)这个做法跟其它的什么做法有本质联系吗?这个跟这个的区别是什么?问题的本质是什么?这个做法的本质又是什么?到底本质上是什么东西导致了这个做法如此..?与这个问题类似的还有其它问题吗?(同样或类似的做法也适用吗?)等等。
不仅学习别人的思路,整理自己的思路也是极其重要的:详见《跟波利亚学解题》的“4. 一个好习惯”和“7. 总结的意义”。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/pongba/archive/2008/07/07/2622713.aspx
什么是你的不可替代性和核心竞争力
By 刘未鹏(pongba) | http://blog.csdn.net/pongba
我虽不是经济学专业,但是翻开任何一本经济学的教材,或者直接翻开 wikipedia 的 economics 条目,都会看到物以稀为贵这条铁律。人才作为资源的一种,也是同样的道理。而稀缺性,换种说法也可以叫做不可替代性。一种资源越是稀缺,不可替代性就越强。再加上如果这种资源是一种具有实实在在使用价值的东西(而不是荷兰的郁金香泡沫),那么其价格就会越高。
问题是,如何构筑你的个人知识体系,使得你的知识技能集尽可能成为不可替代的呢?
CSDN 的孟岩先生前段时间发表了一篇博客“技术路线的选择重要但不具有决定性”,用有说服力的数据阐述了技术路线的选择对于个人知识体系的不可替代性并非一个关键因素,文中也提到了这样一段话:
那么核心竞争力是什么?我观察圈子里很多成功和不成功的技术人,提出一个观点,那就是个人的核心竞争力是是他独特的个性知识经验组合。这个行业里拥挤着上百万聪明人,彼此之间真正的不同在哪里?不在于你学的是什么技术,学得多深,IQ多少,而在于你身上有别人没有的独特的个性、背景、知识和经验的组合。如果这种组合,1,绝无仅有;2,在实践中有价值,3,具有可持续发展性,那你就具备核心竞争力。因此,当设计自己的发展路线时,应当最大限度地加强和发挥自己独特的组合,而不是寻求单项的超越。而构建自己独特组合的方式,主要是通过实践,其次是要有意识地构造。关于这个观点,话题太大,我不打算赘述。
孟岩先生在文中没有对这个问题展开叙述。但我一直也在寻思这个问题,后来在 TopLanguage 上一次讨论的时候,把一些想法整理成形。
长话短说,我相信以下的知识技能组合是具有相当程度的不可替代性的:
专业领域技能:成为一个专业领域的专家,你的专业技能越强,在这个领域的不可替代性就越高。这个自是不用多说的。
跨领域的技能:解决问题的能力,创新思维,判断与决策能力,Critical-Thinking,表达沟通能力,Open Mind 等等。
学习能力:严格来说学习能力也属于跨领域的技能,但由于实在太重要,并且跨任何领域,所以独立出来。如何培养学习能力,到目前为止我所知道的最有效的办法就是持续学习和思考新知识。
性格要素:严格来说这也属于跨领域技能,理由同上。一些我相信很重要的性格要素包括:专注、持之以恒、自省(意识到自己的问题所在的能力,这是改进自身的大前提)、好奇心、自信、谦卑(自信和谦卑是不悖的,前者是相信别人能够做到的自己也能够做到,后者是不要总认为自己确信正确的就一定是正确的,Keep an open mind)等等。
关于如何培养这些方面的能力,呃.. 需要学习的东西太多,对于第2项中列出的一些子项,可以参考我上次列的一些资料(《如何清晰地思考》),我自己也在学习之中。另外我在《一直以来伴随我的一些学习习惯》(一,二,三,四)中也提到了一些相关的方法。
注:
以上将个人的核心竞争力分为4个部分,其中每个部分的罗列并不一定详尽,也有可能我忽略了重要的东西或罗列了不重要的东西,所以欢迎补充和纠正。
以上只是我个人所认为的具有相当程度不可替代性的知识技能集,至于是否有更具不可替代性的“装备”,不妨思考。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/pongba/archive/2009/01/14/3776586.aspx
Eclipse中常用的快捷键(最经典的快捷键,就不用多说了)
Ctrl+D: 删除当前行
Ctrl+Alt+↓ 复制当前行到下一行(复制增加)
Ctrl+Alt+↑ 复制当前行到上一行(复制增加)
Alt+↓ 当前行和下面一行交互位置(特别实用,可以省去先剪切,再粘贴了)
Alt+↑ 当前行和上面一行交互位置(同上)
Alt+← 前一个编辑的页面
Alt+→ 下一个编辑的页面(当然是针对上面那条来说了)
Alt+Enter 显示当前选择资源(工程,or 文件 or文件)的属性
Shift+Enter 在当前行的下一行插入空行(这时鼠标可以在当前行的任一位置,不一定是最后)
Shift+Ctrl+Enter 在当前行插入空行(原理同上条)
Ctrl+Q 定位到最后编辑的地方
Ctrl+L 定位在某行 (对于程序超过100的人就有福音了)
Ctrl+M 最大化当前的Edit或View (再按则反之)
Ctrl+/ 注释当前行,再按则取消注释
Ctrl+O 快速显示 OutLine
Ctrl+T 快速显示当前类的继承结构
Ctrl+W 关闭当前Editer
Ctrl+K 参照选中的Word快速定位到下一个
Ctrl+E 快速显示当前Editer的下拉列表(如果当前页面没有显示的用黑体表示)
Ctrl+/(小键盘) 折叠当前类中的所有代码
Ctrl+×(小键盘) 展开当前类中的所有代码
Ctrl+Space 代码助手完成一些代码的插入(但一般和输入法有冲突,可以修改输入法的热键,也可以暂用Alt+/来代替)
Ctrl+Shift+E 显示管理当前打开的所有的View的管理器(可以选择关闭,激活等操作)
Ctrl+J 正向增量查找(按下Ctrl+J后,你所输入的每个字母编辑器都提供快速匹配定位到某个单词,如果没有,则在stutes line中显示没有找到了,查一个单词时,特别实用,这个功能Idea两年前就有了)
Ctrl+Shift+J 反向增量查找(和上条相同,只不过是从后往前查)
Ctrl+Shift+F4 关闭所有打开的Editer
Ctrl+Shift+X 把当前选中的文本全部变为大写
Ctrl+Shift+Y 把当前选中的文本全部变为小写
Ctrl+Shift+F 格式化当前代码
Ctrl+Shift+P 定位到对于的匹配符(譬如{}) (从前面定位后面时,光标要在匹配符里面,后面到前面,则反之)
下面的快捷键是重构里面常用的,本人就自己喜欢且常用的整理一下(注:一般重构的快捷键都是Alt+Shift开头的了)
Alt+Shift+R 重命名 (是我自己最爱用的一个了,尤其是变量和类的Rename,比手工方法能节省很多劳动力)
Alt+Shift+M 抽取方法 (这是重构里面最常用的方法之一了,尤其是对一大堆泥团代码有用)
Alt+Shift+C 修改函数结构(比较实用,有N个函数调用了这个方法,修改一次搞定)
Alt+Shift+L 抽取本地变量( 可以直接把一些魔法数字和字符串抽取成一个变量,尤其是多处调用的时候)
Alt+Shift+F 把Class中的local变量变为field变量 (比较实用的功能)
Alt+Shift+I 合并变量(可能这样说有点不妥Inline)
Alt+Shift+V 移动函数和变量(不怎么常用)
Alt+Shift+Z 重构的后悔药(Undo)
Ctrl+Shift+U 选择选中的文字后非常类似于UE的列表查询
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/f128690011/archive/2007/06/24/1664354.aspx
1:改变数据库的默认编码配置,在MYSQL的安装目录中,找到my.ini,修改默认编码为:default-character-set=utf8
2:建立数据库时,CREATE DATABASE ms_db CHARACTER SET utf8 COLLATE utf8_general_ci;
3:执行脚本:指定编码格式set names utf8(注意,不是UTF-8
4:如果你采用的是外部接入的方式,在连接中确定请求的编码格式如:jdbc:mysql://localhost:3306 /ms_db?useUnicode=true&characterEncoding=UTF-8(不要出现任何空格,否则出错)
5:set character_set_results=gbk;(解决命令行乱码问题);
--------------------------------------------------------------------------------
问题的关键在于数据导出、导入时要做到所使用的字符集相一致:
1、mysqldump 的 default-character-set变量;
2、mysql 的--default-character-set变量;
3、mysqld的 Db characterset变量。
例如:备份使用latin1字符集则恢复时也要使用该字符集并且数据库的缺省字符集也要是该字符集,即latin1. 换成gbk也应该一样.
乱码的根源在于字符集的不一致:操作系统(Windows为gbk,Linux是UTF-8),数据库(CREATE DATABASE db_name DEFAULT CHARACTER SET gbk 或者CREATE DATABASE db_name DEFAULT CHARACTER SET latin1)使用图形界面是就更要注意其缺省配置。
--------------------------------------------------------------------------------
在这里我把自己知道的东东贴出来,还望大家多多提意见,补充,谢谢~~
show variables like 'character%';查看字符编码
--更改字符集
SET character_set_client = utf-8 ;
SET character_set_connection = utf-8 ;
SET character_set_database = utf-8 ;
SET character_set_results = utf-8 ;
SET character_set_server = utf-8 ;
SET collation_connection = utf8 ;
SET collation_database = utf8 ;
SET collation_server = utf8 ;
MySQL的字符集支持(Character Set Support)有两个方面:字符集(Character set)和排序方式(Collation)。对于字符集的支持细化到四个层次:
服务器(server),数据库(database),数据表(table)和连接(connection)。
1.MySQL默认字符集:MySQL对于字符集的指定可以细化到一个数据库,一张表,一列.传统的程序在创建数据库和数据表时并没有使用那么复杂的配置,它们用的是默认的配置. (1)编译MySQL 时,指定了一个默认的字符集,这个字符集是 latin1;(2)安装MySQL 时,可以在配置文件 (my.ini) 中指定一个默认的的字符集,如果没指定,这个值继承自编译时指定的;(3)启动mysqld 时,可以在命令行参数中指定一个默认的的字符集,如果没指定,这个值继承自配置文件中的配置,此时 character_set_server 被设定为这个默认的字符集;(4)当创建一个新的数据库时,除非明确指定,这个数据库的字符集被缺省设定为character_set_server; (5)当选定了一个数据库时,character_set_database 被设定为这个数据库默认的字符集;(6)在这个数据库里创建一张表时,表默认的字符集被设定为 character_set_database,也就是这个数据库默认的字符集;(7)当在表内设置一栏时,除非明确指定,否则此栏缺省的字符集就是表默认的字符集;如果什么地方都不修改,那么所有的数据库的所有表的所有栏位的都用 latin1 存储,不过我们如果安装 MySQL,一般都会选择多语言支持,也就是说,安装程序会自动在配置文件中把 default_character_set 设置为 UTF-8,这保证了缺省情况下,所有的数据库的所有表的所有栏位的都用 UTF-8 存储。
2.查看默认字符集(默认情况下,mysql的字符集是latin1(ISO_8859_1)通常,查看系统的字符集和排序方式的设定可以通过下面的两条命令:
mysql> SHOW VARIABLES LIKE 'character%';
+--------------------------+---------------------------------+
| Variable_name | Value |
+--------------------------+---------------------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | latin1 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | D:"mysql-5.0.37"share"charsets" |
+--------------------------+---------------------------------+
mysql> SHOW VARIABLES LIKE 'collation_%';
+----------------------+-----------------+
| Variable_name | Value |
+----------------------+-----------------+
| collation_connection | utf8_general_ci |
| collation_database | utf8_general_ci |
| collation_server | utf8_general_ci |
+----------------------+-----------------+
3.修改默认字符集
(1) 最简单的修改方法,就是修改mysql的my.ini文件中的字符集键值,
如 default-character-set = utf8
character_set_server = utf8
修改完后,重启mysql的服务,service mysql restart
使用 mysql> SHOW VARIABLES LIKE 'character%';查看,发现数据库编码均已改成utf8
+--------------------------+---------------------------------+
| Variable_name | Value |
+--------------------------+---------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir | D:"mysql-5.0.37"share"charsets" |
+--------------------------+---------------------------------+
(2) 还有一种修改字符集的方法,就是使用mysql的命令
SET character_set_client = utf8 ;
SET character_set_connection = utf8 ;
SET character_set_database = utf8 ;
SET character_set_results = utf8 ;
SET character_set_server = utf8 ;
mysql> SET collation_connection = utf8 ;
mysql> SET collation_database = utf8 ;
mysql> SET collation_server = utf8 ;
一般就算设置了表的默认字符集为utf8并且通过UTF-8编码发送查询,你会发现存入数据库的仍然是乱码。问题就出在这个connection连接层上。解决方法是在发送查询前执行一下下面这句:
SET NAMES 'utf8';
它相当于下面的三句指令:
SET character_set_client = utf8;
SET character_set_results = utf8;
SET character_set_connection = utf8;
不知道什么原因,我在自己机器上把上述三个字符集都设置成utf8后,查询中文结果还是乱码,只有把character_set_results设置成GBK之后才能从命令行正常显示中文.
set character_set_results=GBK;
---------------------------------------------------------------
如果用eclipse :
点击Window-->Preferences,展开General-->WorkSpace,看到左边的Text file encoding没有,默认的设定是简体中文编码(gbk,gb2312这样),而linux下面呢,是UTF-8。
当你新建一个项目,希望使用和WorkSpace不同编码,请右击你的项目,选择Properties,点击Resource,看到Text file encoding了吧,点击Other,选择UTF-8
最后,将my.ini中的两处default 的字符集改为gbk不要使用utf8
JUnit 设计的目的就是有效地抓住编程人员写代码的意图,然后快速检查他们的代码是否与他们的意图相匹配。 JUnit 发展至今,版本不停的翻新,但是所有版本都一致致力于解决一个问题,那就是如何发现编程人员的代码意图,并且如何使得编程人员更加容易地表达他们的代码意图。JUnit 4.4 也是为了如何能够更好的达到这个目的而出现的。
JUnit 4.4 主要提供了以下三个大方面的新特性来更好的抓住编程人员的代码意图:
1)提供了新的断言语法(Assertion syntax)——assertThat 。
*新的断言语法主要提供了assertThat,其操作示例:
// 联合匹配符not和equalTo表示“不等于”
assertThat( something, not( equalTo( "developer" ) ) );
// 联合匹配符not和containsString表示“不包含子字符串”
assertThat( something, not( containsString( "Works" ) ) );
// 联合匹配符anyOf和containsString表示“包含任何一个子字符串”
assertThat(something, anyOf(containsString("developer"), containsString("Works")));
JUnit 4.4 默认提供一些可读的描述性错误信息
String s = "hello world!";
assertThat( s, anyOf( containsString("developer"), containsString("Works") ) );
// 如果出错后,系统会自动抛出以下提示信息:
java.lang.AssertionError:
Expected: (a string containing "developer" or a string containing "Works")
got: "hello world!"
2)提供了假设机制(Assumption)。
提供语句assumeThat, assumeTrue,assumeNotNull 和 assumeNoException。
*assumeThat作用:语法同assertThat,语义当假设成立时执行其后语句。
应用:1、改变条件,可对某些测试用例选择性执行。2、
*使用: assume* 假设语句,必须得 import static org.junit.Assume.*;。 如果引用了第三方 hamcrest 的匹配符库,必须得 import static org.hamcrest.Matchers.*;,如果引用 JUnit 4.4 自带的匹配符库,需要 import static org.hamcrest.CoreMatchers.*;。
3)提供了理论机制(Theory)
Theory机制比较复杂,一般也用不到。
丰田模式,如果我的理解没有错,其最核心最基本的概念是“集体思考”,强调可视性和持续改进。展开来说,比较有趣的几点:
1- 问题是大家共同的,有问题大家一起解决。
2- 在出现问题的现场解决问题而不是在办公桌。
3- 任何人都可以指手画脚,发现质量问题,工人有权直接停掉生产线。
4- 持续发现问题并解决。
5- 建立共识。
6- 对人,尤其是一线工人的尊重。
7- 危机意识。
《谈话的力量》 by Alan Garner
一、 通过问题促进交谈
1. 提出开放式问题而非封闭式
2. 避免问题过于宽泛
3. 一开始的问题要简单、对方易于回答、感兴趣回答,不要过于难
4. 事先做好准备
5. 提问时不要在别人回答之前就包含个人的观点和立场
二、 表达诚实的称赞
1. 鼓励喜欢的行为比惩罚不喜欢的行为更有效
2. 将称赞说得更具体一些
3. 在称赞中加入对方名字,让他觉得是针对他说的而不是敷衍
4. 可以在称赞后加上一个相关问题,帮对方接受称赞
5. 称赞别人时不要有任何索取
6. 切忌一味称赞,否则显得太假
7. 不要用对方称赞自己的话回答对方
8. 适当向第三方称赞另一个人(间接称赞)
9. 积极接受别人对自己的称赞
三、 倾听别人的话语
1. 积极倾听,就是告诉别人你对他发出的信息的理解(“你是说……,是么?”),尤其是不太确定对方意思的时候,以及对方传递重要信息或者感情上的信息时。
四、 利用自由信息
1. 学会利用自由信息(即你没有主动要求也没有预料到的信息)去展开话题
五、 让别人知道你
1. 学会自我透露。通常的交流经历四个阶段:套话、事实、意见、感受,自我透露的程度逐渐提高
2. 自我透露时内容要具体,也可以适当展示自己的缺点和反面
3. 自我透露切忌观点不明确,如不用“我”而说“你”,不用陈述句而用问句,等
六、 开始一段谈话
1. 通过谈论环境、对方、自己来开始一段谈话,通常谈论环境和对方比谈论自己更容易开始
七、 发出可能被接受的邀请
1. 要学会用双重视角,发出对方可能感兴趣的邀请
2. 一开始的邀请要随意一些,从小处着手,不要让对方觉得邀请参加的活动意义太大太重要而不敢随意参加
八、 积极地接受批评
1. 当别人批评自己时,不要急于逃避、反击
2. 当别人批评自己时,首先要询问具体内容,对时间、地点、原因、人物、什么、怎么样提问,搞清楚别人到底为啥批评自己
3. 第二步要同意对方的批评,可以同意对方批评的事实,如果不同意,则要同意对方有表达意见的权利
4. 第三步可以通过自我透露表明自己的立场
九、 拒绝别人的操纵
1. “破唱片”的方法:不管你别人说什么,都可以同意他们的意见或给予他们表达意见的权利,但是自始至终保持一贯的态度,重复同样的话表达拒绝
十、 要求改变
1. 希望别人做出改变时,可以利用如下公式:“我不太满意,你【说明其行为】,(使得)【指出后果】,所以我觉得【描述自己的感受】。
2. 说明其行为的时候,尽量采取客观的态度,说得具体一些,让对方明确领会你的意思,一次只需提一种行为,不要说太多,最好只专注现在发生或刚刚发生不久的行为,不要翻出“陈芝麻烂谷子”的事,不要抱怨对方“总是……”,不要妄加揣测和推断对方的意图
3. 指出后果时,要用积极的态度
4. 描述感受时,要注意用简洁的语言,不要用粗俗的语言
5. 作完以上陈述后要暂停一下,给对方以回想的时间,从而可能提出令人满意的解决方案
6. 如果没有成功,要进行直接要求,要具体要求对方改变某一个做法,一次只提一件事
7. 如果还没有成功,则采用“破唱片”做法,不断重复要求,直到成功
8. 可能对方无法完全按照你的要求去做,这时会进行商谈,商谈过程中要始终牢记你最初的目的——希望某种需要得到满足或者某种权利受到尊重,解决办法可以根据双方反馈进行调整,但一定要满足最初的目的
十一、 通过动作表情达意
1. 注意保持合适的个人空间
2. 表达喜欢的感情可以采用SOFTEN方法:Smile微笑、Open posture开放的姿态(同时和两个人说话时可以上半身对一个人小半身正对另一个人)、Forward lean身体前倾、Touch身体接触、Eye contact眼神交流(对方瞳孔放大表明喜欢你)、Nod点头
十二、 减少社交场合中的紧张心理
1. 紧张的原因是因为有如下几种信念:逃避、恐惧、以偏概全、要求过高。
2. 挑战逃避意识——追问自己有什么证据表明是这件事情让自己紧张;自己对自己叫“停”,从而驱逐头脑中存在的逃避想法
3. 挑战恐惧心理——想想自己头脑中的“可怕”事件发生的可能性有多大(通常会很小);想到最坏的结果,并用感情色彩较弱的词语去描述它(最坏也就是……,顶多只是称得上倒霉……)
4. 挑战以偏概全的习惯——不仅不要对自己“贴标签”也不要对别人“贴标签”,问问自己“贴标签”的证据在哪里,往往发现没有合理的证据;过去发生的事情不代表将来一定发生,失败过并不代表将来不能成功
5. 挑战要求过高的心理——不要要求完美,也不要坚持遵循对自己不利的准则(过去一直以某种方式做事并不意味着必须一直这样做);不要要求别人遵循你自己的准则,别人是你不可控的
十三、 有计划地去努力
1. 设定明确的目标——目标要明确(描述的行为不会与其他行为混淆);要可证实(即使旁观者也可以确定你是否实现了目标);要肯定(“我要……”而不是“我不能/要……”);要可计量;要明白目标的实现完全取决与你自己的行动(不要根据别人的回应来判断是否成功)
2. 划分目标的等级——多个目标需要实现时,分难易,先做最容易的
3. 增加步骤——当一个目标较难时,可以细分为多个步骤,一步一步去实现
4. 预先演练——可以在付诸行动前自己演习
5. 奖励自己——设定目标时同时设定实现目标后对自己的奖励,并切实兑现奖励(奖励要是自己真正想要的),不要吝惜达成目标后对自己的表扬
Learning from "Apprentice"
Tips learned:
1. If you are a leader, do be decisive.
2. Never underestimate the enemy.
3. As a leader, you should be able to manage your team members.
Suggestions from Mr. Trump
1. Deal good with boss.
2. People needed: can handle pressure, creative.
3. Respect from winning.
4. 领导常常需要力排众议。Lead with authority.
5. A leader should be decisive.
6. 有时候做生意靠直觉。Business comes from instinct.
7. Always listen to others, though you may not do as they say.
8. Go big or go home. Think it big.
9. Sell your ideas.
10. Know when to fold.如果一个想法不切实际或效果不理想,即使它是你一手想起来的,也要适时放弃。
11. There is no failure, you can never quit.
12. I don’t need choker.(怯场的人)
13. You should love what you do.
14. A leader should be able to control his underlings.
15. Always focus in the goal.
16. Getting along with people is very important.
17. Be flexible; be able to change.
18. A leader should know how to inspire his/her staff.
19. Good leader knows the strength and weaknesses of his/her employees.
20. Good deal is all about money; money is what proves your success.
21. Members in the best team push each other. You should push your team members to perform their best.
22. Get to the point, don’t waste time.
23. Loyalty is very important.
24. Great business man knows how to balance creativity and feasibility.
25. Always stand up for yourself.
26. A deal is a deal. Once you shake hands with others, never break up the “hand-shake” for no reason.
27. A god is in the details.
28. Never beg when you sell things.
29. You should believe what you sell, or else you will sell nothing.
30. Energy is very crucial.
31. You will not succeed without passion.
作者 陈怀临 | 2009-06-27 07:53 | 类型 专题分析 | 21条用户评论 »
【编者注:这是我阅读复旦大学计算机系博士生孙贺的主页和博客时,发现的其讲话稿。阅读之后,对其思想的深邃颇为欣赏。另外我对其文中提到的几个哲学家也都不知道,估计在小孙的眼里,陈首席基本上属于文盲的范畴。有兴趣的读者可参阅:知识分子的故园】
非常感谢复旦大学本科生资助委员会给我提供了这样一个机会,使我很荣幸的来和大家进行交流,提出自己的一些想法。
今天我和大家谈的倒不是我个人的在专业领域的看法,我主要是想和大家谈一谈作为当代的知识分子,应该扮演着一个什么样的角色。为什么要谈这样一个问题呢?因为我们发现今天知识分子的意义和两百年前或者三百年前已经有了明显的不同。比如在十七八世纪,许许多多的知识分子,比如帕斯卡、康德、卢梭,他们把他们的研究和实践结合在一起。我们首先以说帕斯卡为例,我在这里提到的帕斯卡,就是所有学过初等数学,都知道“帕斯卡三角形”的那个帕斯卡。他是一个法国科学家,为了帮助工作繁忙的父亲,他设计了法国的第一台计算器。他利用自己发明的气压计证明了真空的存在。不仅如此,他的《沉思录》被认为是当代人和思想的第一次对话。他还是一个虔诚的天主教徒。
不幸的是,他在三十六岁时疯了,在后面的三十七年里一直住在疯人院里。我们再来看康德。在三十一岁那一年,康德写下了《自然通史与天体理论,或根据牛顿定律研究整个宇宙的结构及其力学起源》的非凡著作。之后,康德还写过《将负数引入哲学的尝试》等论文,从此开始了数学和物理学的研究。众所周知,康德最为重要的著作就是三大批判,即《纯粹理论批判》,《实践理论批判》和《判断力批判》。除此以外,康德还有一系列关于教育学的著作,例如《论教育学》、《系科之争》等。康德的主要著作还包括《使用人类学》。我们很难想象一个终身生活在哥尼斯堡这样一个小镇的单身汉,在他八十岁的生活中没有离开过这个小镇一步。在漫长的八十年的单身寂寞的生活中,他思考了人生中一切的伟大的实践。在他的墓碑上有这样的一句话:“有两样东西,我们越是经常不断地思索他们,他们就越是唤起一种始终新颖和日益增长的赞叹和敬畏充溢我们的心灵,那就是我头顶的星空和我心中的道德律。他们向我印证:上帝在我头顶,也在我心中。”我提及的这些事实意在说明:今天的知识分子和两百年前传统意义上的知识分子在形式上出现了非常显著的差别。关于这一点,五十年前的德国哲学家和精神病学家卡尔•雅思贝斯在《在时代的精神生活》这本书中,就已经一针见血地提出了。
尽管雅氏描绘的是二十世纪三四十年代的欧洲社会,但在今天看来,他的针砭时弊、一针见血的分析同样适用于中国现实社会。一言以蔽之,他所阐述的就是在现代社会我们的知识已经瓦解,人的生活缺乏精神上的向导。文艺分析时期,一个人的学术研究和生命实践始终是结合在一起的。但是在今天,我们并不这样来看代学术研究。雅斯贝斯的分析非常精辟,他说,我们的一种以前从事高尚研究的快乐,被一种从事狭窄技术领域研究的快感所取代。在这样的情况下,一种可怕的情况出现了:我们不再认为学术研究是崇高的。比如今天我问大家,大家儿时的梦想是什么,可能对在场的各位同学而言,你们会说童年时代的纯真的梦想是成为一个科学家,因为在那时的我们内心深处科学家代表了一种崇高。但是在今天,当各位从事学术研究的时候,你们会发现:你们现在所走的学术道路与你们儿时的梦想相差甚远。为什么?我们钻入到一个狭窄的领域,我们在进行研究,但是这种研究并不能给我们带来普遍的幸福。
于是在这一点上一个很关键的问题出现了。我们就要问:这种情况是如何发生的?对于二十年前的中国知识分子而言,他们的存在首先代表了一种人文情怀。但是这种情况在今天已经消失殆尽。今天的中国社会在一定程度上、或者说今天的中国人和全世界的许许多多人,没有两三百年前的人更富有想象力,更能耐得住寂寞。今天的人们听任于娱乐的安排,我们上网,聊天,看电视,然后有各种各样的休闲手段。你如果寂寞的话,你会有一个各种各样的方式去排除寂寞。叔本华说过一句话 “孤独是一种伟大的情感”,但是今天的人已经甚少有一种真正的孤独的感觉。大家有的是什么,是郁闷,对吧?我们有的是郁闷。但是对于今天的人们,更为可怕的是,今天中国的一部分知识分子,居然走上了模特在T字台上所走的猫步。比如说于丹,等等。正是在这一点上,我们看到:今天的知识分子已经与一种作为知识分子本身的使命感相隔绝了。这种使命感是什么?我作为一个知识分子,我要去为国家而奉献、牺牲。天下兴旺,匹夫有责的中国古代人文精神在今天的知识分子中悄然消失了。所以,每当我忆起起俄罗斯文学的时候,俄罗斯知识分子的那种流亡意识总是给予我深刻的印象和泪如泉涌的感动。即一个知识分子,他可以抛弃生命中物质的一切,也要保守某种精神生活。一旦人们承认人的生活不是兽性的,而是文明的,那么他在世界中的生活本质上讲就应该是一种精神生活。
海德格尔曾经说过:人是追求生活意义的生物。如果一个人在他的生活中找不到生命的意义,他宁愿去自杀,哪怕他的身边全是面包。如果我们试图理解这样一句话,一个自然的问题就会被立即提出:即这种生命的意义应该如何去寻找?其实在人类的启蒙时代,就曾经提到过这样的问题。即人类在文明开始之初,他们就已经想到过一个人的生活必须有一种深刻的意义在其中。为什么,我们今天来想一下:如果我们认为,我们出生之前的一切,和我们毫无关系,在我们死亡之后的一切,和我们也没有任何关系。那么我们的生命是不是没有任何意义,我们在世界中的生活就只剩下吃喝玩乐。但是事实并不是如此。所以在东西方文明的早期,人们同时想到了同一个问题:即在终极上,人的生活应该是有意义的。从这一点出发,东西方文明对于这样一个绝对意义,想出了两个不同的途径,即起源于东方、盛行于西方的基督教文明和中国的儒学思想。在西方的基督教世界中,西方人认为:倘若有一个绝对的上帝在我们中间,人生就可以获得形而上学的意义。因为在这刻,人们可以自然地产生一种超验之思。我们可以,把一个人的生活放到一个上帝的维度,因此人就有一个全能的上帝去审视字词。在这时,他就可以约束着我们。与此同时,中国的儒家学派,将人的根本意义,集中到了礼教,伦理这一层面,这是一种脱离了行而上学的思辨。所以黑格尔在他的《哲学演讲录》的第一卷中就曾写过:”中国没有真正的哲学,有的只是伦理学。”可悲的是,今天的中国人,还在信仰着以伦理为基础的东西。我们有没有深刻地思考过,我们这种伦理,它的合理之处在哪里?也许这是我们需要真正思考的问题。今天许多的中国学生,缺少一种独立思考的精神,我在这里,我称其为一种精神,而不是一种能力,因为这本身非常重要,无法通过世俗教育去培养。在中国的儒家学派中,我们说“不孝有三,无后为大”,“父母在,不远游,游必有方”,等等。我们也都知道,为了纪念投汨罗江自尽的现实主义诗人屈原,中国传统中于是又了端午节,并有了吃粽子、赛龙舟的习俗。我们称屈原是一个伟大的现实主义诗人。原因何在?不妨去读屈原的《天问》,他百思不得其解要问的是什么?在我看来,他问核心的是在这样一个以儒教为统治的国家中,王权的合法性在哪里。屈原最早认识到了这一点,对一个人而言,是一种非常痛苦的事实。因为一个人生活在儒家思想中,却不能为以这种思想为生活的合理性提供依据。今天的人们一方面去宣扬儒教,一方面我们去纪念屈原,这不是一个非常可笑的事实吗?我们拿着伦理不放,但我们今天的人们没有真正地去思考,这种伦理的合理性在哪里?
基督教文明从公元五世纪到十五世纪,经历了漫长的一千年中世纪。一千年后,欧洲迎来了文艺复兴。与此同时,近代的基督教社会有了一次又一次的改革。直到十九世纪末尼采“杀死”了上帝。尼采曾经写过《查拉图斯特拉如是说》这本书,有人说这本书的出版把无数人的宗教信仰一劳永逸地消除了。尼采是种非常自信的人。他曾经在一本书的前言中写到:我的书是为这个社会极少数的人写的,但在这极少数的人当中,可能一个都还没有出生。但尼采断言,我的书终将名垂千古,载入史册。晚年的尼采非常寂寞,在日记中他写道,在大街上,我想拥抱随便哪一个人。寂寞之极,一八八九年尼采在都灵大街上抱住了一匹受马夫虐待而发疯的马,尼采疯了。二十世纪的曙光来临之时,尼采安静地离开了这个世界。
尼采杀死上帝后,西方人的生活突然呈现了一种荒诞性。如果没有一个人,没有一种绝对的规则存在的话,人是可以胡作非为的,因为绝对意义消失了。一旦绝对意义消失,那么人在在一个荒诞世界中的生活,其实很容易,吃喝玩乐,仅此而已。但是一个知识分子,如果在一个荒诞的世界中,既要去承担一种荒诞,并且要从荒诞中寻觅意义的话,这就非常困难。此时,存在主义的兴起为二十世纪人的生活的合理性提供准则。我们以最著名的存在主义大师萨特为例:当我们去看他的《他人就是地狱》这本书的时候,我们会发现一篇著名的文章,即《论五月风暴》。在这篇文章中,萨特谈论的是一九六八年全球范围内的学潮运动。萨特这样写道:他们反了,他们要寻找一个他们自己的世界。而这个世界,在我们的年轻时代,也曾经寻找过。但在我们年轻的时代,我们没有去反抗。而今天,他们的反抗和我们年轻时候沉默的事实,证明了在面对同一个制度的时候,他们的伟大和我们的渺小。通过这样的方式人们发现,在一个虚无的世界上,人的活动就是成了人的意义本身。
而在今天的中国社会,一个知识分子如何去创造他自己的意义?今天人们没有,或者说今天的中国人缺乏这样的反思。有人问,中国的知识分子,中国的文学家,为什么没有去拿诺贝尔文学奖。或者有人问,中国的文学家,离诺贝尔奖还有多远。在我看来,这个问题,我可以从这样一个视角给出回答,就是在我们今天中国的作家——或者说从鲁迅开始——所描写的生活,偏重于人的社会生活分析而没有很深刻地剖析人的生存本质。当我们去读马尔克斯的《百年孤独》,我们有一种人的孤寂和幻灭的感觉。甚至有人告诉我,他读过之后有一种自杀的感觉。因为在那里,我们看到了关于人谓之人的深刻反思。而今天的中国作家,中国的知识分子,缺乏这种反思。
为什么这种反思尤其重要?黑格尔曾经说过这样一句话“一个民族总要有一些仰望星空的人,这个民族才有希望。如果这个民族所有人都仰望脚下的事物,那么这个民族是没有希望可言的。”今天中国社会的可怕在于我们太缺乏这样的知识分子。这是一个民族的可悲。如果问今天的中国,有什么可以使我们低下头颅来,我认为,在中国近三百年来,我们没有产生一个可以和西方的知识分子相抗衡的知识分子。我们没有产生萨特这样的人物。没有产生康德,黑格尔,叔本华这样的人物。甚至没有产生加缪和福柯这样的人物。这是一个民族的悲哀。每一个深刻思考过时代精神的知识分子都能意会:夫物质之文明,取诸他国,不数十年而具矣,独至精神上之趣味,非千百年之培养,与一二天才之处,不及此。
让我们去审视德意志民族。德国有一个非常伟大的教育家——洪堡。他按照自己的教育思想,建立了洪堡大学。后来,德国许许多多的大学,都是按照他的模式建立起来的。在我读本科的时候,这种思想,我们全世界仍然是他的受益者,那是什么?那就是关于教育之本质的深刻理解。所有人你来德国学习,学费是全部免掉的。因为教育是一种事业。人并不是仅仅生活在现实生活中,人是一种历史的被造物。置于一切历史之下,教育便有了一种根本的意义,教育的目的是去塑造人。今天的中国之教育,中国的高等教育,把人沦为了一种工具。我们总是评论一所大学的毕业生中,有多少人去国企了,有多少人拿了高薪,当一个高等学府用这个作为一种炫耀的资本的时候,我们便不得不承认:一种恢弘壮丽般教育从根本上堕落了。教育的目的是人,人是目的,不是工具。在洪堡的时代,洪堡几乎是把所有的资源平均地用于教育。所以说德国的大学,他们的好与坏,并没有中国的大学这么悬殊,也没有美国的大学这样悬殊。但是德国,按照洪堡的思想,一个人去接受教育,那么这个教育的钱应该是国家来付。今天的中国人,教育部部长扬言:教育不能产业化;但是从国家到地方,我们实际做地恰恰是教育的产业化。但是现在你去德国留学也是要学费的,全世界已经越来越美国化了。全世界已经一起朝资本看齐的。
这世界仍然有一些非常伟大的人。二十世纪有三个最伟大的知识分子:萨特,福柯和乔母斯基。我不知道在座的各位,有多少人知道这者的名字。有人说,二十世纪的人不知道福柯,就像十九世纪的人不知道马克斯一样。不能说他是文盲,至少不能说他是一个知识分子。我知道我身边很多人都不知道福柯。我去年在西班牙。访问期间,我决定去法国扫福柯的墓。我问了一个在西班牙生活多年的华人,他三岁的时候到了马德里。我告诉他,我想去扫福柯的墓,但不知道福柯的墓在巴黎的什么地方。当然我没有这么直接地问,我先问你知不知道福柯,因为我知道中国的许许多多人都不知道福柯。他跟我说了一句话,他说“我也是读过高中的人”。从这个很小的事情,我们可以看出在欧洲的教育中,仍然没有忽略最核心的精神层面的培养。而这一块,在今天的中国,在我们呼喊素质教育的时候,实际上已经把教育庸俗化。教育的根本目的——人的精神力量的培养——在今天的中国已经被完全忽略了。
我现在指导四个本科生进行研究工作。他们中的每个人都在学术领域崭露头角、甚至取得了令人瞩目的成绩。我时常告诉他们,这还不够。一个学者从专业研究中获得快乐,但是一个思想者应该懂得在学术中生活。思想者这一称谓的定义不是来自他的研究,而应该首先来源他的生活。因为教育的首要目的是培养有思想的人,所以我们经常阅读中西方思想史,试图理解与我们看似久远的西方文明。比如说,福柯有句话:“学校是监狱和医院的混合物”,这句话怎么理解?其实在福柯看来,现在许许多多的人文科学,诸如教育学、心理学、社会学,它们不但不是真理,反而是一种权力、一种杀人的工具。比如说,再让我们回望精神病学,福柯在《疯颠与文明》中探讨了现代精神病的起源。在十六世纪之前,我们并不认为精神病人是疯子。我们甚至把他们作为一种可以预见未来的先知一样看待。疯子可以在大街上游走,并且受到人们的尊敬。这个可能是今天的人们所无法想象的。但是在五个世纪后,在我们所谓更加文明的社会当中,他们为什么就被关进了医院呢?实际上,在一六五六年法国国王下了一条命令,就说建立法国总医院。法国总医院的建立,并不是一个医疗机构。它是一个训诫机构。它要告诉人们:一个人要勤奋的工作,你如果不勤奋工作,就会和大街上的所有流浪汉和所谓的疯子一样,全部都关进了这样一个法国总医院里。当时法国总医院的条件极为恶劣,许许多多的人住在一起,下面就是老鼠乱窜。于是,随着麻风病的消退,精神病人成为了社会唾弃的新对象。但是恰恰在于,今天的人们,我们不能说我们是正常的,从而说你们是非正常的。借福柯之言,现代人需要从他们的角度,去证明精神病人的合法性。但是我们发现,在六百多年的历史进程当中,人们文明的若干关键要素、或者说现代文明,正是通过帕斯卡、梵高、尼采,这些所谓的非理性的人来建立的。但是我们要在他们这些疯子面前,去证明我们的理性是正常的,这不是一个很可笑的事实吗?
现代人的精神,远远没有以前人那样纯洁。现在人在精神层面上已经堕落了。比如说,福柯有一句最为尖锐的话:“只要男人和男人的婚姻一天,现代文明就一天无从谈起。”人们无法理解这样一句话,因为大家听到这句话的时候,大家往往首先想到的不是爱情,而是性。人们认为,两个男人和两个男人在一起,这是很恶心的。人们首先不会去想到,两个男人,只要两个男人他们在精神上在一起,那么这种爱情就是高尚的。而这种爱情曾经在古希腊曾经发生过。在公元五世纪以前也曾经有过。只是在今天,人们越来越强调物质,金钱和欲望的满足。当代社会诸如此类的怪现状还有很多。对于今天的中国的知识分子而言,我们应该有许多深思,当你仔细去想这个时代的时候,你会发现许多反常的现象。如果一代青年人还有一部分人去试图改变这种现象,这个国家就会有希望;如果我们这一代人都试图去迎合世俗,这个国家的精神风貌就会停滞不前。我们的许多知识分子——我们姑且称他们为知识分子——不再把教育作为一种神圣的职业来看待。他们开始炒股,他们开始开公司。他们把学生作为一种免费的劳动力。一种非常神圣的师生关系,一种新货相传的思想之光,在今天堕落得一塌糊涂。他们向国家骗基金,几十万或几百万,然后去做一些不痛不痒的学问。更有甚者,少数知识分子一旦走上领导岗位,便扮演了政客的角色。管你学生好坏、是否才华出众,老子嘴大说得算。在复旦,这是多么大的悲哀。当我忆及国父孙文先生的“天下为公,努力前程”的文字时,我为这些人感到奇耻大辱。
这就我们一个时代的悲哀,也是复旦的悲哀。但许许多多的人没有看到这一点。我希望在复旦,在这样一个很小的优秀本科生当中,在你们思考这些问题的时候,你们要看到这一点。若干年后你们才会试图去改变这一切。
加谬在《西西弗斯神话》的开篇就写道:“真正严肃的哲学问题只有一个,那就是人是否可以自杀。”为什么人他要探讨这样一个问题?刘小枫在《拯救与逍遥》这本书中写道,与其让这个世界以暧昧的方式赢,不如让自己以肯定的方式输。但是在今天,唯独有意义的,是一种生活的创造。是我们可以把生活赋予一种真实的意义。这种真实的意义是通过知识分子的精神活动来体现的。这种精神活动,在一个很低级的层面,正是我们所谓的,一日为师,一生为范。在一个很高级的层面来讲,就是真真正正的知识分子的思想,他的精神能够代代相传。
注定有人会被历史的足迹所记录。比如说贾植芳先生。知识分子不能成为一种政府的附庸。知识分子一词,本来就代表了一个人的精神事实,我们中国的知识分子当中,有贾植芳这样的人,也有类似郭沫若这样的作家。一个人在生活当中,他往往会向某些东西妥协。但是一个人的精神,他的视野,应该是向这个天空的方向去了望。这样一个民族才有希望。
回到具体事情上来,我来谈优秀本科生的专门培养。当我去指导本科生的时候,有一次我和一个本科生聊天。我当时我跟他说,我寝室里有两百本书,你随便看,你看不出我是从事哪一个领域研究的。然后他告诉我,他寝室中也有两百本书。我觉得这样的人才是我欣赏的。首先你是一个有追求的人,其次你是一个在专业领域有所成绩的人。但你一个人仅仅在专业领域有所成绩,你仅仅把发文章当作一种目的的话,那么一个人,他生活的价值就会变得很少。曾经有一个老师对我说,我们总是要把一些东西量化,所以我们博士毕业,发表了多少篇SCI,这种量化就非常重要,因为它很客观。我说,错!这种东西很客观,恰恰是由于我们缺乏了许许多多能够高瞻远瞩的教育者,他认为你是不是具有一种博士的胸怀,博士的研究能力。所以说在今天,我们什么都能量化。一个学生的好坏,我们看GPA;一个国家的发展,我们看GDP;那么一个教授的好坏,我们看发了多少SCI/EI。这到底是现代人的一种文明呢?还是现代人的愚蠢。有个伟大的数学家叫做黎曼。他一生只发表了十八篇论文。还包括手稿。但那十八篇论文确是名垂青史。大家如果对于数学有稍微一些多的了解的话,就是说当代数学有个非常重要的难题——黎曼猜想,就是黎曼提出的。
二十世纪之初,年仅三十八岁的希尔伯特在第二届数学家大会发表了二十世纪人类需要解决的二十三个数学难题。像希尔伯特这样伟大的数学家,他曾经说过这样一句话——请大家注意希尔伯特的用语——他说如果我死后一千年能够复活,那么我问的第一个问题就是黎曼猜想解决了没有。与那个已逝的时代相比,现代人比的不是思想的深邃,比的是一个人在物质上的富有,一个人帅不帅,我们舆论已经为这些所左右。这是一个社会的悲哀,学者和大学的媚俗。但是大学的使命并不是如此。我曾经和我的学生讲过康德的《论教育》。你们很难想象康德这样一个八十岁的单身汉,他的《教育学》会写得如此细腻,初读起来仿佛有一种独特的父爱在身边。康德从婴儿出生开始写起。婴儿出生的时候母亲的乳房中总会流出一些透明的液体,我们翻译成中文叫做初乳。是康德首先发问,这种初乳对于婴儿是不是有益。因为在之前这种初乳都是不要的。但康德首先问这种东西是不是对婴儿有益的。他认为人类总不会做无用功。还有,在婴儿哭的时候,家长总喜欢把婴儿抱起来,摇一摇,这样把孩子不哭了。是康德首先发现:婴儿不哭这一表象的原因是由于成人的行为足以导致婴儿的眩晕,就像我们看儿童坐木马转几圈就晕了一样,这对于他大脑的发展是非常不好的影响。康德从此写起,写到一个人的儿童教育,行为习惯的养成。然后,小学时的认知教育,德育的教育,美育的教育,初中时的体育教育,青春期时的性教育,大学时的哲学教育,科学教育。
除了康德,我们还可以列举其他人。比如亚当斯密,我们最熟悉他的书是《国富论》。但是他还写过一本道德哲学的经典——《道德情操论》。这是一个道德伦理学的经典之作。在今天的中国人,如果能够产生这样的知识分子,就至少代表了一个民族有一种很高贵的气质在里面。如果今天所有的知识分子都在作秀,那么这个民族就没有希望。
最后我要送给大家的是伟大神学家巴特的一句话。他在论述心爱的莫扎特的书中写道
Das Schwere schwebt und das Leichte uwendlich schwer wieget
生活是沉重之轻与轻之沉重
|
方法一:在servlet的init()方法中缓存数据
当应用服务器初始化servlet实例之后,为客户端请求提供服务之前,它会调用这个servlet的init()方法。在一个servlet 的生命周期中,init()方法只会被调用一次。通过在init()方法中缓存一些静态的数据或完成一些只需要执行一次的、耗时的操作,就可大大地提高系统性能。
例如,通过在init()方法中建立一个JDBC连接池是一个最佳例子,假设我们是用jdbc2.0的DataSource接口来取得数据库连接,在通常的情况下,我们需要通过JNDI来取得具体的数据源。我们可以想象在一个具体的应用中,如果每次SQL请求都要执行一次JNDI查询的话,那系统性能将会急剧下降。解决方法是如下代码,它通过缓存DataSource,使得下一次SQL调用时仍然可以继续利用它:
以下是引用片段:
public class ControllerServlet extends HttpServlet{
private javax.sql.DataSource testDS = null;
public void init(ServletConfig config) throws ServletException {
super.init(config);
Context ctx = null;
try{
ctx = new InitialContext();
testDS = (javax.sql.DataSource)ctx.lookup("jdbc/testDS");
}catch(NamingException ne){ne.printStackTrace();}
}catch(Exception e){e.printStackTrace();}
}
public javax.sql.DataSource getTestDS(){
return testDS;
}
...
...
}
方法 2:禁止servlet和JSP 自动重载(auto-reloading)
Servlet/JSP提供了一个实用的技术,即自动重载技术,它为开发人员提供了一个好的开发环境,当你改变servlet和JSP页面后而不必重启应用服务器。然而,这种技术在产品运行阶段对系统的资源是一个极大的损耗,因为它会给JSP引擎的类装载器(classloader)带来极大的负担。因此关闭自动重载功能对系统性能的提升是一个极大的帮助。
方法 3: 不要滥用HttpSession
在很多应用中,我们的程序需要保持客户端的状态,以便页面之间可以相互联系。但不幸的是由于HTTP具有天生无状态性,从而无法保存客户端的状态。因此一般的应用服务器都提供了session来保存客户的状态。在JSP应用服务器中,是通过HttpSession对像来实现session的功能的,但在方便的同时,它也给系统带来了不小的负担。因为每当你获得或更新session时,系统者要对它进行费时的序列化操作。你可以通过对 HttpSession的以下几种处理方式来提升系统的性能。
如果没有必要,就应该关闭JSP页面中对HttpSession的缺省设置。 如果你没有明确指定的话,每个JSP页面都会缺省地创建一个HttpSession。如果你的JSP中不需要使用session的话,那可以通过如下的JSP页面指示符来禁止它:
以下是引用片段:
<%@ page session="false"%>
不要在HttpSession中存放大的数据对像:如果你在HttpSession中存放大的数据对像的话,每当对它进行读写时,应用服务器都将对其进行序列化,从而增加了系统的额外负担。你在HttpSession中存放的数据对像越大,那系统的性能就下降得越快。
当你不需要HttpSession时,尽快地释放它:当你不再需要session时,你可以通过调用 HttpSession.invalidate()方法来释放它。尽量将session的超时时间设得短一点:在JSP应用服务器中,有一个缺省的 session的超时时间。当客户在这个时间之后没有进行任何操作的话,系统会将相关的session自动从内存中释放。超时时间设得越大,系统的性能就会越低,因此最好的方法就是尽量使得它的值保持在一个较低的水平。
方法 4: 将页面输出进行压缩
压缩是解决数据冗余的一个好的方法,特别是在网络带宽不够发达的今天。有的浏览器支持gzip(GNU zip)进行来对HTML文件进行压缩,这种方法可以戏剧性地减少HTML文件的下载时间。因此,如果你将servlet或JSP页面生成的HTML页面进行压缩的话,那用户就会觉得页面浏览速度会非常快。但不幸的是,不是所有的浏览器都支持gzip压缩,但你可以通过在你的程序中检查客户的浏览器是否支持它。下面就是关于这种方法实现的一个代码片段:
以下是引用片段:
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
OutputStream out = null;
String encoding = request.getHeader("Accept-Encoding");
if (encoding != null && encoding.indexOf("gzip") != -1){
request.setHeader("Content-Encoding" , "gzip");
out = new GZIPOutputStream(request.getOutputStream());
}
else if (encoding != null && encoding.indexOf("comdivss") != -1){
request.setHeader("Content-Encoding" , "comdivss");
out = new ZIPOutputStream(request.getOutputStream());
}else{
out = request.getOutputStream();
}
...
...
}
方法 5: 使用线程池
应用服务器缺省地为每个不同的客户端请求创建一个线程进行处理,并为它们分派service()方法,当service()方法调用完成后,与之相应的线程也随之撤消。由于创建和撤消线程会耗费一定的系统资源,这种缺省模式降低了系统的性能。但所幸的是我们可以通过创建一个线程池来改变这种状况。
另外,我们还要为这个线程池设置一个最小线程数和一个最大线程数。在应用服务器启动时,它会创建数量等于最小线程数的一个线程池,当客户有请求时,相应地从池从取出一个线程来进行处理,当处理完成后,再将线程重新放入到池中。如果池中的线程不够地话,系统会自动地增加池中线程的数量,但总量不能超过最大线程数。通过使用线程池,当客户端请求急剧增加时,系统的负载就会呈现的平滑的上升曲线,从而提高的系统的可伸缩性。
方法 6: 选择正确的页面包含机制
在JSP中有两种方法可以用来包含另一个页面:
1、使用include指示符
以下是引用片段:
<%@ includee file=”test.jsp” %>
2、使用jsp指示符
以下是引用片段:
<jsp:includee page=”test.jsp” flush=”true”/>
在实际中发现,如果使用第一种方法的话,可以使得系统性能更高。
方法 7:正确地确定javabean的生命周期
JSP的一个强大的地方就是对javabean的支持。通过在JSP页面中使用jsp:useBean标签,可以将javabean直接插入到一个JSP页面中。它的使用方法如下:
以下是引用片段:
<jsp:useBean id="name" scope="page|request|session|application"
class="package.className" type="typeName">
</jsp:useBean>
其中scope属性指出了这个bean的生命周期。缺省的生命周期为page。如果你没有正确地选择bean的生命周期的话,它将影响系统的性能。
举例来说,如果你只想在一次请求中使用某个bean,但你却将这个bean的生命周期设置成了session,那当这次请求结束后,这个 bean将仍然保留在内存中,除非session超时或用户关闭浏览器。这样会耗费一定的内存,并无谓的增加了JVM垃圾收集器的工作量。因此为bean 设置正确的生命周期,并在bean的使命结束后尽快地清理它们,会使用系统性能有一个提高。
其它一些有用的方法
1、在字符串连接操作中尽量不使用“+”操作符:在java编程中,我们常常使用“+”操作符来将几个字符串连接起来,但你或许从来没有想到过它居然会对系统性能造成影响吧?由于字符串是常量,因此JVM会产生一些临时的对像。你使用的“+”越多,生成的临时对像就越多,这样也会给系统性能带来一些影响。解决的方法是用StringBuffer对像来代替“+”操作符。
2、避免使用System.out.println()方法:由于System.out.println()是一种同步调用,即在调用它时,磁盘I/O操作必须等待它的完成,因此我们要尽量避免对它的调用。但我们在调试程序时它又是一个必不可少的方便工具,为了解决这个矛盾,我建议你最好使用 Log4j工具(http://Jakarta.apache.org ),它既可以方便调试,而不会产生System.out.println()这样的方法。
3、ServletOutputStream 与 PrintWriter的权衡:使用PrintWriter可能会带来一些小的开销,因为它将所有的原始输出都转换为字符流来输出,因此如果使用它来作为页面输出的话,系统要负担一个转换过程。而使用ServletOutputStream作为页面输出的话就不存在一个问题,但它是以二进制进行输出的。因此在实际应用中要权衡两者的利弊。
总结
本文的目的是通过对servlet和JSP的一些调优技术来极大地提高你的应用程序的性能,并因此提升整个J2EE应用的性能。通过这些调优技术,你可以发现其实并不是某种技术平台(比如J2EE和.NET之争)决定了你的应用程序的性能,重要是你要对这种平台有一个较为深入的了解,这样你才能从根本上对自己的应用程序做一个优化。
正则表达式规则
|
|
|
String.matches() 这个方法主要是返回是否匹配指定的字符串,如果匹配则为true,否则为false;
如:/**
* 判断字符创是否是一个有效的日期
*
* @param theStr
* @return true 是,false否
*/
public static boolean isDate(String theStr) {
return theStr.matches("\\d{4}\\-\\d{1,2}\\-\\d{1,2}");
}
这个方法的参数为正则表达式,关于正则表达式的用法如下:
正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来:(1)检查一个串中是否含有符合某个规则的子串,并且可以得到这个子串;(2)根据匹配规则对字符串进行灵活的替换操作。
正则表达式学习起来其实是很简单的,不多的几个较为抽象的概念也很容易理解。之所以很多人感觉正则表达式比较复杂,一方面是因为大多数的文档没有做到由浅入深地讲解,概念上没有注意先后顺序,给读者的理解带来困难;另一方面,各种引擎自带的文档一般都要介绍它特有的功能,然而这部分特有的功能并不是我们首先要理解的。
文章中的每一个举例,都可以点击进入到测试页面进行测试。闲话少说,开始。
1. 正则表达式规则
1.1 普通字符
字母、数字、汉字、下划线、以及后边章节中没有特殊定义的标点符号,都是"普通字符"。表达式中的普通字符,在匹配一个字符串的时候,匹配与之相同的一个字符。
举例1:表达式 "c",在匹配字符串 "abcde" 时,匹配结果是:成功;匹配到的内容是:"c";匹配到的位置是:开始于2,结束于3。(注:下标从0开始还是从1开始,因当前编程语言的不同而可能不同)
举例2:表达式 "bcd",在匹配字符串 "abcde" 时,匹配结果是:成功;匹配到的内容是:"bcd";匹配到的位置是:开始于1,结束于4。
1.2 简单的转义字符
一些不便书写的字符,采用在前面加 "\" 的方法。这些字符其实我们都已经熟知了。
表达式
|
可匹配
|
\r, \n
|
代表回车和换行符
|
\t
|
制表符
|
\\
|
代表 "\" 本身
|
还有其他一些在后边章节中有特殊用处的标点符号,在前面加 "\" 后,就代表该符号本身。比如:^, $ 都有特殊意义,如果要想匹配字符串中 "^" 和 "$" 字符,则表达式就需要写成 "\^" 和 "\$"。
表达式
|
可匹配
|
\^
|
匹配 ^ 符号本身
|
\$
|
匹配 $ 符号本身
|
\.
|
匹配小数点(.)本身
|
这些转义字符的匹配方法与 "普通字符" 是类似的。也是匹配与之相同的一个字符。
举例1:表达式 "\$d",在匹配字符串 "abc$de" 时,匹配结果是:成功;匹配到的内容是:"$d";匹配到的位置是:开始于3,结束于5。
1.3 能够与 '多种字符' 匹配的表达式
正则表达式中的一些表示方法,可以匹配 '多种字符' 其中的任意一个字符。比如,表达式 "\d" 可以匹配任意一个数字。虽然可以匹配其中任意字符,但是只能是一个,不是多个。这就好比玩扑克牌时候,大小王可以代替任意一张牌,但是只能代替一张牌。
表达式
|
可匹配
|
\d
|
任意一个数字,0~9 中的任意一个
|
\w
|
任意一个字母或数字或下划线,也就是 A~Z,a~z,0~9,_ 中任意一个
|
\s
|
包括空格、制表符、换页符等空白字符的其中任意一个
|
.
|
小数点可以匹配除了换行符(\n)以外的任意一个字符
|
举例1:表达式 "\d\d",在匹配 "abc123" 时,匹配的结果是:成功;匹配到的内容是:"12";匹配到的位置是:开始于3,结束于5。
举例2:表达式 "a.\d",在匹配 "aaa100" 时,匹配的结果是:成功;匹配到的内容是:"aa1";匹配到的位置是:开始于1,结束于4。
1.4 自定义能够匹配 '多种字符' 的表达式
使用方括号 [ ] 包含一系列字符,能够匹配其中任意一个字符。用 [^ ] 包含一系列字符,则能够匹配其中字符之外的任意一个字符。同样的道理,虽然可以匹配其中任意一个,但是只能是一个,不是多个。
表达式
|
可匹配
|
[ab5@]
|
匹配 "a" 或 "b" 或 "5" 或 "@"
|
[^abc]
|
匹配 "a","b","c" 之外的任意一个字符
|
[f-k]
|
匹配 "f"~"k" 之间的任意一个字母
|
[^A-F0-3]
|
匹配 "A"~"F","0"~"3" 之外的任意一个字符
|
举例1:表达式 "[bcd][bcd]" 匹配 "abc123" 时,匹配的结果是:成功;匹配到的内容是:"bc";匹配到的位置是:开始于1,结束于3。
举例2:表达式 "[^abc]" 匹配 "abc123" 时,匹配的结果是:成功;匹配到的内容是:"1";匹配到的位置是:开始于3,结束于4。
1.5 修饰匹配次数的特殊符号
前面章节中讲到的表达式,无论是只能匹配一种字符的表达式,还是可以匹配多种字符其中任意一个的表达式,都只能匹配一次。如果使用表达式再加上修饰匹配次数的特殊符号,那么不用重复书写表达式就可以重复匹配。
使用方法是:"次数修饰"放在"被修饰的表达式"后边。比如:"[bcd][bcd]" 可以写成 "[bcd]{2}"。
表达式
|
作用
|
{n}
|
表达式重复n次,比如:"\w{2}" 相当于 "\w\w";"a{5}" 相当于 "aaaaa"
|
{m,n}
|
表达式至少重复m次,最多重复n次,比如:"ba{1,3}"可以匹配 "ba"或"baa"或"baaa"
|
{m,}
|
表达式至少重复m次,比如:"\w\d{2,}"可以匹配 "a12","_456","M12344"...
|
?
|
匹配表达式0次或者1次,相当于 {0,1},比如:"a[cd]?"可以匹配 "a","ac","ad"
|
+
|
表达式至少出现1次,相当于 {1,},比如:"a+b"可以匹配 "ab","aab","aaab"...
|
*
|
表达式不出现或出现任意次,相当于 {0,},比如:"\^*b"可以匹配 "b","^^^b"...
|
举例1:表达式 "\d+\.?\d*" 在匹配 "It costs $12.5" 时,匹配的结果是:成功;匹配到的内容是:"12.5";匹配到的位置是:开始于10,结束于14。
举例2:表达式 "go{2,8}gle" 在匹配 "Ads by goooooogle" 时,匹配的结果是:成功;匹配到的内容是:"goooooogle";匹配到的位置是:开始于7,结束于17。
1.6 其他一些代表抽象意义的特殊符号
一些符号在表达式中代表抽象的特殊意义:
表达式
|
作用
|
^
|
与字符串开始的地方匹配,不匹配任何字符
|
$
|
与字符串结束的地方匹配,不匹配任何字符
|
\b
|
匹配一个单词边界,也就是单词和空格之间的位置,不匹配任何字符
|
进一步的文字说明仍然比较抽象,因此,举例帮助大家理解。
举例1:表达式 "^aaa" 在匹配 "xxx aaa xxx" 时,匹配结果是:失败。因为 "^" 要求与字符串开始的地方匹配,因此,只有当 "aaa" 位于字符串的开头的时候,"^aaa" 才能匹配,比如:"aaa xxx xxx"。
举例2:表达式 "aaa$" 在匹配 "xxx aaa xxx" 时,匹配结果是:失败。因为 "$" 要求与字符串结束的地方匹配,因此,只有当 "aaa" 位于字符串的结尾的时候,"aaa$" 才能匹配,比如:"xxx xxx aaa"。
举例3:表达式 ".\b." 在匹配 "@@@abc" 时,匹配结果是:成功;匹配到的内容是:"@a";匹配到的位置是:开始于2,结束于4。
进一步说明:"\b" 与 "^" 和 "$" 类似,本身不匹配任何字符,但是它要求它在匹配结果中所处位置的左右两边,其中一边是 "\w" 范围,另一边是 非"\w" 的范围。
举例4:表达式 "\bend\b" 在匹配 "weekend,endfor,end" 时,匹配结果是:成功;匹配到的内容是:"end";匹配到的位置是:开始于15,结束于18。
一些符号可以影响表达式内部的子表达式之间的关系:
表达式
|
作用
|
|
|
左右两边表达式之间 "或" 关系,匹配左边或者右边
|
( )
|
(1). 在被修饰匹配次数的时候,括号中的表达式可以作为整体被修饰
(2). 取匹配结果的时候,括号中的表达式匹配到的内容可以被单独得到
|
举例5:表达式 "Tom|Jack" 在匹配字符串 "I'm Tom, he is Jack" 时,匹配结果是:成功;匹配到的内容是:"Tom";匹配到的位置是:开始于4,结束于7。匹配下一个时,匹配结果是:成功;匹配到的内容是:"Jack";匹配到的位置时:开始于15,结束于19。
举例6:表达式 "(go\s*)+" 在匹配 "Let's go go go!" 时,匹配结果是:成功;匹配到内容是:"go go go";匹配到的位置是:开始于6,结束于14。
举例7:表达式 "¥(\d+\.?\d*)" 在匹配 "$10.9,¥20.5" 时,匹配的结果是:成功;匹配到的内容是:"¥20.5";匹配到的位置是:开始于6,结束于10。单独获取括号范围匹配到的内容是:"20.5"。
2. 正则表达式中的一些高级规则
2.1 匹配次数中的贪婪与非贪婪
在使用修饰匹配次数的特殊符号时,有几种表示方法可以使同一个表达式能够匹配不同的次数,比如:"{m,n}", "{m,}", "?", "*", "+",具体匹配的次数随被匹配的字符串而定。这种重复匹配不定次数的表达式在匹配过程中,总是尽可能多的匹配。比如,针对文本 "dxxxdxxxd",举例如下:
表达式
|
匹配结果
|
(d)(\w+)
|
"\w+" 将匹配第一个 "d" 之后的所有字符 "xxxdxxxd"
|
(d)(\w+)(d)
|
"\w+" 将匹配第一个 "d" 和最后一个 "d" 之间的所有字符 "xxxdxxx"。虽然 "\w+" 也能够匹配上最后一个 "d",但是为了使整个表达式匹配成功,"\w+" 可以 "让出" 它本来能够匹配的最后一个 "d"
|
由此可见,"\w+" 在匹配的时候,总是尽可能多的匹配符合它规则的字符。虽然第二个举例中,它没有匹配最后一个 "d",但那也是为了让整个表达式能够匹配成功。同理,带 "*" 和 "{m,n}" 的表达式都是尽可能地多匹配,带 "?" 的表达式在可匹配可不匹配的时候,也是尽可能的 "要匹配"。这 种匹配原则就叫作 "贪婪" 模式 。
非贪婪模式:
在修饰匹配次数的特殊符号后再加上一个 "?" 号,则可以使匹配次数不定的表达式尽可能少的匹配,使可匹配可不匹配的表达式,尽可能的 "不匹配"。这种匹配原则叫作 "非贪婪" 模式,也叫作 "勉强" 模式。如果少匹配就会导致整个表达式匹配失败的时候,与贪婪模式类似,非贪婪模式会最小限度的再匹配一些,以使整个表达式匹配成功。举例如下,针对文本 "dxxxdxxxd" 举例:
表达式
|
匹配结果
|
(d)(\w+?)
|
"\w+?" 将尽可能少的匹配第一个 "d" 之后的字符,结果是:"\w+?" 只匹配了一个 "x"
|
(d)(\w+?)(d)
|
为了让整个表达式匹配成功,"\w+?" 不得不匹配 "xxx" 才可以让后边的 "d" 匹配,从而使整个表达式匹配成功。因此,结果是:"\w+?" 匹配 "xxx"
|
更多的情况,举例如下:
举例1:表达式 "<td>(.*)</td>" 与字符串 "<td><p>aa</p></td> <td><p>bb</p></td>" 匹配时,匹配的结果是:成功;匹配到的内容是 "<td><p>aa</p></td> <td><p>bb</p></td>" 整个字符串, 表达式中的 "</td>" 将与字符串中最后一个 "</td>" 匹配。
举例2:相比之下,表达式 "<td>(.*?)</td>" 匹配举例1中同样的字符串时,将只得到 "<td><p>aa</p></td>", 再次匹配下一个时,可以得到第二个 "<td><p>bb</p></td>"。
2.2 反向引用 \1, \2...
表达式在匹配时,表达式引擎会将小括号 "( )" 包含的表达式所匹配到的字符串记录下来。在获取匹配结果的时候,小括号包含的表达式所匹配到的字符串可以单独获取。这一点,在前面的举例中,已经多次展示了。在实际应用场合中,当用某种边界来查找,而所要获取的内容又不包含边界时,必须使用小括号来指定所要的范围。比如前面的 "<td>(.*?)</td>"。
其实,"小括号包含的表达式所匹配到的字符串" 不仅是在匹配结束后才可以使用,在匹配过程中也可以使用。表达式后边的部分,可以引用前面 "括号内的子匹配已经匹配到的字符串"。引用方法是 "\" 加上一个数字。"\1" 引用第1对括号内匹配到的字符串,"\2" 引用第2对括号内匹配到的字符串……以此类推,如果一对括号内包含另一对括号,则外层的括号先排序号。换句话说,哪一对的左括号 "(" 在前,那这一对就先排序号。
举例如下:
举例1:表达式 "('|")(.*?)(\1)" 在匹配 " 'Hello', "World" " 时,匹配结果是:成功;匹配到的内容是:" 'Hello' "。再次匹配下一个时,可以匹配到 " "World" "。
举例2:表达式 "(\w)\1{4,}" 在匹配 "aa bbbb abcdefg ccccc 111121111 999999999" 时,匹配结果是:成功;匹配到的内容是 "ccccc"。再次匹配下一个时,将得到 999999999。这个表达式要求 "\w" 范围的字符至少重复5次,注意与 "\w{5,}" 之间的区别。
举例3:表达式 "<(\w+)\s*(\w+(=('|").*?\4)?\s*)*>.*?</\1>" 在匹配 "<td id='td1' style="bgcolor:white"></td>" 时,匹配结果是成功。如果 "<td>" 与 "</td>" 不配对,则会匹配失败;如果改成其他配对,也可以匹配成功。
|
|
在java语言中使用正则表达式
|
|
|
首先让我们构成一个正则表达式。为简单起见,先构成一个正则表达式来识别下面格式的电话号码数字:(nnn)nnn-nnnn。
第一步,创建一个pattern对象来匹配上面的子字符串。一旦程序运行后,如果需要的话,可以让这个对象一般化。匹配上面格式的正则表达可以这样构成: (\d{3})\s\d{3}-\d{4},其中\d单字符类型用来匹配从0到9的任何数字,另外{3}重复符号,是个简便的记号,用来表示有3个连续的数字位,也等效于(\d\d\d)。\s也另外一个比较有用的单字符类型,用来匹配空格,比如Space键,tab键和换行符。
是不是很简单?但是,如果把这个正则表达式的模式用在java程序中,还要做两件事。对java的解释器来说,在反斜线字符(\)前的字符有特殊的含义。在java中,与regex有关的包,并不都能理解和识别反斜线字符(\),尽管可以试试看。但为避免这一点,即为了让反斜线字符(\)在模式对象中被完全地传递,应该用双反斜线字符(\)。此外圆括号在正则表达中两层含义,如果想让它解释为字面上意思(即圆括号),也需要在它前面用双反斜线字符(\)。也就是像下面的一样:
\\(\\d{3}\\)\\s\\d{3}-\\d{4}
现在介绍怎样在java代码中实现刚才所讲的正则表达式。要记住的事,在用正则表达式的包时,在你所定义的类前需要包含该包,也就是这样的一行:
import java.util.regex.*;
下面的一段代码实现的功能是,从一个文本文件逐行读入,并逐行搜索电话号码数字,一旦找到所匹配的,然后输出在控制台。
BufferedReader in;
Pattern pattern = Pattern.compile("\\(\\d{3}\\)\\s\\d{3}-\\d{4}");
in = new BufferedReader(new FileReader("phone"));
String s;
while ((s = in.readLine()) != null)
{
Matcher matcher = pattern.matcher(s);
if (matcher.find())
{
System.out.println(matcher.group());
}
}
in.close();
对那些熟悉用Python或Javascript来实现正则表达式的人来说,这段代码很平常。在Python和Javascript这些语言中,或者其他的语言,这些正则表达式一旦明确地编译过后,你想用到哪里都可以。与Perl的单步匹配相比,看起来多多做了些工作,但这并不很费事。
find()方法,就像你所想象的,用来搜索与正则表达式相匹配的任何目标字符串,group()方法,用来返回包含了所匹配文本的字符串。应注意的是,上面的代码,仅用在每行只能含有一个匹配的电话号码数字字符串时。可以肯定的说,java的正则表达式包能用在一行含有多个匹配目标时的搜索。本文的原意在于举一些简单的例子来激起读者进一步去学习java自带的正则表达式包,所以对此就没有进行深入的探讨。
这相当漂亮吧! 但是很遗憾的是,这仅是个电话号码匹配器。很明显,还有两点可以改进。如果在电话号码的开头,即区位号和本地号码之间可能会有空格。我们也可匹配这些情况,则通过在正则表达式中加入\s?来实现,其中?元字符表示在模式可能有0或1个空格符。
第二点是,在本地号码位的前三位和后四位数字间有可能是空格符,而不是连字号,更有胜者,或根本就没有分隔符,就是7位数字连在一起。对这几种情况,我们可以用(-|)?来解决。这个结构的正则表达式就是转换器,它能匹配上面所说的几种情况。在()能含有管道符|时,它能匹配是否含有空格符或连字符,而尾部的?元字符表示是否根本没有分隔符的情况。
最后,区位号也可能没有包含在圆括号内,对此可以简单地在圆括号后附上?元字符,但这不是一个很好的解决方法。因为它也包含了不配对的圆括号,比如" (555" 或 "555)"。相反,我们可以通过另一种转换器来强迫让电话号码是否带有有圆括号:(\(\d{3}\)|\d{3})。如果我们把上面代码中的正则表达式用这些改进后的来替换的话,上面的代码就成了一个非常有用的电话号码数字匹配器:
Pattern pattern =
Pattern.compile("(\\(\\d{3}\\)|\\d{3})\\s?\\d{3}(-|)?\\d{4}");
可以确定的是,你可以自己试着进一步改进上面的代码。
现在看看第二个例子,它是从Friedl的中改编过来的。其功能是用来检查文本文件中是否有重复的单词,这在印刷排版中会经常遇到,同样也是个语法检查器的问题。
匹配单词,像其他的一样,也可以通过好几种的正则表达式来完成。可能最直接的是\b\w+\b,其优点在于只需用少量的regex元字符。其中\w元字符用来匹配从字母a到u的任何字符。+元字符表示匹配匹配一次或多次字符,\b元字符是用来说明匹配单词的边界,它可以是空格或任何一种不同的标点符号(包括逗号,句号等)。
现在,我们怎样来检查一个给定的单词是否被重复了三次?为完成这个任务,需充分利用正则表达式中的所熟知的向后扫描。如前面提到的,圆括号在正则表达式中有几种不同的用法,一个就是能提供组合类型,组合类型用来保存所匹配的结果或部分匹配的结果(以便后面能用到),即使遇到有相同的模式。在同样的正则表达中,可能(也通常期望)不止有一个组合类型。在第n个组合类型中匹配结果可以通过向后扫描来获取到。向后扫描使得搜索重复的单词非常简单:\b(\w+) \s+\1\b。
圆括号形成了一个组合类型,在这个正则表示中它是第一组合类型(也是仅有的一个)。向后扫描\1,指的是任何被\w+所匹配的单词。我们的正则表达式因此能匹配这样的单词,它有一个或多个空格符,后面还跟有一个与此相同的单词。注意的是,尾部的定位类型(\b)必不可少,它可以防止发生错误。如果我们想匹配"Paris in the the spring",而不是匹配"Java's regex package is the theme of this article"。根据java现在的格式,则上面的正则表达式就是:Pattern pattern =Pattern.compile("\\b(\\w+)\\s+\\1\\b");
最后进一步的修改是让我们的匹配器对大小写敏感。比如,下面的情况:"The the theme of this article is the Java's regex package.",这一点在regex中能非常简单地实现,即通过使用在Pattern类中预定义的静态标志CASE_INSENSITIVE :
Pattern pattern =Pattern.compile("\\b(\\w+)\\s+\\1\\b",
Pattern.CASE_INSENSITIVE);
有关正则表达式的话题是非常丰富,而且复杂的,用Java来实现也非常广泛,则需要对regex包进行的彻底研究,我们在这里所讲的只是冰山一角。即使你对正则表达式比较陌生,使用regex包后会很快发现它强大功能和可伸缩性。如果你是个来自Perl或其他语言王国的老练的正则表达式的黑客,使用过 regex包后,你将会安心地投入到java的世界,而放弃其他的工具,并把java的regex包看成是手边必备的利器。
|
|
摘要: 莫小米文章
地址:http://blog.tianya.cn/blogger/view_blog.asp?BlogName=xiaomi520&idWriter=0&Key=0
几米语录:
米语录 生活永远不是童话
... 阅读全文
**君子耻其言而过其行**
typedef int* pint;
typedef pint* ppint;
void func(ppint &x)
{
x = new int*;
*x= new int(32);
}
//使用方法
int **p=0;
func(p);
cout<<(**p)<<endl;
int *pV;
pV = new int(2); //这里注意与在cpp中与java中语法的差异
cout<<"PV = "<<(*pV)<<endl;
int ival = 1024;
int *pi = &ival;
int* &ptrVal2 = pi;
菩提本无树 (2009-04-04 17:48:59)
佛对我说:你的心上有尘。我用力地擦拭。
佛说:你错了,尘是擦不掉的。我于是将心剥了下来.
佛又说:你又错了,尘本非尘,何来有尘
我想这是从神秀和慧能那两个偈子引申出来。
神秀说:“身是菩提树,心如明镜台,时时勤拂拭,勿使惹尘埃。”
慧能说:“菩提本无树,明镜亦非台,本来无一物,何处惹尘埃。”
的确,要能够参透这两个偈子的确很难,就是正确的理解也不易。
身是菩提树,心如明镜台,时时勤拂拭,勿使惹尘埃
众生的身体就是一棵觉悟的智慧树,
众生的心灵就象一座明亮的台镜。
要时时不断地将它掸拂擦试,
不让它被尘垢污染障蔽了光明的本性。
菩提本无树,明镜亦非台,本来无一物,何处惹尘埃
菩提原本就没有树,
明亮的镜子也并不是台。
本来就是虚无没有一物,
那里会染上什么尘埃?
这首畿子可以看出慧能是个有大智慧的人(后世有人说他是十世比丘转世),他这个畿子很契合禅宗的顿悟的理念。是一种出世的态度,主要意思是,世上本来就是空的,看世间万物无不是一个空字,心本来就是空的话,就无所谓抗拒外面的诱惑,任何事物从心而过,不留痕迹。这是禅宗的一种很高的境界,领略到这层境界的人,就是所谓的开悟了。
禅的境界一花一世界,一叶一如来。这样的境界,是何等的完美。
禅的生活是非常朴实,没有欲望及贪求的,一切的作用都能融入空性。空不是什么都没有,而是使自己生活得更逍遥自在,如鱼得水。做事不要过于认真执着,而是要认真雕刻。
禅是“感情”的生活,禅的感情就是无缘大悲,同体大悲的心量。
禅是启发我们要学会舍得;真正的快乐只有舍得才能得,从舍中构筑一切的有。要辨证的看待拥有和失去,拥有不一定快乐,因为一旦想要拥有烦恼就出现了,因为“有”未必不是一种负担,只有豁达地看待得与失,成与败,拥有一颗无所得的心,你才会快乐。
最快乐的生活,就是善于驭心的生活。境不转心转,如果能够常常调心,就能常生喜悦而少烦恼。
佛法教我们把快乐和痛苦都放下,但是,放下并不是不去追求,而是随缘不变。
当我们能了解到,环境是无法控制、变化无常的,就能获致真正的快乐与内心的安定。
用清静心看世间,世间即清静,用解脱心看世间,心即解脱。
会调心的人就会生活,会生活的人才得大智慧,智慧高的人生活范围大,因为他能包容,能够令人安定,每个人都喜欢跟他在一起。
处理事务要多包容、忍耐,量大福大,量小阻碍多。
尊重别人,就能获得别人的尊重,
不听人我是非,听人我是非即是是非人,不能成大事。
修行就是管自己,自己都管不了,还管得了谁?众生就是我,我就是众生。
认识自己,如果不认识自己的心,就无法安排人生,也许你可以安排你的事业,家庭,希望一切如意,可是你却随时要接受无常的安排。认清自己为认清世界的根本,要研究这世界不如先研究自己。
修行就是要:审查自己的心、规画自己的心、企划自己的心。
身体的健康与心理有关,能够放下,不想烦恼的事,身心就能解脱。
佛法不是在庙里,而是在心里。
浪有高有低,海水依旧是海水,生活有苦有乐,心依旧是心。
其实尘在外,心在内,常拂之,心净无尘;
尘在内,心在外,常剥之,无尘无心;
心中有尘,尘本是心,
何畏心中尘,无尘亦无心?正如慧能所说的仁者心动
佛家追求的是一种超脱
却不是刻意的寻求
主旨在心
世间人,法无定法,然后知非法法也;
天下事,了犹未了,何妨以不了了之
菩提本无树,明镜亦非台。本来无一物,何处惹尘埃?
佛家的学说往往浸透着深奥的人生哲学,从而引得无数人将此作为座右铭,因为一方面这是一种处世方式,另一方面也是人们几千年的经验结晶。在学哲学时,常把佛家学说定义为唯心主义,从这句诗中也可以看出,菩提本无树,就是说,首先没有物质的存在,所以又如何惹尘埃呢?
菩提真的无树吗?记得以前有一部电影,是欧美的,描述的是一个非洲丛林的原始部落,生产力低下,以猎物为生,彼此生活安逸,波澜不惊。但是有一天,有一个人在海滩上拣到了一个易拉罐,把它带到了部落,虽然是一个对于我们来说不值钱的物件,但在那里却是件希罕物,可以说是珍宝。围绕着这一物件,为了得到它,部落里展开了一场争斗,在一场你争我夺的,钩心斗角的争夺后,他们省悟了,最后将易拉罐重新扔入了无际的大海。部落又恢复了昔日的平静。
人是从自然界演变而来,人类的本性就是永远也不满足,这种本性演发了无穷无尽的矛盾,也同时推动者人类社会的前进,在这种前进中,满含着血腥与残酷,在矛盾中,人们会选择一种信仰,目的只是为了逃避现实。
菩提既是树,明镜就是台,这些都是物质,皆是物,你可以闭眼不见,但都是客观存在。本来无一物,只是主观的逃避。
对于现实,我们会采取多种方式,当我们享受着生活的美好时,当我们在阳光下时,是不会去考虑菩提树是否存在的问题的;或当我们在爱河中徜徉,陶醉于其中时,何曾想过明镜?
只有当我们面临着生活的压力,面临着现实的残酷,当我们的爱被背叛,被蹂躏,在施展全身之力皆无果时,便会无奈的寻求心理的安慰。将烦恼抛之脑后,以重新焕发生活的斗志,或者,已丧失了斗志,仅寻求一种解脱。这也就是佛学这种理论赖以存在的基础。
这种理论在今天看来,也许有其积极的作用,那便是引导人们理智对待人生,当有冲突时,回避或退让或是好办法。
然而,人终究是人,一种贪婪,健忘的生物,当生活,现实,爱情等等因素重新回归美好时,便又会看到菩提树,看到明镜台了,便又会去惹尘埃了。
Tutorial: The H.264 Scalable Video Codec (SVC)收藏
Codecs are used to compress video to reduce the bandwidth required to transport streams, or to reduce the storage space required to archive them. The price for this compression is increased computational requirements: The higher the compression ratio, the more computational power is required.
Fixing the tradeoff between bandwidth and computational requirements has the effect of defining both the minimum channel bandwidth required to carry the encoded stream and the minimum specification of the decoding device. In traditional video systems such as broadcast television, the minimum specification of a decoder (in this case a set-top box) is readily defined.
Today, however, video is used in increasingly diverse applications with a correspondingly diverse set of client devices—from computers viewing Internet video to portable digital assistants (PDAs) and even the humble cell phone. The video streams for these devices are necessarily different.
To be made more compatible with a specific viewing device and channel bandwidth, the video stream must be encoded many times with different settings. Each combination of settings must yield a stream that targets the bandwidth of the channel carrying the stream to the consumer as well as the decode capability of the viewing device. If the original uncompressed stream is unavailable, the encoded stream must first be decoded and then re-encoded with the new settings. This quickly becomes prohibitively expensive.
In an ideal scenario, the video would be encoded only once with a high efficiency codec. The resulting stream would, when decoded, yield the full resolution video. Furthermore, in this ideal scenario, if a lower resolution or bandwidth stream was needed to reach further into the network to target a lower performance device, a small portion of the encoded stream would be sent without any additional processing. This smaller stream would be easier to decode and yield lower resolution video. In this way, the encoded video stream could adapt itself to both the bandwidth of the channel it was required to travel through and to the capabilities of the target device. These are exactly the qualities of a scalable video codec.
H.264 SVC
The Scalable Video Codec extension to the H.264 standard (H.264 SVC) is designed to deliver the benefits described in the preceding ideal scenario. It is based on the H.264 Advanced Video Codec standard (H.264 AVC) and heavily leverages the tools and concepts of the original codec. The encoded stream it generates, however, is scalable: temporally, spatially, and in terms of video quality. That is, it can yield decoded video at different frame rates, resolutions, or quality levels.
The SVC extension introduces a notion not present in the original H.264 AVC codec−that of layers within the encoded stream. A base layer encodes the lowest temporal, spatial, and quality representation of the video stream. Enhancement layers encode additional information that, using the base layer as a starting point, can be used to reconstruct higher quality, resolution, or temporal versions of the video during the decode process. By decoding the base layer and only the subsequent enhancement layers required, a decoder can produce a video stream with certain desired characteristics. Figure 1 shows the layered structure of an H.264 SVC stream. During the encode process, care is taken to encode a particular layer using reference only to lower level layers. In this way, the encoded stream can be truncated at any arbitrary point and still remain a valid, decodable stream.
(Click to enlarge)
Figure 1. The H.264 SVC Layered Structure.
This layered approach allows the generation of an encoded stream that can be truncated to limit the bandwidth consumed or the decode computational requirements. The truncation process consists simply of extracting the required layers from the encoded video stream with no additional processing on the stream itself. The process can even be performed "in the network". That is, as the video stream transitions from a high bandwidth to a lower bandwidth network (for example, from an Ethernet network to a handheld through a WiFi link), it could be parsed to size the stream for the available bandwidth. In the above example, the stream could be sized for the bandwidth of the wireless link and the decode capabilities of the handheld decoder. Figure 2 shows such an example as a PC forwards a low bandwidth instance of a stream to a mobile device.
Figure 2. Parsing Levels to Reduce Bandwidth and Resolution.
H.264 SVC Under the Hood
To achieve temporal scalability, H.264 SVC links its reference and predicted frames somewhat differently than conventional H.264 AVC encoders. Instead of the traditional Intra-frame (I frame), Bidirectional (B frame) and Predicted (P frame) relationship shown in Figure 3, SVC uses a hierarchical prediction structure.
(Click to enlarge)
Figure 3. Traditional I, P, and B Frame Relationship.
The hierarchical structure defines the temporal layering of the final stream. Figure 4 illustrates a potential hierarchical structure. In this particular example, frames are only predicted from frames that occur earlier in time. This ensures that the structure exhibits not only temporal scalability but also low latency.
(Click to enlarge)
Figure 4. Hierarchical Predicted Frames in SVC.
This scheme has four nested temporal layers: T0 (the base layer), T1, T2, and T3. Frames constituting the T1 and T2 layers are only predicted from frames in the T0 layer. Frames in the T3 layer are only predicted from frames in the T1 or T2 layers.
To play the encoded stream at 3.75 frames per second (fps), only the frames that constitute T0 need be decoded. All other frames can be discarded. To play the stream at 7.5 fps, the layers making up T0 and T1 are decoded. Frames in layers T2 and T3 can be discarded. Similarly, if frames that constitute T0, T1 and T2 are decoded, the resulting stream will play at 15 fps. If all frames are decoded, the full 30 fps stream is recovered.
By contrast, in H.264 AVC (for Baseline Profile where only unidirectional predicted frames are used), all the frames would need to be decoded irrespective of the desired display rate. To transit to a low bandwidth network, the entire stream would need to be decoded, the unwanted frames discarded, and then re-encoded.
Spatial scalability in H.264 SVC follows a similar principle. In this case, lower resolution frames are encoded as the base layer. Decoded and up-sampled base layer frames are used in the prediction of higher-order layers. Additional information required to reconstitute the detail of the original scene is encoded as a self-contained enhancement layer. In some cases, reusing motion information can further increase encoding efficiency.
Simulcast vs. SVC
There is an overhead associated with the scalability inherent in H.264 SVC. As can be seen in Figure 3, the distance between reference and predicted frames can be longer in time (from T0 to T1 for example) than with the conventional frame structure. In scenes with high motion, this can lead to slightly less efficient compression. There is also an overhead associated with the management of the layered structure in the stream.
Overall, an SVC stream containing three layers of temporal scalability and three layers of spatial scalability might be twenty percent larger than an equivalent H.264 AVC stream of full resolution and full frame rate video with no scalability. If scalability is to be emulated with the H.264 AVC codec, multiple encode streams are required, resulting in a dramatically higher bandwidth requirement or expensive decoding and re-encoding throughout the network.
Additional SVC Benefits
Error Resilience:
Error resilience is traditionally achieved by adding additional information to the stream so errors can be detected and corrected. SVC's layered approach means that a higher level of error detection and correction can be performed on the smaller base layer without adding significant overhead. Applying the same degree of error detection and correction to an AVC stream would require that the entire stream be protected, resulting in a much larger stream. If errors are detected in the SVC stream, the resolution and frame rate can be progressively degraded until, if needed, only the highly protected base layer is used. In this way, degradation under noisy conditions is much more graceful than with H.264 AVC.
Storage Management:
Since an SVC stream or file remains decodable even when truncated, SVC can be employed both during transmission and after the file is stored. Parsing files stored to disk and removing enhancement layers allows file size to be reduced without additional processing on the video stream stored within the file. This would not be possible with an AVC file which necessitates an "all or nothing" approach to disk management.
Content Management:
The SVC stream or file inherently contains lower resolution and frame rate streams. These streams can be used to accelerate the application of video analytics or for cataloging algorithms. The temporal scalability also makes the stream easier to search in fast forward or reverse.
An Application Case Study
A typical application for H.264 SVC is a surveillance system. (Stretch offers market-leading solutions in this area; see its web site for details.) Consider the case where an IP camera is sending a video feed to a control room where it is stored, and basic motion detection analytics are run on the stream. The video feed is viewed at the camera's maximum resolution (1280 x 720) on the control room monitors, and is stored in D1 (720 x 480) resolution to conserve disk space. A first-response team also has access to the stream in the field on mobile terminals within the response vehicle. The resolution of those displays is CIF (352 x 240) and the stream is served at 7 fps.
In an implementation using H.264 AVC, the first likely constraint would be that the camera serves multiple streams. In this example, one at 1280x720 resolution and one at 720 x 480 resolution. This places additional cost within the camera, but allows one stream to be directly recorded at the control room while another is decoded and displayed. Without this feature, an expensive decode, resize, and re-encode step would be needed. The D1 stream is also decoded and resized to CIF resolution to feed the video analytics being run on the stream. The CIF resolution video is temporally decimated to achieve 7 frames per second and re-encoded so that it can be made available to the first-response vehicle over a wireless link. Figure 5 shows a potential implementation of the system using H.264 AVC.
Figure 5. H.264 AVC Video Surveillance Application.
Using an H.264 SVC codec, the multi-stream requirement placed on the camera can be relaxed, reducing complexity and network bandwidth between the camera and control room. The full 1280 x 720 stream can now be stored on the network video recorder (NVR) with the knowledge that it can be easily parsed to create a D1 (or CIF) stream to free up disk space after a specified period. A CIF stream can be served directly from the NVR for analytics work, and a second stream at a reduced frame rate can be made available to the first-response vehicle. Figure 6 shows a potential H.264 SVC implementation.
Figure 6. H.264 SVC Video Surveillance Application.
At no point is there a need to operate on the video stream itself—operating on the stored file suffices. The advantages are clear:
- Reduced network bandwidth
- Flexible storage management
- Removal of expensive decode and re-encode stages
- High definition video available on the NVR for archive if needed
Conclusion
Scalable video codecs have been in development for many years. The broadcast industry, strictly controlled by well-established standards, has been slow to adopt this technology. Advances in processor, sensor, and display technology are fuelling an explosion in video adoption. The Internet and IP technologies are seamlessly serving video to an ever more diverse and remote community of display devices. Scalable video codecs such as H.264 SVC satisfy many of the demands of these systems, and they are poised to become a catalyst in wide the spread adoption of video as a communication medium.
About the author
Mark Oliver is the Director of Product Marketing at Stretch. A native of the UK, Oliver gained a degree in Electrical and Electronic Engineering from the University of Leeds. During a ten year tenure with Hewlett Packard, Oliver managed Engineering and Manufacturing functions in HP Divisions both in Europe and the US before heading up Product Marketing and Applications activities at a series of video related startups. Prior to joining Stretch, Oliver managed Marketing for Video and Imaging within the DSP Division of Xilinx.
Related Articles:
摘要: The Scalable Video Coding Amendment of the H.264/AVC Standardfunction StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection()... 阅读全文
以下转载于“ Jenny@博客大巴”
第一:看轻自己,重视别人;
曾经有一度,我以为自己相当重要,不仅拼搏着自己的理想,而且承载着别人的未来。我活得很辛苦很紧张,因为生活在他人的世界里。我在意别人的所思所想,我在乎别人的所作所为,周围的微小变化都能够影响到我内心的安宁。我开始焦虑不安,找很多朋友谈话。我知道她们都是对的,我明白她们在说什么,只是我无法说服自己。终于有一天,我顿悟了,所有这一切困惑,是因为我把自己太看重了。
我喜欢看月亮,从新月开始,到上弦月,到圆月,再到下弦月,最后到残月,周而复始,愈发感觉到天地的广袤和自我的渺小。当我真的开始看轻自己的时候,我进入一个全新的世界,周围每个人都能给我惊喜,无论是我崇拜之人,还是我泛泛之交。我发现了他/她们的优点,我理解了他/她们的苦衷,我开始珍惜和重视身边的每个人。我越来越快乐,越来越豁达,学会应该怎样和别人相处,让自己和他人都更舒服一点。
第二:时间是自己的,机会也是自己的;
不知什么时候我开始意识到日月如梭。眼见耳闻着所谓“英雄末路,美人迟暮”的故事在不断上演,唯有唏嘘不已,自我不断警醒。时间面前人人平等,关键在于如何最佳利用,实现最大价值化。人生本原本就没有意义,只是你如何描绘它。
年少无知的时候,我以为应该好好尽情享受青春的感觉,从来没有想到时间只拥有一次,20岁永远不会再来。现在浅薄如我,才发现“书到用时方恨少”。我还有很多书需要看,很多技能需要学习,很多专业知识需要巩固,很多朋友需要关心……不过幸运的是,任何时候都为时不晚,只要随时启程,就有新鲜的发现。机会也永远垂青有准备的人。
第三:平衡就健康。
我向来都知足常乐,极具阿Q精神。 每个人生活都不容易,也都有各自的精彩。活得简单一些,难得糊涂一点,会让自己的内心平和许多。
对于我,工作,家庭,生活,朋友,一个都不能少。我热爱工作,因为我在创造多重价值,个人资本、公司利益和社会责任。多说一句价值观的问题,没有人能给你判定价值几何,只有你自己。你的付出和回报在正常状况下是成正比的,不要过多要求别人,应该更多省视自己,自己做得够好了吗?!家庭是我珍视的,也永远是最安全的避风港,唯有亲人对自己无怨无悔。我向来要求生活品质,不求最贵的,也不求最好的,而是最适合自己的。朋友是我最大的财富,我全心全意地去维护这份感情,谢谢你们给我的一切,甘为树洞,是我莫大的荣幸!
一位心理医生和一位30岁女白领的对话,她想纠正自己最近几个月里总是拖延工作的恶习。
“你喜欢吃蛋糕吗?”“喜欢。” “你喜欢先吃蛋糕,还是蛋糕上的奶油?” “当然是奶油啦!我通常先吃完奶油,然后才吃蛋糕的。”
医生从吃蛋糕的习惯出发,重新讨论她对待工作的态度。正如医生预料的,在上班第一个钟头,她总是把容易和喜欢做的工作先完成,而在剩下6个钟头里,她就尽量规避棘手的差事。
医生建议她从现在开始,在上班第一个钟头,要先去解决那些麻烦的差事,在剩下的时间里,其他工作会变得相对轻松。医生解释其中的道理说:按1天工作7个钟头计算,1个钟头的痛苦与6个钟头的幸福,显然要比1个钟头的幸福,加上6个钟头的痛苦划算。
她完全同意这样的计算方法,而且坚决照此执行,不久就彻底克服了拖延工作的毛病。
这就是推迟满足感,它意味着你不能贪图暂时的安逸,你得重新设置人生快乐与痛苦的次序:首先,面对问题并感受痛苦;然后,解决问题并享受更大的快乐,这是惟一可行的生活方式。
[转载]习惯的力量:35岁之前如何可以做得很成功
习惯的力量是惊人的。习惯能载着你走向成功,也能驮着你滑向失败。如何选择,完全取决于你自己。
1、习惯的力量:35岁以前养成好习惯
你想成功吗?那就及早培养有利于成功的好习惯。
习惯的力量是惊人的,35岁以前养成的习惯决定着你是否成功。
有这样一个寓言故事:
一位没有继承人的富豪死后将自己的一大笔遗产赠送给远房的一位亲戚,这位亲戚是一个常年靠乞讨为生的乞丐。这名接受遗产的乞丐立即身价一变,成了百万富翁。新闻记者便来采访这名幸运的乞丐:“你继承了遗产之后,你想做的第一件事是什么?”乞丐回答说:“我要买一只好一点的碗和一根结实的木棍,这样我以后出去讨饭时方便一些。”
可见,习惯对我们有着绝大的影响,因为它是一贯的,在不知不觉中,经年累月地影响着我们的行为,影响着我们的效率,左右着我们的成败。
一个人一天的行为中,大约只有5%是属于非习惯性的,而剩下的95%的行为都是习惯性的。即便是打破常规的创新,最终可以演变成为习惯性的创新。
根据行为心理学的研究结果:3周以上的重复会形成习惯;3个月以上的重复会形成稳定的习惯,即同一个动作,重复3周就会变成习惯性动作,形成稳定的习惯。
亚里士多德说:“人的行为总是一再重复。因此,卓越不是单一的举动,而是习惯。”
“人的行为总是一再重复。因此,卓越不是单一的举动,而是习惯。”所以,在实现成功的过程中,除了要不断激发自己的成功欲望,要有信心、有热情、有意志、有毅力等之外,还应该搭上习惯这一成功的快车,实现自己的目标。
有个动物学家做了一个实验:他将一群跳蚤放入实验用的大量杯里,上面盖上一片透明的玻璃。跳蚤习性爱跳,于是很多跳蚤都撞上了盖上的玻璃,不断地发叮叮冬冬的声音。过了一阵子,动物学家将玻璃片拿开,发现竟然所有跳蚤依然在跳,只是都已经将跳的高度保持在接近玻璃即止,以避免撞到头。结果竟然没有一只跳蚤能跳出来——依它们的能力不是跳不出来,只是它们已经适应了环境。
后来,那位动物学家就在量杯下放了一个酒精灯并且点燃了火。不到五分钟,量杯烧热了,所有跳蚤自然发挥求生的本能,每只跳蚤再也不管头是否会撞痛(因为它们以为还有玻璃罩),全部都跳出量杯以外。这个试验证明,跳蚤会为了适应环境,不愿改变习性,宁愿降低才能、封闭潜能去适应。
我想,人类之于环境也是如此。人类在适应外界大环境中,又创造出适合于自己的小环境,然后用习惯把自己困在自己所创造的环境中。所以,习惯决定着你的活动空间的大小,也决定着你的成败。养成好习惯对于你的成功非常重要。
心理学巨匠威廉·詹姆士说:“播下一个行动,收获一种习惯;播下一种习惯,收获一种性格;播下一种性格,收获一种命运。”
2、35岁以前成功必备的9大习惯
好习惯会使成功不期而至。
好习惯会使成功不期而至。我认为下面9个好习惯是成功必备的:
(1)积极思维的好习惯
有位秀才第三次进京赶考,住在一个经常住的店里。考试前两天他做了三个梦:第一个梦是梦到自己在墙上种白菜,第二个梦是下雨天,他戴了斗笠还打着伞,第三个梦是梦到跟心爱的表妹脱光了衣服躺在一起,但是背靠着背。临考之际做此梦,似乎有些深意,秀才第二天去找算命的解梦。算命的一听,连拍大腿说:“你还是回家吧。你想想,高墙上种菜不是白费劲吗?戴斗笠打雨伞不是多此一举吗?跟表妹脱光了衣服躺在一张床上,却背靠背,不是没戏吗?”秀才一听,心灰意冷,回店收拾包裹准备回家。
店老板非常奇怪,问:“不是明天才考试吗?今天怎么就打道回府了?”秀才如此这般说了一番,店老板乐了:“唉,我也会解梦的。我倒觉得,你这次一定能考中。你想想,墙上种菜不是高种吗?戴斗笠打伞不是双保险吗?跟你表妹脱光了背靠背躺在床上,不是说明你翻身的时候就要到了吗?”秀才一听,更有道理,于是精神振奋地参加考试,居然中了个探花。
可见,事物本身并不影响人,人们只受到自己对事物看法的影响,人必须改变被动的思维习惯,养成积极的思维习惯。
怎样才算养成了积极思维的习惯呢?当你在实现目标的过程中,面对具体的工作和任务时,你的大脑里去掉了“不可能”三个字,而代之以“我怎样才能”时,可以说你就养成了积极思维的习惯了。
(2)高效工作的好习惯
一个人成功的欲望再强烈,也会被不利于成功的习惯所撕碎,而溶入平庸的日常生活中。所以说,思想决定行为,行为形成习惯,习惯决定性格,性格决定命运。你要想成功,就一定要养成高效率的工作习惯。
确定你的工作习惯是否有效率,是否有利于成功,我觉得可以用这个标准来检验:即在检省自己工作的时候,你是否为未完成工作而感到忧虑,即有焦灼感。如果你应该做的事情而没有做,或做而未做完,并经常为此而感到焦灼,那就证明你需要改变工作习惯,找到并养成一种高效率的工作习惯。
高效工作从办公室开始:
1)了解你每天的精力充沛期。通常人们在早晨9点左右工作效率最高,可以把最困难的工作放到这时来完成。
2)每天集中一、两个小时来处理手头紧急的工作,不接电话、不开会、不受打扰。这样可以事半功倍。
3)立刻回复重要的邮件,将不重要的丢弃。若任它们积累成堆,反而更费时间。
4)做个任务清单,将所有的项目和约定记在效率手册中。手头一定要带着效率手册以帮助自己按计划行事。一个人一天的行为中,大约只有5%是属于非习惯性的,而剩下的95%的行为都是习惯性的。
5)学会高效地利用零碎时间,用来读点东西或是构思一个文件,不要发呆或做白日梦。
6)减少回电话的时间。如果你需要传递的只是一个信息,不妨发个手机短信。
7)对可能打来的电话做到心中有数,这样在你接到所期待的电话后便可迅速找到所需要的各种材料,不必当时乱翻乱找。
8)学习上网高效搜寻的技能,以节省上网查询的时间。把你经常要浏览的网站收集起来以便随时找到。
9)用国际互联网简化商业旅行的安排。多数饭店和航线可以网上查询和预订。
10)只要情况允许就可委派别人分担工作。事必躬亲会使自己疲惫不堪,而且永远也做不完。不妨请同事帮忙,或让助手更努力地投入。
11)做灵活的日程安排,当你需要时便可以忙中偷闲。例如,在中午加班,然后早一小时离开办公室去健身,或是每天工作10个小时,然后用星期五来赴约会、看医生。
12)在离开办公室之前开列次日工作的清单,这样第二天早晨一来便可以全力以赴。
凡事有计划
计划习惯,就等于计划成功。
凡事制定计划有个名叫约翰·戈达德的美国人,当他15岁的时候,就把自己一生要做的事情列了一份清单,被称做“生命清单”。在这份排列有序的清单中,他给自己所要攻克的127个具体目标。比如,探索尼罗河、攀登喜马拉雅山、读完莎士比亚的著作、写一本书等。在44年后,他以超人的毅力和非凡的勇气,在与命运的艰苦抗争中,终于按计划,一步一步地实现了106个目标,成为一名卓有成就的电影制片人、作家和演说家。
中国有句老话:“吃不穷,喝不穷,没有计划就受穷。”尽量按照自己的目标,有计划地做事,这样可以提高工作效率,快速实现目标。
(3)养成锻炼身体的好习惯
增强保健意识
计划习惯,就等于计划成功。如果你想成就一番事业,你就必须有一个健康的身体;要想身体健康,首先要有保健意识。
我认识一个大学教师,身体一直很健康。早些时候,我们经常在一起玩。在谈及各人身体状况时,他说肾部偶尔有轻微不适的感觉。我们曾劝他去医院检查一下,但他自恃身体健康,不以为意。直至后来感觉比较疼痛,其爱人才强迫他去检查。诊断结果是晚期肾癌。虽经手术化疗的等治疗措施,但终未能保住生命,死时才39岁。此前,他曾因学校分房、评职称不如意,心情一直抑郁,他的病和情绪有关,但如果他保健意识强,及早去检查,完全有可以进行预防,消患于未萌。保健意识差,让他付出了生命的代价。
如何落实保健意识呢?一是要有生命第一、健康第一的意识,有了这种意识,你就会善待自己的身体、自己的心理,而不会随意糟踏自己的身体。二是要注意掌握一些相关的知识。三是要使自己有一个对身体应变机制:定期去医院做身体检查;身体觉得有不适的地方,应及早去医院检查;在有条件的情况下,可以请一个保健医生,给自己的健康提出忠告。
有计划地锻炼身体
锻炼身体的重要性已经越来越多地为人们所接受,但我感觉很多人只停留在重视的意识阶段,而缺乏相应的行动。我认为锻炼既要针对特定工作姿势所能引发的相应疾病有目的地进行,以防止和治疗相应的疾病,更要把锻炼当作一种乐趣,养成锻炼的习惯。
因为工作需要,我经常与客户打交道,并因处理突发事情四处奔忙,这在一定程度起到了锻炼身体的作用,同时,我还每周坚持游泳一到两次,以保证有足够的精力去做工作,去享受生活。
身体锻炼,就像努力争取成功一样,贵在坚持。
除上述两点以,注意饮食结构,合理膳食,以及注意养成好的卫生习惯等,都是养成健康习惯的组成部分。
总之,健康是“革命”的本钱,是成功的保证。健康成就自己。
(4)不断学习的好习惯
“万般皆下品,唯有读书高”的年代已经过去了,但是养成读书的好习惯则永远不会过时。
哈利·杜鲁门是美国历史上著名的总统。他没有读过大学,曾经营农场,后来经营一间布店,经历过多次失败,当他最终担任政府职务时,已年过五旬。但他有一个好习惯,就是不断地阅读。多年的阅读,使杜鲁门的知识非常渊博。他一卷一卷地读了《大不列颠百科全书》以及所有查理斯·狄更斯和维克多·雨果的小说。此外,他还读过威廉·莎士比亚的所有戏剧和十四行诗等。
杜鲁门的广泛阅读和由此得到的丰富知识,使他能带领美国顺利度过第二次世界大战的结束时期,并使这个国家很快进入战后繁荣。他懂得读书是成为一流领导人的基础。读书还使他在面对各种有争议的、棘手的问题时,能迅速做出正确的决定。例如,在20世纪50年代他顶住压力把人们敬爱的战争英雄道格拉斯·麦克阿瑟将军解职。
他的信条是:“不是所有的读书人都是一名领袖,然而每一位领袖必须是读书人。”
美国前任总统克林顿说:在19世纪获得一小块土地,就是起家的本钱;而21世纪,人们最指望得到的赠品,再也不是土地,而联邦政府的奖学金。因为他们知道,掌握知识就是掌握了一把开启未来大门的钥匙。”
每一个成功者都是有着良好阅读习惯的人。世界500家大企业的CEO至少每个星期要翻阅大概30份杂志或图书资讯,一个月可以翻阅100多本杂志,一年要翻阅1000本以上。
世界500家大企业的CEO至少每个星期要翻阅大概30份杂志或图书资讯,一个月可以翻阅100多本杂志,一年要翻阅1000本以上。如果你每天读15分钟,你就有可能在一个月之内读完一本书。一年你就至少读过12本书了,10年之后,你会读过总共120本书!想想看,每天只需要抽出15分钟时间,你就可以轻易地读完120本书,它可以帮助你在生活的各方面变得更加富有。如果你每天花双倍的时间,也就是半个小时的话,一年就能读25本书——10年就是250本!
我觉得,每一个想在35岁以前成功的人,每个月至少要读一本书,两本杂志。
(5)谦虚的好习惯
一个人没有理由不谦虚。相对于人类的知识来讲,任何博学者都只能是不及格。
著名科学家法拉第晚年,国家准备授予他爵位,以表彰他在物理、化学方面的杰出贡献,但被他拒绝了。法拉第退休之后,仍然常去实验室做一些杂事。一天,一位年轻人来实验室做实验。他对正在扫地的法拉第说道:“干这活,他们给你的钱一定不少吧?”老人笑笑,说道:“再多一点,我也用得着呀。”“那你叫什么名字?老头?”“迈克尔·法拉第。”老人淡淡地回答道。年轻人惊呼起来:“哦,天哪!您就是伟大的法拉第先生!”“不”,法拉第纠正说,“我是平凡的法拉第。”
谦虚不仅是一种美德,更是是一种人生的智慧,是一种通过贬低自己来保护自己的计谋。
(6)自制的好习惯
任何一个成功者都有着非凡的自制力。
三国时期,蜀相诸葛亮亲自率领蜀国大军北伐曹魏,魏国大将司马懿采取了闭城休战、不予理睬的态度对付诸葛亮。他认为,蜀军远道来袭,后援补给必定不足,只要拖延时日,消耗蜀军的实力,一定能抓住良机,战胜敌人。
诸葛亮深知司马懿沉默战术的利害,几次派兵到城下骂阵,企图激怒魏兵,引诱司马懿出城决战,但司马懿一直按兵不动。诸葛亮于是用激将法,派人给司马懿送来一件女人衣裳,并修书一封说:“仲达不敢出战,跟妇女有什么两样。你若是个知耻的男儿,就出来和蜀军交战,若不然,你就穿上这件女人的衣服。”
“士可杀不可辱。”这封充满侮辱轻视的信,虽然激怒了司马懿,但并没使老谋深算的司马懿改变主意,他强压怒火稳住军心,耐心等待。
相持了数月,诸葛亮不幸病逝军中,蜀军群龙无首,悄悄退兵,司马懿不战而胜。
抑制不住情绪的人,往往伤人又伤己如果司马懿不能忍耐一时之气,出城应战,那么或许历史将会重写。
现代社会,人们面临的诱惑越来越多,如果人们缺乏自制力,那么就会被诱惑牵着鼻子走,偏离成功的轨道。
(7)幽默的好习惯
有人说,男人需要幽默,就像女人需要一个漂亮的脸蛋一样重要。
男人需要幽默,就像女人需要一个漂亮的脸蛋一样重要。美国第16任总统林肯长相丑陋,但他从不忌讳这一点,相反,他常常诙谐地拿自己的长相开玩笑。在竞选总统时,他的对手攻击他两面三刀,搞阴谋诡计。林肯听了指着自己的脸说:“让公众来评判吧。如果我还有另一张脸的话,我会用现在这一张吗?”还有一次,一个反对林肯的议员走到林肯跟前挖苦地问:“听说总统您是一位成功的自我设计者?”“不错,先生。”林肯点点头说,“不过我不明白,一个成功的设计者,怎么会把自己设计成这副模样?”林肯就是这种幽默的方法,多次成功地化解了可能出现的尴尬和难堪场面。
没有幽默的男人不一定就差,但懂得幽默的男人一定是一个优秀的人,懂得幽默的女人更是珍稀动物。
(8)微笑的好习惯
微笑是大度、从容的表现,也是交往的通行证。
举世闻名的希尔顿大酒店,其创建人希尔顿在创业之初,经过多年探索,最终发现了一条简单、易行、不花本钱的经营秘诀——微笑。从此,他要求所有员工:无论饭店本身遭遇到什么困难,希尔顿饭店服务员脸上的微笑永远是属于顾客的阳光。这束“阳光”最终使希尔顿饭店赢得了全世界一致好评。
在欧美发达国家,人们见面都要点头微笑,使人们相互之间感到很温暖。而在中国,如果你在大街上向一个女士微笑,那么你可能被说成“有病”。向西方人学习,让我们致以相互的微笑吧。
从古至今,敬业是所有成功人士最重要的品质之一。
(9)敬业、乐业的好习惯
敬业是对渴望成功的人对待工作的基本要求,一个不敬业的人很难在他所从事的工作中做出成绩。
美国标准石油公司有一个叫阿基勃特的小职员,开始并没有引起人们的特别注意。他的敬业精神特别强,处处注意维护和宣传企业的声誉。在远行住旅馆时总不忘记在自己签名的下方写上“每桶四美元的标准石油”字样,在给亲友写信时,甚至在打收条时也不例外,签名后总不忘记写那几个字。为此,同事们都叫他“每桶四美元”。这事被公司的董事长洛克菲勒知道了,他邀请阿基勃特共进晚餐,并号召公司职员向他学习。后来,阿基勃特成为标准石油公司的第二任董事长。
3、35岁以前成功必须戒除的9大恶习
坏习惯使成功寸步难行。
与建立良好习惯相应的,是克服不良习惯。不破不立,不改掉不良习惯,好习惯是难以建立起来的。
古希腊的佛里几亚国王葛第士以非常奇妙的方法,在战车的轭打了一串结。他预言:谁能打开这个结,就可以征服亚洲。一直到公元前334年还没有一个人能将绳结打开。这时。亚历山大率军入侵小亚细亚,他来到葛第士绳结前,不加考虑便拔剑砍断了它。后来,他果然一举占领了比希腊大50倍的波斯帝国。
一个孩子在山里割草,不小心被毒蛇咬伤了脚。孩子疼痛难忍,而医院在远处的小镇上。孩子毫不犹豫地用镰刀割断受伤的脚趾,然后忍着巨痛艰难地走到医院。虽然缺少了一个脚趾,但这个孩子以短暂的疼痛保住了自己的生命。
改掉坏习惯,就应该有亚历山大的气概,就应有那个小孩的果断和勇敢,彻底改掉坏习惯,让好习惯引领自己走向成功。
以下这9大恶习是你必须戒除的:
1)经常性迟到。你上班或开会经常迟到吗?迟到是造成使老板和同事反感的种子,它传达出的信息:你是一个只考虑自己、缺乏合作精神的人。
2)拖延。虽然你最终完成了工作,但拖后腿使你显得不胜任。为什么会产生延误呢?如果是因为缺少兴趣,你就应该考虑一下你的择业;如果是因为过度追求尽善尽美,这毫无疑问会增多你在工作中的延误。社会心理学专家说:很多爱拖延的人都很害怕冒险和出错,对失败的恐惧使他们无从下手。
3)怨天尤人。这几乎是失败者共同的标签。一个想要成功的人在遇到挫折时,应该冷静地对待自己所面临的问题,分析失败的原因,进而找到解决问题的突破口。
4)一味取悦他人。一个真正称职的员工应该对本职工作内存在的问题向上级说明并提出相应的解决办法,而不应该只是附和上级的决定。对于管理者,应该有严明的奖惩方式,而不应该做“好好先生”,这样做虽然暂时取悦了少数人,却会失去大多数人的支持。
5)传播流言。每个人都可能会被别人评论,也会去评论他人,但如果津津乐道的是关于某人的流言蜚语,这种议论最好停止。世上没有不透风的墙,你今天传播的流言,早晚会被当事人知道,又何必去搬石头砸自己的脚?所以,流言止于智者。
6)对他人求全责备、尖酸刻薄。每个人在工作中都可能有失误。当工作中出现问题时,应该协助去解决,而不应该一味求全责备。特别是在自己无法做到的情况下,让自己的下属或别人去达到这些要求,很容易使人产生反感。长此以往,这种人在公司没有任何威信而言。
7)出尔反尔。已经确定下来的事情,却经常做变更,就会让你的下属或协助员工无从下手。你做出的承诺,如果无法兑现,会在大家面前失去信用。这样的人,难以担当重任。
8)傲慢无礼。这样做并不能显得你高人一头,相反会引起别人的反感。因为,任何人都不会容忍别人瞧不起自己。傲慢无礼的人难以交到好的朋友。人脉就是财脉,年轻时养成这种习惯的人,相信你很难取得成功。
9)随大流。人们可以随大流,但不可以无主见。如果你习惯性地随大流,那你就有可能形成思维定势,没有自己的主见,或者既便有,也不敢表达自己的主见,而没有主见的人是不会成功的。
jndi全局注册表和enc的基本概念 |
通俗的将jndi就是对ejb容器中所有的资源和组件进行管理的花名册,通过该服务,可以很方便的找到希望使用的资源。当组件被部署到服务器上后,该组件就会被自动注册到花名册上,以便用户使用,如果组件被卸载,花名册上的记录就会自动消失。
jndi中注册的所有的资源和组件可以被服务器内外的各种程序请求或者访问,是一种全局性的资源!但是ejb中不同的组件通过全局性的jndi服务器形成依赖关系,则会给系统造成不稳定的因素!因此就引入了enc(ejb组件的企业名称上下文)的概念!通过她来实现不同组件之间的引用关系!!!!
在上一篇文章中写到了通过标注的方式实现方向依赖注入!还以上篇为例:
有接口:HelloWordRemote HelloWordLocal ICal(Remote)
而HelloWordBean实现了分别实现了他们
另外又有了个远程接口:
@Remote
public Interface MyService{
public String helloWord();
public int add(int a,int b);
}
一个类想实现这个接口并且在这个类中引用了...如下:
@Stateless
public class FacedServcie implements MyService{
private HelloWordLocal myserv1;
private ICal ical;
.....
....
}
可以通过配置文件实现反向依赖注入:
<ejb-jar
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
version="3.0">
<enterprise-beans>
<session>
<ejb-name>FacedServcie</ejb-name>
<ejb-ref>
<ejb-ref-name>abc1</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<remote>com.ICal</remote>
<mapped-name>HelloWordBean1/remote</mapped-name>
<injection-target>
<injection-target-class>
xiaoxiao.FacedService
</injection-target-class>
<injection-target-name>
ical
</injection-target-name>
</injection-target>
</ejb-ref>
.........(对于另一个组件的配置)
</session>
</enterprise-beans>
</ejb-jar>
还可以通过检索的方式来实现:
@Stateless
public class FacedServcie implements MyService{
private HelloWordLocal myserv1;
private ICal ical;
public String helloWord(){
try{
InitialContext ctx=new InitalContext();
ical=(ICal)ctx.lookup("java:comp/env/abc1");
//其中java:comp/env是组件局部enc所有记录的根路径而abc1是在配置文件中注册的名字!
}catch(NamingException e){}
if(ical!=null){
return ical.helloWord();
}else{
return "error!";
}
}
....
}
配置文件如下:
<ejb-jar
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
version="3.0">
<enterprise-beans>
<session>
<ejb-name>FacedServcie</ejb-name>
<ejb-ref>
<ejb-ref-name>abc1</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<remote>com.ICal</remote>
<mapped-name>HelloWordBean1/remote</mapped-name>
</ejb-ref>
.........(对于另一个组件的配置)
</session>
</enterprise-beans>
</ejb-jar>
本人建议使用第一种反向依赖注入的方式!
还有其他的一些注入:如持久化单元注入,资源型注入 数据源类型的注入。。。
|
|
|
|
EJB事务 |
在ejb组件设计中,组件行为有时需要具备事务特征,即使用事务保证组件行为的完整性,使组件要么执行成功,要么回到起点.等价没有执行!
讨论事务时要明确两个概念:
事务范围
算法的可恢复性与事务性:如果事务中的算法动作结果受事务提交或者回滚影响,则该算法具有事务可恢复性,否则就不具备事务可恢复性.
事务在本质上就是一个管理系列算法动作一致性的对象!ejb提供了两种事务类型:声明性和程序性事务
声明性事务:由ejb容器负责事务对象的 生成,管理,销毁;具体算法在事务上的注册,事务的提交和回滚等
主要介绍声明性的事务:
ejb容器为其中的 所有的ejb组件提供了一种默认的事务模式:Requires
在该模式下面,组件中的方法如果在事务环境下被调用(即客户端调用了该组件的方法),则方法中的逻辑会被添加到客户端的事务环境中,和客户端的程序使用相同的事务控制对象.如果不在事务环境中调用(在客户端没有调用该组件中的方法),ejb容器就创建新的事务对象,管理该方法中的所有逻辑.
例如:
ejb组件:
@Statefull
public class personmanager inplements IPersonAdmin{
@PersistenceContext(unitName="mydb")
private EntityManager manager;
@EJB(mappedName="MySession/remote")
private IPersonAdmin mytools;
public List<person> QueryAll(){
....
}
public void createPerson(Person p){
Person pobj=new Person();
pobj.setName("ziaoxioa");
#1 manager.persist(pobj);
#2 mytools.createPerson(p);
#3 manager.persist(null);
}
客户代码:
...
myinf.createPerson(p);
...
默认情况下,ejb读物起会为ejb组件中的所有方法配置一中requires型的事务服务.在这种事务模式下面,如果方法被在事务环境下调用,方法就使用客户端事务对象和事务环境ruguo不在事务环境中被调用,则ejb容器就会创建新的事务对象和环境来负责管理该方法的逻辑完整性!由于上面的#3错误,所以数据库中不会添加任何记录!
ejb容器为ejb组件添加的默认的事务策略能够满足多数情况下的算法要求,特殊情况下,可以通过@TransactionAttribute和<container-transaction>标记修改组件的默认事务策略!如下:
<ejb-jar
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
version="3.0">
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>MySession</ejb-name>
<method-name>createPerson</method-name>
</method>
<trans-attribute>RequiresNew</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>
@TransactionAttribute(REQUIRES_NEW)
public void createPerson(Person p){
manager.persist(p);
}
这样MySession中的createPerson方法事务修改成了RequiesNew模式,在这种模式下,ejb容器不论客户端是否具有事务特征,为createPerson创建一个新的事务对象,此时两个createPerson在完全不同的事务对象控制下,所以#2可以提交到数据库中,#1,#3则回滚
声明性事务模式:
Required |
ejb容器为ejb组件方法提供的默认事务模式,在这种模式下,如果调用程序具备自身的事务对象,则组件方法就和客户程序使用相同的事务对象,否则ejb容器就会创建新的事务对象来管理组件方法逻辑 |
Supports |
在这种模式下,如果调用程序具备事务特征,则组件方法就会调用调用程序事务对象管理自身逻辑,如果调用程序不包含任何的事务对象,则组件方法也处于无事务管理状态 |
NotSupported |
这种模式下,组件方法不支持事务,同时也会忽略掉调用程序中的事务对象,组件方法中的逻辑不受客户程序事务的提交或回滚的影响 |
RequiresNew |
在这种模式下,忽略调用程序具备的事务特征,ejb容器会新创建一个新的事务对象管理组件方法逻辑 |
Mandatory |
ejb容器不会为该方法创建新的事务管理对象。该组件方法的调用程序必须提供事务对象,处于事务环境中,否则程序将产生异常javax.ejb.EJBTransactionRequiredException
|
Never |
这种模式下,该方法不会被ejb容器提供事务对象服务,并且调用程序也不能处于事务环境中,否则将产生EJBException异常
|
下面的程序首先清楚组件上的默认事务模式,然后在为方法设定具体事务属性:
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>MySession</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>NotSupported</trans-attribute>
</container-transaction>
<container-transaction>
<method>
<ejb-name>MySession</ejb-name>
<method-name>createPerson</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
声明性事务的控制:
@Stateless
/*10*/public class PersonManager implements IPersonAdmin
/*11*/{
/*12*/ @Resource
/*13*/ private EJBContext ctx;
/*14*/ @PersistenceContext(unitName="mydb")
/*15*/ private EntityManager manager;
/*16*/ @EJB(mappedName="MySession/remote")
/*17*/ private IPersonAdmin mytools;
/*18*/ public List<Person> QueryAll()
/*19*/ {
/*20*/ Query q=manager.createQuery("from Person c");
/*21*/ List results=q.getResultList();
/*22*/ List<Person> result=(List<Person>)results;
/*23*/ return result;
/*24*/ }
/*25*/ public void createPerson(Person p)
/*26*/ {
/*27*/ Person pobj=new Person();
/*28*/ pobj.setName("zhanghao");
/*29*/ pobj.setAge(new Integer(32));
/*30*/ pobj.setSex("male");
/*31*/ manager.persist(pobj);
/*32*/ boolean result=ctx.getRollbackOnly();
/*33*/ if(!result)
/*34*/ {
/*35*/ ctx.setRollbackOnly();
/*36*/ }
/*37*/ }
/*38*/}
该方法使用gejb容器提供的默认的事务模式,事务会在方法结束时自动提交。
getRollbackOnly()返回房前事务的状态,true表示已经回滚,false表示没有回滚。
|
|
|
|
视频总结-jndi |
jndi:java命名和目录接口
jndi把object和context(还可以有subcontext)组织成一个jndi树
这样object就可一被绑定到不同的context上面
jndi是一种查找服务,用于查找:
web应用环境变量
EJB和他们的环境变量
通过DataSource的数据库连接池
JMS没有表和连接工厂
其他服务
不要将jndi当做数据库使用
jndi对象存储在内存中
访问jndi对象与网络性能有关
jndi树:
InitialContext是JNDI树所有搜索的起点
对象绑定到jndi树上,java对象是树叶,context是节点
一个绑定把对象与一个逻辑名和一个context关联起来
创建Initial Context
从服务器端对象连接到jndi
//创建一个InitialContext
context ctx=new InitialContext();//链接到当前的jndi树上
从任何一个地方连接到jndi
.创建Environment对象
weblogic.jndi.Enviroment env=new Weblogix.jndi.Enviroment();
填写Enviroment
env.setProviderurl("t3://127.0.0.1:7001");//weblogic server的位置
env.setSecurityPrincipal("system");//安全信息
env.setSecurityCredentiais("password");
//使用Environment对象创建InitialContext
context ctx=env.getInitialContext();
.hashtable的用法....
创建subcontext
创建一个用于绑定对象的subcontext
创建Environment对象
context ctx=env.getInitialContext();//首先获得已经存在的subcontext或者initialcontext
填写Environment
context subcontext=ctx.createSubcontext("newSubcontext");
subcontext.rebind("boundobject",object);
subcontext.close();
ctx.close();
其他链接到jndi的方法:
使用ConstantProperties名和hashtable类:
HashTable env=new HashTable();
env.put(Context.initial_context_factory,"weblogic.jndi.WLInitialContextFactory");
env.put(Context.procider_url,"t3://localhost:7001");
env.put(Context.security_principal,"system");
env.put(Context.crrdentials,"password");
Context ctx=new InitialContext(env);
另一个例子:使用hardcoded名和properties类
Properties env=new Properties();
env.setProperties("java.naming.factory.initial","weblogic.jndi.WLInitialContextFactory");
env.setProperties("java.naming.provider.url","t3://localhost:7001")
env.setProperties("java.naming.security.principal","system");
env.setProperties("java.naming.security.credentials","password");
Context ctx=new InitialContext(env);
jndi.properties
.jndi.properties文件为所有的Initial Contexts设置默认的属性
.jndi.properties文件的搜索顺序
.classpath
.$JAVA_HOME/lib
实例:
java.naming.factoyr.initial=weblogic.jndi.WLInitialContextFactory
java.naming.security.url=t3://localhost:7001
java.naming.security.pricipal=system
java.naming.security.credentials=password
使用默认值:
Context ctx=new InitialContext();
从jndi查找:
.lookup()从jndi树获得对象
.通过lookup()返回的对象必须映射到他们合适的类型
try{
//先获得InitialContext
//Context ic=new Context();
Object obj;
obj=ic.lookup("javax.transation.UserTransaction");
UserTransaction ut=(UserTransaction)obj;
ut.begin();
.....
ic.close();
}catch(NamingEcxeption e){....}
远程绑定对象:
.远程绑定到远程命名服务的对象必须是序列化的
.访问命名服务时,对象是采用复制机制
查找的对象是序列化到客户端的
一个binding实例:
public static Context getInitialContext()throws NamingException{
创建Environment对象
weblogic.jndi.Environment env=new Weblogix.jndi.Environment();
填写Enviroment
env.setProviderurl("t3://127.0.0.1:7001");//weblogic server的位置
env.setSecurityPrincipal("system");//安全信息
env.setSecurityCredentiais("password");
//使用Environment对象创建InitialContext
context ctx=env.getInitialContext();
return ctx;
}
//获得Initial Context
Context ctx=getInitialContext();
//创建名为band的对象
Bank myBank=new Bank();
//把对象绑定到jndi树
ctx.rebind("theBank",myBank);
ctx.close();
|
|
|
|
EJB3.0中的依赖注入,截获器及其在WebLogic Server 10中的扩展2007-09-05 来自:lizhe1985 [收藏到我的网摘]
1 前言
与EJB2.1相比,EJB3.0规范引入了两个重要概念:依赖注入(DI:Dependency Injection)和截获器(Interceptor),本文首先介绍了这两个概念并给出相关示例,然后分析了EJB3.0规范在这两方面的不足之处,最终深入探讨了WebLogic Server 10对它们的支持和扩展。
2 依赖注入
2.1 基本概念
依赖注入是从开源社区的一些著名轻量级容器(如Spring、Pico container)中所发展出来的概念,其主要思想就是由容器而不是对象本身来负责处理对象之间的依赖关系。与传统的服务定位器相比,依赖注入具有易测试、弱侵入性等优点,这也就是为什么在最新的Java EE 5规范中引入它的原因。
对于EJB3.0来说,依赖注入就是由容器负责查找被依赖的对象并注入到依赖bean中,而bean本身不再需要进行JNDI或者context查询。此外,依赖注入发生在任何业务方法被调用之前,而且支持setter方法注入和域注入两种方式。
通过与标注结合使用,在bean类中声明依赖注入是非常简单的(当然,也可以在部署描述符文件中声明依赖注入):
@EJB用于注入EJB业务对象
@PersistenceUnit 用于注入EntityManagerFactory
@PersistenceContext 用于注入EntityManager
@Resource 用于注入其它资源对象,如连接工厂、消息目标等
2.2 示例
@Stateless
public class ServiceBean implements Service {
private javax.sql.DataSource myDS;
@Resource(mappedName=“LocalDataSource")
public void setMyDS(javax.sql.DataSource ds) {this.myDS = ds; }
@EJB(beanName=“AccountBean")
private Account account;
}
在无状态会话bean ServiceBean中,声明了两个依赖:一个是数据源,一个是业务接口。在运行期间,EJB3.0容器一旦创建了ServiceBean的实例,就会分别通过方法注入和域注入将数据源对象和业务对象注入到ServiceBean中。
3 截获器
3.1 基本概念
作为EJB3.0中提出的新概念,截获器是可以对bean的业务方法和生命周期事件进行拦截的组件。截获器需要由@Interceptors 或发布描述符文件中相关的标签指定。截获器可以带有状态而且可以进行依赖注入,其生命周期与其所绑定的EJB bean实例的生命周期一致。
定义在截获器中用于拦截目的的方法被称为截获器方法,其中,针对业务方法的截获器方法通过@AroundInvoke标注或发布描述符文件中相关的标签指定;针对生命周期回调的截获器方法通过@PostConstruct, @PreDestroy等标注或发布描述符文件中对应的标签指定。
截获器分为四类:
缺省截获器:可作用于ejb-jar中定义的所有EJB bean。缺省截获器只能定义在DD中,不存在相应的标注
类级截获器:只能作用于所指定的EJB bean
方法级截获器:只能作用于所指定的某个EJB bean业务方法,方法级截获器不能用于拦截bean的生命周期事件
bean 级截获器:又被称为自我截获器,因为截获器同时就是EJB bean本身,此时相关的截获器方法只能作用于该EJB
3.2 截获器链的调用顺序
因为可以为EJB定义多个截获器,所以存在截获器链的调用顺序问题,缺省情况下,以下原则被遵循:
调用顺序依次是缺省截获器、类级截获器、方法级截获器以及bean级截获器
对于同类别的截获器,按照声明的顺序调用
总是优先调用父类的截获器方法。
此外,EJB3.0规范还提供了更灵活的选项,详细信息请参考EJB3.0规范中“截获器”一节:
在发布描述符文件中设置“exclude-default-interceptors” 可以取消对缺省截获器的调用,而应用“exclude-class-interceptors”则取消对类级截获器的调用
为了替换缺省的截获器链调用顺序,可以设置发布描述符文件的“interceptor-order”。
3.3 示例
@Stateless(name="Trader")
@Interceptors(ClassInterceptor.class)
public class TraderBean implements Trader {
@Interceptors(MethodInterceptor.class)
public String sell(String stockSymbol) {
…
}
@AroundInvoke
public Object selfInterceptor(InvocationContext) throws Exception {
…
}
}
在无状态会话bean TraderBean中,声明了两个截获器:一个类级截获器,一个方法级截获器,此外,通过使用@AroundInvoke标注,TraderBean的方法selfInterceptor被声明为截获器方法,所以TraderBean就是bean级截获器。
4 EJB3.0规范在依赖注入和截获器方面的不足
从依赖注入方面来说,EJB3.0目前支持的注入类型是非常有限的,诸如List、Map之类的集合类型都不能被注入。
另一方面,EJB3.0的截获器可被看作是一种AOP模型,截获器类相当于方面(Aspect),而截获器方法相当于通知(Advice),但这种AOP是非常简单的:
不支持引入(Introduction);
不支持切入点(Pointcut)模式
通过标注告诉容器某个EJB需要使用截获器,从而使得这种AOP模型具有一定的侵入性
5 WebLogic Server 10 EJB3.0容器简介
5.1 Pitchfork 简介
Pitchfork是由Interface21与BEA合作开发的一个具有Apache License的开源项目,作为Spring的“增值”项目,开发Pitchfork有两个目的:
当前应用服务器可使用Pitchfork实现Java EE 5中的依赖注入,标注处理以及EJB3.0中的截获器。
在Spring容器中支持Java EE 5的标注
5.2 WebLogic Server 10 EJB3.0容器的架构
WebLogic Server 10完全支持Java EE 5和EJB3.0,其EJB3.0 容器是基于Pitchfork来实现依赖注入与截获器的,而Pitchfork又利用了Spring的依赖注入和AOP。此时,WebLogic Server 10的用户有两种选择:
使用EJB3.0标准模型: EJB bean实例由EJB容器创建,然后由Pitchfork实施Java EE 5 的依赖注入和截获器,这是WebLogic Server 10的缺省配置。
使用Spring扩展模型:EJB bean实例由Spring容器创建并实施Spring的依赖注入,然后由Pitchfork实施Java EE 5的依赖注入,EJB3.0截获器和Spring AOP。
6 Spring扩展模型
6.1 使用Spring扩展模型的主要开发步骤
下载某个版本的Spring类库(最好是由BEA指定的版本),至少需要包括以下jar文件:spring.jar, aspectjweaver.jar, commons-logging.jar, log4j-1.2.14.jar,如果需要,还可以增加其它jar文件。
将这些jar文件加入到WebLogic Server 10的类路径中。
创建文本文件Weblogic.application.ComponentFacotry以标识当前应用将使用Spring扩展模型,其内容只有一行: Weblogic.application.SpringComponentFactory。
创建/META-INF/services子目录,然后放入前面创建的文件Weblogic.application.ComponentFacotry
建立Spring 配置文件,并放入到/META-INF目录下,如果是EJB应用程序,Spring配置文件的名字应该是spring-ejb-jar.xml,如果是Web应用程序,Spring配置文件的名字则是spring-web.xml.
为了使EJB bean能利用Spring的依赖注入与AOP,需要同时将其定义在spring-ejb-jar.xml(或spring-web.xml)中,从Spring角度来看,这就是一个普通的Spring bean,只不过它的id或name必须与对应的EJB name相同。
将上述目录文件、相关的Java类、部署描述符等打包成标准的jar文件、war文件或ear文件。
需要注意的是,在Spring配置文件中定义的bean,如果它也是一个EJB bean,则该Spring bean的class属性会被忽略以避免潜在的冲突。
6.2 示例
示例一:利用Spring的依赖注入。本例将演示两点,(1) 注入一个集合类型,(2) 注入一个Spring POJO对象
(1) 开发一个bean类
@Stateless(name="AccountManagementBean")
@Remote({examples.AccountManagement.class})
public class AccountManagementBean
{
private List accountList;
private BusinessObject businessObject;
public boolean doBusiness(String account) {
if (accountList.contains(account)) {
businessObject.doBusiness();
return true;
}
return false;
}
public BusinessObject getBusinessObject() {
return businessObject;
}
public void setBusinessObject(BusinessObject businessObject) {
this.businessObject = businessObject;
}
public List getAccountList() {
return accountList;
}
public void setAccountList(List accountList) {
this.accountList = accountList;
}
}
(2) 一个POJO
public class BusinessObjectImpl implements BusinessObject
{
private String result;
public void doBusiness() {
System.out.println("I am doing business, the result is: " + result);
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
}
(3) Spring-ejb-jar.xml
…
<beans>
<bean name="BusinessObject" class="examples.BusinessObjectImpl">
<property name="result" value="success" />
</bean>
<bean id="AccountManagementBean">
<property name="businessObject" ref="BusinessObject" />
<property name="accountList">
<list>
<value>Safin</value>
<value>Amy</value>
<value>Albert</value>
<value>Yang</value>
</list>
</property>
</bean>
</beans>
示例二:利用Spring 的AOP。本例演示了混合使用JEE interceptor、基于代理的Spring AOP以及AspectJ的Aspect
(1) 开发一个bean类
@Stateless(name="AccountManagementBean")
@Remote({examples.AccountManagement.class})
public class AccountManagementBean
{
public AccountManagementBean() {}
@Interceptors({examples.JEEInterceptor.class})
public boolean doBusiness(String account) {
System.out.println("I am doing business " + account);
return true;
}
}
(2) 开发一个JEE interceptor
public class JEEInterceptor {
@AroundInvoke
private Object intercept(InvocationContext inv) throws Exception{
System.out.println("I am in JEEInterceptor.intercept()");
return inv.proceed();
}
}
(3) 开发一个Advice
public class SimpleAdvice implements MethodInterceptor{
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("I am in Spring AOP interceptor");
return invocation.proceed();
}
}
(4) 开发一个Pointcut
public class SimpleStaticPointcut extends StaticMethodMatcherPointcut {
public boolean matches(Method method, Class cls) {
return "doBusiness".equals(method.getName());
}
public ClassFilter getClassFilter() {
return new ClassFilter() {
public boolean matches(Class cls) {
return AccountManagementBean.class.isAssignableFrom(cls);
}
};
}
}
(5) 开发一个AspectJ Aspect
@Aspect
public class Aspects {
@Around("execution(* examples.AccountManagementBean.doBusiness(..))")
public Object around(ProceedingJoinPoint pjp) {
System.out.println(“I am in AspectJ aspect);
Object retVal = null;
try {
retVal = pjp.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
return retVal;
}
}
(5) Spring-ejb-jar.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<bean id="AccountManagementBean" />
<bean id="myAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice">
<bean class=”examples.SimpleAdvice” />
</property>
<property name="pointcut">
<bean class="examples.SimpleStaticPointcut" />
</property>
</bean>
<bean id="MyAspect" class="examples.Aspects" />
</beans>
6.3 优点
提供Spring扩展模型具有如下好处:
可以在同一个发布单元中混合使用EJB bean和Spring POJO,而且一个EJB bean可以同时是一个Spring POJO,因此被EJB容器和Spring容器同时管理
有效地克服了EJB3.0 规范在依赖注入和截获器方面的一些缺陷
为用户提供更灵活的选择:
如果标准的EJB 依赖注入以及截获器可以满足应用需求,或者可移植性是优先考虑的因素,则选用标准模型
如果标准的EJB依赖注入以及截获器不能满足应用需求,或者不用考虑可移植性,或者需要集成一些Spring应用,则应选用Spring扩展模型
7 Spring AOP在WebLogic Server 10 Spring扩展模型中的使用限制及说明
7.1 代理生成方式
Spring AOP采用的是一种基于代理的框架,目前有两种生成代理的方式:JDK动态代理和CGLIB。在WebLogic Server 10的Spring扩展模型中,目前不支持CGLIB方式,这主要是因为生成的EJB类都是final的
7.2 代理创建
在Spring中,代理或者是通过诸如ProxyFactoryBean之类的工厂bean明确创建,或者是通过“自动代理”创建器隐含创建。
在WebLogic Server 10中,Pitchfork已经隐含提供了类似的“自动代理”机制,所以原有的Spring代理创建方式是无效的,换句话说,用户只需要在Spring配置文件中定义目标bean以及对应的Spring Advisor和AspectJ Aspect, 不需要再定义ProxyFactoryBean和“自动代理”创建器,Pitchfork会自动为我们创建AOP代理
7.3 截获的顺序问题
在Spring扩展模型中,可以混合使用JEE截获器、Spring Advisor以及AspectJ Aspect,此时的调用顺序为JEE截获器、Spring Advisor以及AspectJ Aspect。
7.4 bean的实例化模式
缺省方式下,Spring bean是Singleton的,即Spring容器总是返回同一个bean实例,在Spring扩展模型中,这意味着同一个Spring Advisor或AspectJ Aspect实例将被应用到不同的EJB bean实例上,如果Advisor或Aspect实例是有状态的,这可能会产生问题,为此我们推荐如下的使用方式:
SLSB & MDB
带有状态的Advisor或Aspect
不推荐用带有状态的Advisor或Aspect,除非用户意识到相关的后果并认为这种后果是可以接收的,此时的实例化模式取决于具体应用
没有状态的Advisor或Aspect
采用Singleton实例化模式
SFSB
带有状态的Advisor或Aspect
正常情况下应该采用的实例化模式是Prototype,除非用户意识到采用Singletong的后果并认为这种后果是可以接收的
没有状态的Advisor或Aspect
采用Singleton实例化模式
8 结束语
依赖注入和截获器的引入,使得EJB3.0克服了很多EJB2.1的缺点,但与开源社区中流行的轻量级容器相比,EJB3.0无论是在依赖注入的范围还是在AOP的易用性方面都还存在一定的不足。而最近BEA所推出的WebLogic Server 10不但完全支持EJB3.0,而且对其进行了有效扩展,这使得一方面可以充分利用在开源社区中出于领导地位的Spring在依赖注入和AOP方面的强大能力,另一方面又紧密依托WebLogic Server 10在事务、安全、集群方面领先的技术,从而为EJB3.0用户开发出易维护、可扩展、高效率的企业应用程序打下坚实的基础。
作者简介
李钢 dev2devid: cc_masterli ,BEA研发中心WebLogic Server 研发团队成员,西安交通大学计算机专业博士,一直从事java中间件领域的研发,2005年加入BEA,现为EJB3 中国研发小组的负责人。
宇.凡
首先,谈谈为什么要读博?
1、如果你压根就没想好这个问题,完全是随波逐流,或者证明自己是一个"好学生",或者认为考博可以带来生活的翻天复地的变化,或者认为读博就是混个学位,为了以后好提升,那么,请你谨慎考虑。
首先,博士并不一定意味着高收入。收入更多的是与行业与职位相关,而不是与学位相关的。
其次,既便为了想进高校而读博,也要事先考虑一下是不是喜欢那种生活方式,能否接受那种清苦?能不能坐冷板凳?不然,高校的日子也不好过,竞争一样激烈。而考博只不过是"多米诺骨牌"的第一个环节。等你博士毕业之后,不继续自己的科研,可是又已经付出那么多青春、热情和心血,放弃是否舍得?如果继续从事科研,就要考虑自己是否热爱这种寂寞的无人喝彩的工作,并且身边都是精英,你能否承受那种压力?要知道,真正的名专家名学者毕竟是少数,大多数人是要默默无闻、平平淡淡过一生的。你也可以有更好的未来,但那意味着加倍的付出和努力。
2、如果已经想好了,比如就是为了提高自己的科研能力,扩大自己的知识面,或者仅仅是体验一下这种生活,或者证明一下自己,或者临时没有更好的出路,想过渡一下,或者干脆就是喜欢从事科研,那么,无论任何理由,只要是坚定的,能说服自己的,那么你就可以选择自己的活法。祝贺你,你就可以尝试。
接下来,我们看一下读博士可能需要什么?
1、高智商就不要说了,还要有高的情商。这样才能保证自己高处能胜寒,或者寂寞的时候依然美丽着。
但凡读到博士的人,总是一些人群中的佼佼者。要么是绝顶聪明,要么是极端有毅力,要么就是非常灵活,总之,可谓八仙过海、各显神通。我在读博期间的感受之一就是,周围的人的确不简单,都有令人非常佩服的一面,可能再"混"日子的人,跟一般人相比也有一份自律和坚持。所以这是一个可以相互约束、相互见证、共同进步的群体。高智商基本是读博的第一要素。
但是不要以为光有高智商就有好的生活。高情商也很重要,比如你要经常想一下自己是什么样的人?想过和适合过什么样的生活?你怎样让自己在纷繁的乱世中保持一份清醒,远离物质诱惑?你怎样让自己保持快乐?因为,的确是有一些人没想好就进来了,所以学得很累,日子过得很牵强,时不时可能还觉得"活着没劲"。如果这样的话,倒不如及早融入社会洪流更让你能安静下来。既能出世也能入世是最好的,如果压根做不到出世,就绝对入世一些,让自己实际"生活"起来,也就运转自如了。
因为如果没有高情商,那么读博不但可能不会给你带来更多的快乐,而且会带来很多负累。因为你可能会跟社会上的人比物质,跟潜心做学问的人比成果,跟那些滋润的"小家庭"比幸福,等等。那就比较麻烦。因为老天爷毕竟不会把所有的好事都给一个人。你得到了一些,就要坦然面对可能因此失去的。
2、读博需要有点毅力,沉得住气,至少一段时间内是这样。
读博可不是说着玩的。如果只是想混混,也不是那么好混的。现在的毕业论文盲审制度,还是能卡住不少没下功夫或者功夫下得不到,或者下了功夫但没下到当处的人的。而且,平时博士还有论文发表的数量和档次的要求,动不动就是国家核心期刊几篇,理工科的可能还需要在国际刊物上发表。虽然大多数博士都完成任务,拿到了学位,但那是付出了很多焦虑、睡不着觉、掉头发等等代价的。当然,视个人天资和基础不同,可能各有差异,但不努力就可以完成任务的还真没听说过。
平时上课、读书的要求就不要说了。为了完成博士论文,或者在那样一个氛围中,为了自己至少像个博士,理工科的人要无数次地做实验,甚至通宵达旦,而文科的学生则要天天泡在书堆里,基本上3年下来,看小说的时间是没有的。大家都比较训练有素,就是自己浪费了时间会自责。所以为了逃避自责的痛苦和外在的压力,大家一般还是要选择一点点的去面对和积累。没有点做冷板凳的功夫是不行的,至少在一段时间内是这样。
博士同学中已经是硕导的,在博士论文的冲刺阶段,也会形容枯槁,也有老师们形容"做完博士论文就像扒层皮",毕竟抛却客观要求不说,就自身而言,大家也知道专心在学校搞点研究不容易,所以基本上博士论文就是一段时间内的最高水平。何况博士论文的最高要求,也是最基本的,就是"创新"。这两个字,可是会把人折磨坏的。结果是,做博士论文的时候,大多数同学都"自然减肥"。一个抱着侥幸心理,本来以为混混就可以过关的同学,在博士论文写完之后,说了这样一句深刻的推翻自己以前逻辑的话——"以后,谁要再说博士是混出来的,我跟他急!"
接下来看一下读博可能带来的一些负面影响。
1、读博可能会改变一个人的生活节奏和轨迹。比如恋爱、婚姻和家庭。
说这个好象是废话。但是我们可以算笔账,一个人中间一直不停地读书,等博士毕业也是接近30的人了。这时候的社会工作经验还可能是零。如果不是足够幸运地在读书期间遇到合适的另一半并且已经成家的话,那么就要在毕业之后不但面临找工作,适应新环境的问题,也要面对建立一个小家,适应婚姻和家庭的问题,还要考虑是先在工作上干出点成绩还是抓紧要孩子的问题。这时候大多数小家庭都是无产阶级,可能早先工作的同龄人已经拥有了自己的房子、车子和孩子,心理上的落差需要自己摆平。
也有很大一部分人是有了一定的工作、家庭、孩子之后又去读博的,这种辛苦就不要说了。面对家庭和自己的前途之间的不调和,需要自己判断、选择。有时候,有所选择是痛苦的。所以有很多人说,早知如此,宁愿不要选择的机会。可是时光是无法倒流的。校园里有不少带着孩子读书的母亲,有的将孩子放在周边的幼儿园或者学校里,自己面对多重压力,孩子也跟着受苦。精力、财力和爱心、责任之间的冲突和压力,让很多母亲说:"等我拿到学位的那一天,我可能最想做的就是找个没人的地方大哭一场。"
有的时候,鱼和熊掌的确不可得兼,这是事实。所以大多数博士在毕业后都会多多少少有些尴尬,来自情感的、家庭的、工作的,等等。
2、读博可能会加重取舍之间的难度。
有人认为,读完博士,工作等等可选择的余地更大了。实际上不是这样的。博士阶段着重培养的是在某一领域具有独立进行研究和解决问题的能力的人。它不是一个通才教育,只会将人的研究领域和学习领域越限越窄。所以,除非是在高校或做科研,不然,博士并不是最好的选择。
而且,读博可能多多少少还会产生这样的效应,就是你在长期的研究和投入中已经多多少少对这些研究产生兴趣。明知继续研究可能热情和动力不足,但是放弃却着实可惜,那时该怎么办?其实周围很多同学都是这样的。最后选择的未必是最初想选择的生活道路。我学的是文科,我的很多同学,本来想进新闻媒体,或者出版单位,或者机关等等,机会并不是没有,但是真正抉择的时候,却又割舍不下对专业培养起来的感情,最终继续选了高校进行教学科研,也有的虽然进了新闻出版,却做的并不开心,有点后悔的意思。不得不搞学术的时候不觉得热爱,反倒是真正离开了觉得自己"还是有点"喜欢学术的。这是一种悖论。会带来很多困惑和尴尬,这些问题的解决需要智慧、对自己的了解,还需要决断能力。一旦上了这贼船就必须面对,由不得你了。
说了这些,有人可能退缩了,觉得后脊梁骨嗖嗖发凉。其实,运用最简单的逻辑想想,如果真的读博就像地狱,哪还有现在的趋之若骛呢?不否认有一些头脑发昏,没想明白就混进来的人,但是一定也是有人是真正考虑好了并认可这种方式的。权且说其一二:
1、读博是人的一种生活方式,而且很奢侈,不是每个人都可以享受的。
相比于钱来说,读博的机会显得更是一种稀缺资源。有机会读博的人可能不觉得,但是有很多人是压根没有机会考虑和尝试的,他们的羡慕和憧憬可能不是你读博的理由,但是至少有一点是肯定的,你可以体会跟别人不一样的人生。这也是一种生活方式。而且这种生活体验是非常奢侈的,有限的,难得的,所以自然也是有价值的有意义的。如果说有人选择冒险、挑战生命极限是一种生活方式,那么读博也是。读博完成和实现的是一种精神追求。享受这种方式本身就是一种经历、一种财富、一种收获。
有一个同事,我在博客中提到过的,海归,放弃了原来在外企的高薪工作,跑到国外读博士,最后回到高校。就是因为她觉得在外企的工作,使人变得没有时间思考,人像机器。所以为了进高校,她选择了读博并为这个目标奋斗了10几年。她说,人是要有点追求的。斯夫!当人们解决了基本的生存问题之后,对精神的渴望和寄托就会浮出水面,而读博是使人更接近思想本身的一种方式。
2、读博可以有机会接近和聆听大师的声音,并与最聪明的人相处。想不提高都难!
有博士点的地方,大都是师资力量相当强的地方,各种资源也很多。读博士可以使人轻而易举地就接近原来只闻其名、不见其人的一些大家,聆听他们在学术、做人等等方面的一些感受和教诲。这将是受益终生的。这种视界的打开和融合对一个人的提升来说至关重要。因为这些学者的点拨,可能会使人少走很多弯路,并在一些领域迅速接近国内或国外同行。某种意义上,这有"鲤鱼跳龙门"之效。特别是在一些综合性的名牌大学,这种优势就更加明显。用原来硕导的话说:"就像从省队进了国家队"。各种讲座、交流以及图书等等资源,使人进步飞快。
再说周围的同学,都是来自各地的人中龙凤。依我的经验,每个读到博士的人,都是有一些品质可能是一般的老百姓没有的,比如那种悟性、那种天资、那种刻苦、那种执着、那种毅力,等等。所以,与这样的一群聪明人交往,无论别人是不是有一些很难容忍的缺点,但也总是有一些优点是值得学习的,在这样的一种碰撞和交流中,无论是对学术的,还是对生活的看法,都会让人获益匪浅。真的是想不提高都难!
3、读博可以积累一些资源。
博士期间会遇到很多名师,也会有很多优秀的同学,这些都是一些潜在的资源。就算日后你的同学里出不了王侯将相,但至少以他们的起点,在各行各业上都会是不错的骨干。至少就我而言,很多同学遍布在很多城市的很多高校,无论对搞研究,还是作为了解风土人情的交流,都是颇有助益的。博士期间的师生关系有助于建立广泛的学术联系。
毕业之后,如果选择一个中等城市或者发展中的学校或单位,那么可能意味着你会瞬间拥有别人奋斗10几年才能拥有的东西,比如各种津贴补助、比如房子,或者配偶的工作,都能得到解决。生活会有明显提高。从这个意义上,用原来同事的话说,读博就是赚钱。或者,读博还极有可能在毕业后进入一个博士成群的工作团体。这样,你就有可能使自己一直处于一个不断学习不断上升不断进步的状态。与智者的交流毕竟是令人愉快的。对此我受益良多。
另外,比较重要的一点,也是一个老教授曾经说过的,做研究工作,所有的科研成果的发表,名利都是自己的,不象在机关等单位工作,在年轻的时候多是为别人做嫁衣,而到了退休,往往是人一走茶就凉。而现在看来,读博直接地与以后是否有机会搞科研密切相关。
4、读博可以愉悦身心,是难得的生命体验。
因为博士不象本科生那样有天天上不完的课程,有各种各样的活动的约束,有各种检查和评比,所以基本上属于比较天马行空的、自由的一群。而高校大都有优美的环境和小资的气氛,博士生里面,大家基本上要么是有收入的,要么是可以自己赚些外快的,思想相对比较成熟了,各方面处于学校和社会的结合带,并可以暂时脱离家庭的束缚,做一些自由自在的个性的事情,是难得的生命体验。对于工作多年的人来说,这是一种放松、调整和休憩,而对于从未走上工作岗位的人来说,也从别人那里直接间接得到一些启迪。
我的博士生活就是丰富多彩的。有一帮朋友,大家经常轮流坐庄,出去吃饭、喝茶、野餐,或者就在校园里散散步、打打球,或者在学校的食堂里进行"学术午餐"和"学术晚餐",关于学术的、人生的、社会的,无所不谈。现在回想起来,我的同学和朋友都颇为留恋那段时光。我们都曾说过这样的类似"痴人说梦"之类的话,"如果条件允许的话,真想一辈子当学生,一辈子在校园里待下去。让读书变成一种生活方式。"
......
我想说了这么多,不知那些想了解些什么的人是更清醒了还是更晕乎了?其实,大家都是时而清醒时而糊涂的,这都正常。关键是,主要问题想明白了就行,小事不妨糊涂一点。某一时间和地点,我们只能有一次选择人生的机会。是否读博?这本身就是一个考卷。想好了再下笔,一旦下笔就坚持下去。相信,你会看到传说中的彩虹
|
|
相关回复:
作者: zhangtikun 发布日期: 2008-11-16
说的不错
想考博的人应该仔细权衡自己到底适不适合读博,已读博的人应该再多些自律和坚持,既然选择了这种生活方式就没有必要后悔。
抵制些诱惑,抗拒些浮躁,忙碌的同时也要学会享受生活,在小天地里也要活得精彩。自勉!;)
作者: sunnybrucelee 发布日期: 2008-11-16
说的很好啊:D:D
作者: 康熙来了 发布日期: 2008-11-16
共勉!!!
作者: kumu 发布日期: 2008-11-16
非常好,借鉴中。。。
作者: 无锋 发布日期: 2008-11-16
:P学习!
作者: luzzy 发布日期: 2008-11-16
赞这种生活方式,一直想提高自己,但实在没有那样的毅力,也许过惯了这种懒散的生活了.
作者: pigeon0411 发布日期: 2008-11-16
楼主写的很好,很实际,帮助很大!谢谢
作者: 红冰2009 发布日期: 2008-11-17
很中肯也很实在的体验
作者: hanbin618 发布日期: 2008-11-17
很中肯,学习!
作者: shtjww 发布日期: 2008-11-17
是啊 每月不到2000的生活方式 哈哈
作者: tent1215 发布日期: 2008-11-17
有相同的观点
作者: jinlchen 发布日期: 2008-11-17
现在有时间体验这样的生活,单身一人不用考虑太多的问题。 就是怕坚持不下来啊
作者: xuht 发布日期: 2008-11-17
一语中的,说得太好了,就是一种生活方式
作者: pengyuan209 发布日期: 2008-11-17
很中肯也很实在的体验
作者: wuyan9537 发布日期: 2008-11-18
学习了:)
作者: hitwyb1538 发布日期: 2008-11-19
"读博是一种生活方式"!
作者: 姆粒 发布日期: 2008-11-21
嗯:)同意
作者: cnzxy 发布日期: 2008-11-21
要是三年前就看到这篇文章,我想我会义无反顾放弃读博进入社会。
作者: 临渊者慕鱼 发布日期: 2008-11-21
:o我还打算直博呢!
可以借鉴一下哎!
作者: 大雪人 发布日期: 2008-11-21
说的很好,我想读博,很有帮助,谢谢了
作者: xiebin6592 发布日期: 2008-11-22
:P:P:P
作者: zhaoyan198 发布日期: 2008-11-28
是写的很好,就是倒数第二段哪些说的可能比较不切理工学生的实际,我们可没有那个精力去喝茶聊天潇洒去,学术讨论好像也不太能形容成晚餐那么美好,也许等我毕业了会怀念,但是现在肯定还是想尽快毕业。
作者: bsklwwy 发布日期: 2008-11-28
说的不错,很实际,也不偏激。
和别的看待博士的文章不同,真正写出了读博的感受。
想要读博或正在读博的人可以看看,有很大的启迪!
作者: xjlk0000 发布日期: 2008-11-28
我也赞一下,一直在为自己的考博寻找合适的理由,心中总有那么一些文中谈到的体会,却不能明确的表达出来,谢谢楼主
作者: tsingo 发布日期: 2008-11-28
hao学习学习
作者: qingqingcao288 发布日期: 2008-11-30
很好,值得借鉴。
|
dy @ 2005-12-06 20:02
我们不逾法,但我们张扬,每一种性感都尖叫嘶喊.
我们不色情,但我们激荡,每一种宣泄都淋漓酣畅.
我们不畸形,但我们包容,每一种存在都值得尊重.
我们原创 我们独特 我们精髓 我们唯美 ------------rock
|
一輩子有多少的來不及
發現已經失去最重要的東西
恍然大悟早已遠去
為何總是在犯錯之後
才肯相信錯的是自己.
他們說這就是人生.試著體會
試著忍住眼淚還是躲不開應該有的情緒
我不會奢求世界停止轉動
我知道逃避一點都沒有用
只是這段時間裡尤其在夜裡
還是會想起難忘的事情
我想我的思念是一種病
久久不能痊癒
當你在穿山越領的另一邊
我在孤獨的路上沒有盡頭
時常感覺你在耳後的呼吸
卻未曾感覺你在心口鼻息
汲汲營營忘記身邊的人需要愛的關心
藉口總是拉遠了距離不知不覺地無聲無息
我們總是在抱怨事與願違卻願意回頭看看自己
想想自己到底做了甚麼蠢事情.
也許是上帝給我一個試煉
只是這傷口需要花點時間
只是會想念過去的一切
那些人事物會離我遠去
而我們終究也會遠離變成回憶
當你在穿山越領的另一邊
我在孤獨的路上沒有盡頭
時常感覺你在耳後的呼吸
卻未曾感覺你在心口的鼻息
oh思念是一種病
多久沒有說愛你
多久沒有擁抱你所愛的人
當這個世界不再那麼美好
只有愛可以讓他更好
我相信一切都來得及
別管那些紛紛擾擾
別讓不開心的事停下了腳步
就怕你不說.就怕你不做
別讓遺憾繼續一切都來得及
|
能做多少就做多少
不卑 不抗 不扯淡
多和别人交流
多倾听别人的想法
坚持下去一定会有收获
看情况形势 看场合说话
不清楚的不能瞎说
清楚的点到为止
讨论的时候 拿小本记好
坚持下去一定会有收获
时常提醒自己 你还刚刚上路
别刚会走 就要轮滑
尽量减少抱怨 避免攀比
不在别人耳后说三道四
坚持下去一定会有收获
一天一个苹果
睡前读一个小时书
早上醒后 想想一天的计划
努力 让自个保持清醒
坚持下去一定会有收获
泛型编程:源起、实现与意义
为什么泛型
泛型编程(Generic Programming)最初提出时的动机很简单直接:发明一种语言机制,能够帮助实现一个通用的标准容器库。所谓通用的标准容器库,就是要能够做到,比如用一个List类存放所有可能类型的对象,这样的事情;熟悉一些其它面向对象的语言的人应该知道,如Java里面这是通过在List里面存放Object引用来实现的。Java的单根继承在这里起到了关键的作用。然而单根继承对C++这样的处在语言链底层的语言却是不能承受之重。此外使用单根继承来实现通用容器也会带来效率和类型安全方面的问题,两者都与C++的理念不相吻合。
于是C++另谋他法——除了单根继承之外,另一个实现通用容器的方案就是使用“参数化类型”。一个容器需要能够存放任何类型的对象,那干脆就把这个对象的类型“抽”出来,参数化它[1]:
template<class T> class vector {
T* v;
int sz;
public:
vector(int);
T& operator[](int);
T& elem(int i) { return v[i]; }
// ...
};
一般来说看到这个定义的时候,每个人都会想到C的宏。的确,模板和宏在精神上的确有相仿之处。而且的确,也有人使用C的宏来实现通用容器。模板是将一个定义里面的类型参数化出来,而宏也可以做到参数化类型。甚至某种意义上可以说宏是模板的超集——因为宏不仅可以参数化类型,宏实质上可以参数化一切文本,因为它本来就是一个文本替换工具。然而,跟模板相比,宏的最大的缺点就是它并不工作在C++的语法解析层面,宏是由预处理器来处理的,而在预处理器的眼里没有C++,只有一堆文本,因此C++的类型检查根本不起作用。比如上面的定义如果用宏来实现,那么就算你传进去的T不是一个类型,预处理器也不会报错;只有等到文本替换完了,到C++编译器工作的时候才会发现一堆莫名其妙的类型错误,但那个时候错误就已经到处都是了。往往最后会抛出一堆吓人的编译错误。更何况宏基本无法调试。
注1
实际上,还有一种实现通用容器的办法。只不过它更糟糕:它要求任何能存放在容器内的类型都继承自一个NodeBase,NodeBase里面有pre和next指针,通过这种方式,就可以将任意类型链入一个链表内了。但这种方式的致命缺点是(1)它是侵入性的,每个能够放在该容器内的类型都必须继承自NodeBase基类。(2)它不支持基本内建类型(int、double等),因为内建类型并不,也不能继承自NodeBase。这还姑且不说它是类型不安全的,以及效率问题。
我们再来看一看通用算法,这是泛型的另一个动机。比如我们熟悉的C的qsort:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
这个算法有如下几个问题:
1. 类型安全性:使用者必须自行保证base指向的数组的元素类型和compar的两个参数的类型是一致的;使用者必须自行保证size必须是数组元素类型的大小。
2. 通用性:qsort对参数数组的二进制接口有严格要求——它必须是一个内存连续的数组。如果你实现了一个巧妙的、分段连续的自定义数组,就没法使用qsort了。
3. 接口直观性:如果你有一个数组char* arr = new arr[10];那么该数组的元素类型其实就已经“透露”了它自己的大小。然而qsort把数组的元素类型给“void”掉了(void *base),于是丢失掉了这一信息,而只能让调用方手动提供一个size。为什么要把数组类型声明为void*?因为除此之外别无它法,声明为任意一个类型的指针都不妥(compar的参数类型也是如此)。qsort为了通用性,把类型信息丢掉了,进而导致了必须用额外的参数来提供类型大小信息。在这个特定的算法里问题还不明显,毕竟只多一个size参数而已,但一旦涉及的类型信息多了起来,其接口的可伸缩性(scalability)问题和直观性问题就会逐渐显现。
4. 效率:compar是通过函数指针调用的,这带来了一定的开销。但跟上面的其它问题比起来这个问题还不是最严重的。
泛型编程
泛型编程最初诞生于C++中,由Alexander Stepanov[2]和David Musser[3]创立。目的是为了实现C++的STL(标准模板库)。其语言支持机制就是模板(Templates)。模板的精神其实很简单:参数化类型。换句话说,把一个原本特定于某个类型的算法或类当中的类型信息抽掉,抽出来做成模板参数T。比如qsort泛化之后就变成了:
template<class RandomAccessIterator, class Compare>
void sort(RandomAccessIterator first, RandomAccessIterator last,
Compare comp);
其中first,last这一对迭代器代表一个前闭后开区间,迭代器和前开后闭区间都是STL的核心概念。迭代器建模的是内建指针的接口(解引用、递增、递减等)、前开后闭区间是一个简单的数学概念,表示从first(含first)到last(不含last)的区间内的所有元素。此外,comp是一个仿函数(functor)。仿函数也是STL的核心概念,仿函数是建模的内建函数的接口,一个仿函数可以是一个内建的函数,也可以是一个重载了operator()的类对象,只要是支持函数调用的语法形式就可成为一个仿函数。
通过操作符重载,C++允许了自定义类型具有跟内建类型同样的使用接口;又通过模板这样的参数化类型机制,C++允许了一个算法或类定义,能够利用这样的接口一致性来对自身进行泛化。例如,一个原本操作内建指针的算法,被泛化为操纵一切迭代器的算法。一个原本使用内建函数指针的算法,被泛化为能够接受一切重载了函数调用操作符(operator())的类对象的算法。
让我们来看一看模板是如何解决上面所说的qsort的各个问题的:
1. 类型安全性:如果你调用std::sort(arr, arr + n, comp);那么comp的类型就必须要和arr的数组元素类型一致,否则编译器就会帮你检查出来。而且comp的参数类型再也不用const void*这种不直观的表示了,而是可以直接声明为对应的数组元素的类型。
2. 通用性:这个刚才已经说过了。泛型的核心目的之一就是通用性。std::sort可以用于一切迭代器,其compare函数可以是一切支持函数调用语法的对象。如果你想要将std::sort用在你自己的容器上的话,你只要定义一个自己的迭代器类(严格来说是一个随机访问迭代器,STL对迭代器的访问能力有一些分类,随机访问迭代器具有建模的内建指针的访问能力),如果需要的话,再定义一个自己的仿函数类即可。
3. 接口直观性:跟qsort相比,std::sort的使用接口上没有多余的东西,也没有不直观的size参数。一个有待排序的区间,一个代表比较标准的仿函数,仅此而已[4]。
4. 效率:如果你传给std::sort的compare函数是一个自定义了operator()的仿函数。那么编译器就能够利用类型信息,将对该仿函数的operatpr()调用直接内联。消除函数调用开销。
动态多态与静态多态
泛型编程的核心活动是抽象:将一个特定于某些类型的算法中那些类型无关的共性抽象出来,比如,在STL的概念体系里面,管你是一个数组还是一个链表,反正都是一个区间,这就是一层抽象。管你是一个内建函数还是一个自定义类,反正都是一个Callable(可调用)的对象(在C++里面通过仿函数来表示),这就是一层抽象。泛型编程的过程就是一个不断将这些抽象提升(lift)出来的过程,最终的目的是形成一个最大程度上通用的算法或类。
有人肯定会问,既然同是抽象,那为什么不用基于多态的面向对象抽象呢?比如STL的std::for_each,用Java的多态机制也可以解决:
interface IUnaryFun
{
void invoke(Object o);
}
interface IInputIter
{
IInputIter preIncrement();
boolean equals(IInputIter otherIter);
… // other methods
}
IUnaryFun for_each(IInputIter first, IInputIter last, IUnaryFun func)
{
for(;!first.equals(last); first.preIncrement())
func.invoke(*first);
return func;
}
其实,这里最主要的原因很简单,效率。面向对象的多态引入了间接调用。当然,并不是说间接调用不好,有些时候,比如确实需要运行期多态的时候,只能诉诸继承这样的手段。但当能够利用编译期类型信息的时候,为什么要付出不必要的间接调用开销呢?比如这里的for_each,利用接口来实现其通用性,就付出了所谓的“抽象惩罚”(abstraction penalty)。而C++的模板,就是为了消除这样的抽象惩罚。利用模板编写的std::for_each,对于每一个特定的参数类型组合都有一个独立的,最高效的实例化版本,就跟你手写一个特定于这些类型的专门的for_each算法一样[5]。于是抽象惩罚消失了,而这也正是C++模板库能够真正被工业界广泛用在C++最擅长的领域(重视效率的领域)的重要原因之一。
另一方面,对于每一组参数类型组合实例化一个版本出来的做法增加了代码空间,这是一个典型的以空间换时间的例子,不过对于一门静态并追求效率的语言来说,这个代码空间的开销反正也是必不可少的,因为即便你手动为各种不同的参数类型组合编写特定的算法版本的话,也是付出一样的代码空间开销,而且还顺便违反了DRY原则[6]。此外,由于在抽象的时候不用总想着要建立的接口,所以泛型算法编写起来也更为直观。
C++泛型的另一个好处就是,跟面向对象编程的基于继承和虚函数的运行时多态机制不同,C++模板是非侵入性的。你不需要让你的类继承自某个特定的接口才能用于某个算法,只要支持特定的语法接口就行了(比如只要支持begin()调用)。这也被称为结构一致性(Structural Conformance),意即只要语法结构一致即可。而另一方面,基于接口继承的面向对象多态则必须要显式地声明继承自一个接口,这就是所谓的名字一致性(Named Conformance)。
当然,泛型支持的静态多态和虚函数支持的动态多态并没有任何程度上绝对的优劣之分。它们适用于不同的场合。当类型信息可得的时候,利用编译期多态能够获得最大的效率和灵活性。当具体的类型信息不可得,就必须诉诸运行期多态了。Bjarne Stroustrup曾经用了一个典型的例子来澄清这个区别:
std::vector<Shape*> v;
… // fill v
std::for_each(v.begin(), v.end(), std::mem_fun(&Shape::draw));
这里,v里面到底将来会存放什么类型的Shape,编译期无法知道,因而必须求助于动态多态。另一方面,编译器倒的确知道它们都继承自Shape,利用这仅有的静态类型信息,我们使用了泛型算法std::for_each和泛型容器std::vector。这里尤其值得注意的是for_each的静态多态行为:for_each只有一份模板实现,然而根据传给它的第三个参数(本例中是std::mem_fun(&Shape::draw))的不同,for_each的行为也不同(这里最终被for_each调用的是Shape::draw,但实际上你可以包装任何函数,只要这个函数接受一个Shape*型的参数),for_each这种“行为不同”是发生在编译期的,所以是静态多态。
前面说过,模板与接口继承比较,模板是非侵入的。这是C++泛型与面向对象的多态机制的本质区别之一。但实际上,面向对象未必就意味着一定要用接口来实现动态的多态。一些动态类型的脚本语言,如Ruby,它的多态机制就既是运行期(动态)的,又是非倾入性的(不用通过继承自某个特定的接口来达到复用)。人们把这个叫做Duck Typing[7]。如果不是因为效率问题,其实这样的多态机制才是最直观的,从使用方面来说,它既有非侵入性,又没有只能工作在编译期的限制。但效率至少在可见的将来、在某些领域仍是一个顾虑。因此像C++这种区分编译期和运行期多态的语言,仍有其独特的优势。
此外,泛型编程的类型安全优势也让它从C++走入了其它主流的静态类型语言当中,尤其是C家族的Java和C#,在前几年相继接纳泛型。
特化,图灵完备性,元编程
C++的模板是支持特化的,这就给了它实现编译期控制结构的可能性,进而带来了一个图灵完备的子语言。模板特化的引入原本只是为了效率目的——针对不同的类型提供不同的实现。但后来却被发现能够实现编译期的if/else和递归等控制结构。
模板元编程最初由Erwin Unruh在1994年的一次会议上提出;当时他写了一个程序,在编译错误里面打印出一个素数序列。这个事件在C++历史上的地位就仿佛哥伦布发现新大陆。用Bjarne Stroustrup的话来说就是当时他当时和其他几个人觉得太神奇了。实际上,这个事情正标志了C++模板系统的图灵完备性被发现;后来Todd Veldhuizen写了一篇paper,用C++模板构建了一个元图灵机,从而第一次系统证明了C++模板的图灵完备性。接下来的事情就顺理成章了——一些ad hoc的模板元编程技巧不断被发掘出来,用于建造高效、高适应性的通用组件。最终,David Abrahams编写了boost库中的基本组件之一:Boost.MPL库。Boost.MPL以类型和编译期常量为数据,以模板特化为手段,实现了一个编译期的STL。你可以看到常见的vector,你可以看到transform算法,只不过算法操纵的对象和容器存放的对象不再是运行期的变量或对象,而是编译期的类型和常量。想知道模板元编程是如何用在库构建中的,可以打开一个Boost的子库(比如Boost.Tuple或Boost.Variant)看一看。
然而,毕竟C++的模板元编程是一门被发现而不是被发明的子语言。一方面,它在构建泛型库的时候极其有用。然而另一方面,由于它并非语言设计初始时考虑在内的东西,所以不仅在语法上面显得不那么first-class(比较笨拙);更重要的是,由于本不是一个first-class的语言特性,所以C++编译器并不知道C++元编程的存在。这就意味着,比如对下面这样一个编译期的if/else设施[8]:
template<bool b, class X, class Y>
struct if_ {
typedef X type; // use X if b is true
};
template<class X, class Y>
struct if_<false,X,Y> {
typedef Y type; // use Y if b is false
};
typedef if_<(sizeof(Foobar)<40), Foo, Bar>::type type;
编译器并没有真的去进行if/else的分支选择,而是按部就班毫不知情地进行着模板的特化匹配。如果遇到Boost.MPL这样的模板元编程非常重的库,就会严重拖累编译速度,编译器进行了一重一重的特化匹配,实例化了一个又一个的模板实例,就是为了去获取里面定义的一个typedef,完了之后中间所有实例化出来的模板实例类型全都被丢弃[9]。
模板元编程最全面深入的介绍是Boost.MPL库的作者David Abrahams的《C++ Template Metaprogramming》,其中的样章(第三章)[10]对模板元编程作了一个非常高屋建瓴的概览[11]。
关于模板元编程,需要提醒的是,它并不属于“大众技术”。日常编程中极少需要用到元编程技巧。另一方面,C++模板里面有大量ad hoc的技巧,如果一头扎进去的话,很容易只见树木不见森林,所以需要提醒初学者的是,即便要学习,也要时刻保持“高度”,始终记得元编程的意义和目的,这样才不至于迷失在无穷无尽的语言细节中。
C++09——进化
泛型编程在C++中取得了工业程度上的成功,得益于其高效性和通用性。但同时,在经过了近十年的使用之后,C++模板,这个作为C++实现泛型的机制的缺点也逐渐暴露出来。比如其中对于初学者最严重的一个问题就是在使用一个模板库时常常遇到无法理解的编译错误,动辄长达上K字节。这些编译错误很容易把一个初学者吓走。究其本质原因,为什么编译器会报出令人难以卒读的编译错误,是因为在编译器的眼里,只有类型,而没有“类型的类型”。比如说,迭代器就是一个类型的类型,C++里面也把它称为“概念”(Concept)。例如,std::sort要求参数必须是随机访问迭代器,如果你一不小心给了它一个非随机访问的迭代器,那么编译器不是抱怨“嘿!你给我的不是随机访问迭代器”,而是抱怨找不到某某重载操作符(典型的比如operator+(int))。因为在编译器眼里,没有“迭代器”这么个概念,这个概念只存在于程序员脑子里和STL的文档里。为了帮助编译器产出更友好的信息(当然,还有许多非常重要的其它原因[12]),C++09将对“类型的类型”加入first-class的支持,其带来的众多好处会将C++中的泛型编程带向一个新的高度:更友好、更实用、更直观。
此外,C++的模板元编程尚没有first-class的语言支持,一方面是因为其运用不像一般的模板编程这么广泛,因而没有这么紧急。另一方面,C++09的时间表也等不及一个成熟的提案。如果以后模板元编程被运用得越来越广泛的话,那first-class的语言支持是难免的。
总结
本文对C++模板,以及C++模板所支持的泛型编程作了一个概览。着重介绍了泛型编程诞生的原因,泛型编程的过程和意义,与其它抽象手段的比较。并对C++中的模板元编程做了一些介绍。最后介绍了C++模板在C++09中的增强。
[2] http:// en.wikipedia.org/wiki/Alexander_Stepanov
[3] http://www.cs.rpi.edu/~musser
[4] 实际上,STL的区间概念被证明是一个不完美的抽象。你有没有发现,要传递一个区间给一个函数,如std::sort,你需要传递两个参数,一个是区间的开头,一个是区间的末尾。这种分离的参数传递方式被证明是不明智的,在一些场合会带来使用上不必要的麻烦。比如你想迭代一组文件,代表这组文件的区间由一个readdir_sequence函数返回,由于要分离表达一个区间,你就必须写:
readdir_sequence entries(".", readdir_sequence::files);
std::for_each(entries.begin(), entries.end(), ::remove);
如果你只想遍历这个区间一次的话,你也许不想声明entries这个变量,毕竟多一个名字就多一个累赘,你也许只想:
std::for_each(readdir_sequence(".", readdir_sequence::files), ::remove);
下一代C++标准(C++09)会解决这个问题(将区间这个抽象定义为一个整体)。
[5] 当然,语言并没有规定模板实例化的底层实现一定要是对每组参数类型组合实例化一个版本出来。但目前的实现,这种方案是最高效的。完全消除了抽象惩罚。另一方面,One size fit all的方案也不是不可行,但总会有间接调用。这也正说明了静态类型系统的一个典型优点:帮助编译器生成更高效的代码。
[6] http:// en.wikipedia.org/wiki/Don't_repeat_yourself
[7] http:// en.wikipedia.org/wiki/Duck_typing
[8] 摘自Bjarne Stroustrup的paper:Evolving a language in and for the real world: C++ 1991-2006
[9] 也正因此,D语言加入了语言直接对模板元编程的支持,比如真正工作在编译期的static if-else语句。
[10] http://www.boost-consulting.com/mplbook/
[11] 第三章的翻译见我的blog:《深度探索元函数》http://blog.csdn.net/pongba/archive/2004/09/01/90642.aspx
[12] 由于篇幅原因,这里无法展开详述Concept对C++泛型编程的其它重要意义,有兴趣的可以参见我的一篇blog:《C++0x漫谈系列之:Concept! Concept!》。http://blog.csdn.net/pongba/archive/2007/08/04/1726031.aspx
常去看的几个博客
1、刘未鹏|C++的罗浮宫
http://blog.csdn.net/pongba
假如你对人工智能、机器学习、知识发现和认知科学有兴趣,这个博客绝对是一个宝藏!
2、笑对人生,傲立寰宇 的博客:
http://dahua.spaces.live.com/blog/
一个非常好的技术博客,博主林大华是中科大本科、香港中文大学硕士,目前在MIT读博。博客里有很多深入浅出、诙谐有趣的技术文章和读书心得,常让我拍案叫绝,那些干涩无味的数学原理也可以聊侃得如此趣味横生,呵呵。数学和matlab方面的朋友不妨多上去看看 O(∩_∩)O
3、不交作业 的博客:
http://blog.163.com/oneoctopus@126/blog/
一位在华南理工大学读研的学生,和他不相识,但每周都会去他的博客看看。也许是因为同龄,看他的博客、他的经历,让自己有很大的共鸣。研二一年,就集中精力写一篇文章,近期才完稿,投到著名的ACC(American Control Conference)会议去,有点‘十年磨一剑’的感觉;目前研三在申请美国的名校,祝他马到成功啦。
同龄人前进的脚步,最能鞭策自己不懈前行……
4、晃晃悠悠 的博客:
http://dy1981.ycool.com/
以前学习小波的时候接触到的一个博客,挺不错的,而且还有对音乐和现实生活的一些体会和感受,每个人的人生故事都有特别的精彩之处。
5、萝卜驿站 的博客:
http://luobo.ycool.com/
matlab强人,博客里有N多小波、混沌等方面的matlab代码共享,还有很多matlab编程技巧方面的解答。
6、天上有宫阙 的博客:
http://www.myclub2.com/blog/realghost/category/1396.html
里面有不少matlab和数学的学习资料,特别是代码共享,呵呵。
让人心疼的12句话...哪句说到你...-
1有些事,我们明知道是错的,也要去坚持,因为不甘心;有些人,我们明知道是爱的,也要去放弃,因为没结局;有时候,我们明知道没路了,却还在前行,因为习惯了
2以为蒙上了眼睛,就可以看不见这个世界;以为捂住了耳朵,就可以听不到所有的烦恼;以为脚步停了下来,心就可以不再远行;以为我需要的爱情,只是一个拥抱
3那些已经犯过的错误,有一些是因为来不及,有一些是因为刻意躲避,更多的时候是茫然地站到了一边我们就这样错了一次又一次,却从不晓得从中汲取教训,做一些反省
4你不知道我在想你,是因为你不爱我,我明明知道你不想我,却还爱你,是因为我太傻也许有时候,逃避不是因为害怕去面对什么,而是在等待什么
5天空没有翅膀的痕迹,但鸟儿已经飞过;心里没有被刀子割过,但疼痛却那么清晰这些胸口里最柔软的地方,被爱人伤害过的伤口,远比那些肢体所受的伤害来得犀利,而且只有时间,才能够治愈
6很多人,因为寂寞而错爱了一人,但更多的人,因为错爱一人,而寂寞一生我们可以彼此相爱,却注定了无法相守不是我不够爱你,只是我不敢肯定,这爱,是不是最正确的
7如果背叛是一种勇气,那么接受背叛则需要一种更大的勇气前者只需要有足够的勇敢就可以,又或许只是一时冲动,而后者考验的却是宽容的程度,绝非冲动那么简单,需要的唯有时间
8生命无法用来证明爱情,就像我们无法证明自己可以不再相信爱情在这个城市里,诚如劳力士是物质的奢侈品,爱情则是精神上的奢侈品可是生命脆弱无比,根本没办法承受那么多的奢侈
9人最大的困难是认识自己,最容易的也是认识自己很多时候,我们认不清自己,只因为我们把自己放在了一个错误的位置,给了自己一个错觉所以,不怕前路坎坷,只怕从一开始就走错了方向
10生活在一个城市里,或者爱一个人,又或者做某件事,时间久了,就会觉得厌倦,就会有一种想要逃离的冲动也许不是厌倦了这个城市爱的人坚持的事,只是给不了自己坚持下去的勇气
11多少次又多少次,回忆把生活划成一个圈,而我们在原地转了无数次,无法解脱总是希望回到最初相识的地点,如果能够再一次选择的话,以为可以爱得更单纯
12如果你明明知道这个故事的结局,你或者选择说出来,或者装作不知道,万不要欲言又止有时候留给别人的伤害,选择沉默比选择坦白要痛多了
清华校长送给毕业生的五句话
“未来的世界:方向比努力重要,能力比知识重要,健康比成绩重要,生活比文凭重要,情商比智商重要! ”
——清华大学校长留给毕业生的一段话
方向比努力重要。
现在是讲究绩效的时代,公司、企业、政府,需要的是有能力且能与企业方向共同发展的人,而不是一味努力但却南辕北辙的人。自己适合哪些行业,哪些职业,有很多东西是先天决定的,只有充分地发掘自己的潜力,而不是总与自己的弱点对抗,一个人才能出人头地,就像现在很多企业招聘的时候,他们相信通过培训和教育可以让火鸡学会爬树,但是还是觉得选个松树方便一些。方向不对,再努力、再辛苦,你也很难成为你想成为的那种人。
能力比知识重要。
知识在一个人的构架里只是表象的东西,就相当于有些人可以在答卷上回答如何管理企业、如何解决棘手的问题、如何当好市长等等,但是在现实面前,他们却显得毫无头绪、不知所措,他们总是在问为什么会是这种情况,应该是哪种情况等等。他们的知识只是知识,而不能演化为能力,更不能通过能力来发掘他们的潜力。现在很多企业都在研究能力模型,从能力的角度来观察应聘者能否胜任岗位。当然,高能力不能和高绩效直接挂钩,能力的发挥也是在一定的机制、环境、工作内容与职责之内的,没有这些平台和环境,再高的能力也只能被尘封。
健康比成绩重要。
成绩只能代表过去,这是很多人已经认同的一句话。对于毕业后走入工作岗位的毕业生,学生阶段的成绩将成为永久的奖状贴在墙上,进入一个工作单位,就预示着新的竞赛,新的起跑线。没有健康的身心,如何应对变幻莫测的市场环境和人生变革,如何应对工作压力和个人成就欲的矛盾?而且在现代社会,拥有强健的身体已经不是最重要的,健康的心理越来越被提上日程,处理复杂的人际关系、承受挫折与痛苦、缓解压力与抑郁,这些都将成为工薪族乃至学生们常常面对的问题。为了防止英年早逝、过劳死,还是多注意一下身体和心理的健康投资吧。
生活比文凭重要。
曾经有一个故事,说有个记者问放羊的小孩,为什么放羊?答:为了挣钱,挣钱干啥?答:盖房子,盖房子干啥?答:娶媳妇,娶媳妇干啥?答:生孩子,生孩子干啥?答:放羊!
记得去年在人大听一个教授讲管理学基础课,他说你们虽然都是研究生,但很多人本质上还是农民!大家惊愕,窃窃私语。他说你们为什么读研究生,很多人是不是想找个好工作,找好工作为了什么,为了找个好老婆,吃喝住行都不错,然后生孩子,为了孩子的前途更光明,这些不就是农民的朴素想法吗?那个农民父母不希望自己的子女比自己更好?说说你们很多人是不是农民思想,什么时候,你能突破这种思维模式,你就超脱了。当这个社会看重文凭的时候,假文凭就成为一种产业,即使是很有能力的人,也不得不弄个文凭,给自己脸上贴点金。比起生活,文凭还重要吗?很多人找女朋友或者男朋友,把学历当作指标之一,既希望对方能够给他/她伴侣的温暖与浪漫,又希望他/她知识丰富、学历相当或更高,在事业上能蒸蒸日上;我想说,你找的是伴侣,不是合作伙伴,更不是同事,生活就是生活,这个人适合你,即使你是博士他/她斗大字不识一个,那也无所谓,适合就会和谐融洽,人比文凭更重要。很多成功的人在回头的时候都说自己太关注工作和事业了,最遗憾的是没有好好陪陪父母、爱人、孩子,往往还伤心落泪,何必呢,早意识到这些,多给生活一些空间和时间就可以了。我们没有必要活得那么累。
情商比智商重要。
这个就很有意思了,大家忽然一下子对情商重视了起来,因为在新的世纪,情商将成为成功领导中最重要的因素之一。比如在许多员工和自己的亲人因恐怖袭击丧生的时刻,某公司CEO Mark Loehr让自己镇定下来,把遭受痛苦的员工们召集到一起,说:我们今天不用上班,就在这里一起缅怀我们的亲人,并一一慰问他们和亲属。在那一个充满阴云的星期,他用自己的实际行动帮助了自己和他的员工,让他们承受了悲痛,并把悲痛转化为努力工作的热情,在许多企业经营亏损的情况下,他们公司的营业额却成倍上涨,这就是情商领导的力量,是融合了自我情绪控制、高度忍耐、高度人际责任感的艺术。曾经有个记者刁难一位企业家:听说您大学时某门课重考了很多次还没有通过。这位企业家平静地回答:我羡慕聪明的人,那些聪明的人可以成为科学家、工程师、律师等等,而我们这些愚笨的可怜虫只能管理他们。要成为卓越的成功者,不一定智商高才可以获得成功的机会,如果你情商高,懂得如何去发掘自己身边的资源,甚至利用有限的资源拓展新的天地,滚雪球似得积累自己的资源,那你也将走向卓越。
在世界上出人头地的人,都能够主动寻找他们要的时势,若找不到,他们就自己创造出来。
——萧伯纳
35岁前成功的12条黄金法则
第一章:一个目标
一艘没有航行目标的船,任何方向的风都是逆风
1、你为什么是穷人,第一点就是你没有立下成为富人的目标
2、你的人生核心目标是什么?
杰出人士与平庸之辈的根本差别并不是天赋、机遇,而在于有无目标。
3、起跑领先一步,人生领先一大步:成功从选定目标开始
4、贾金斯式的人永远不会成功
为什么大多数人没有成功?真正能完成自己计划的人只有5%,大多数人不是将自己的目标舍弃,就是沦为缺乏行动的空想
5、 如果你想在35岁以前成功,你一定在25至30岁之间确立好你的人生目标
6、 每日、每月、每年都要问自己:我是否达到了自己定下的目标
第二章:两个成功基点
站好位置,调正心态,努力冲刺,35岁以前成功
(一)人生定位
1、 人怕入错行:你的核心竞争力是什么?
2、 成功者找方法,失败者找借口
3、 从三百六十行中选择你的最爱
人人都可以创业,但却不是人人都能创业成功
4、 寻找自己的黄金宝地
(二)永恒的真理:心态决定命运,35岁以前的心态决定你一生的命运
1、 不满现状的人才能成为富翁
2、 敢于梦想,勇于梦想,这个世界永远属于追梦的人
3、 35岁以前不要怕,35岁以后不要悔
4、 出身贫民,并非一辈子是贫民,只要你永远保持那颗进取的心。中国成功人士大多来自小地方
5、 做一个积极的思维者
6、 不要败给悲观的自己
有的人比你富有一千倍,他们也会比你聪明一千倍么?不会,他们只是年轻时心气比你高一千倍。
人生的好多次失败,最后并不是败给别人,而是败给了悲观的自己。
7、 成功者不过是爬起来比倒下去多一次
8、 宁可去碰壁,也不要在家里面壁
克服你的失败、消极的心态
(1) 找个地方喝点酒
(2) 找个迪厅跳跳舞
(3) 找帮朋友侃侃山
(4) 积极行动起来
第三章:三大技巧
1、管理时间:你的时间在哪里,你的成就就在哪里。
把一小时看成60分钟的人,比看作一小时的人多60倍
2、你不理财,财不理你
3、自我管理,游刃有余
(1) 创业不怕本小,脑子一定要好
(2) 可以开家特色店
(3) 做别人不愿做的生意
第四章:四项安身立命的理念
35岁以前一定要形成个人风格
1、做人优于做事
做事失败可以重来,做人失败却不能重来
(1) 做人要讲义气
(2) 永不气馁
2、豁达的男人有财运,豁达的女人有帮夫运
35岁以前搞定婚姻生活
3、忠诚的原则:35岁以前你还没有建立起忠诚美誉,这一缺点将要困扰你的一生
4、把小事做细,但不要耍小聪明
中国人想做大事的人太多,而愿把小事做完美的人太少
第五章:五分运气
比尔·盖茨说:人生是不公平的,习惯去接受它吧
1、人生的确有很多运气的成人:谋事在人,成事在天:中国的古训说明各占一半
2、机会时常意外地降临,但属于那些不应决不放弃的人
3、抓住人生的每一次机会
机会就像一只小鸟,如果你不抓住,它就会飞得无影无踪
4、 智者早一步,愚者晚一步
第六章:六项要求
1、智慧
(1)别人可你以拿走你的一切,但拿不走你的智慧
(2)巧妙运用自己的智慧
(3)智者与愚者的区别
2、勇气
(1)勇气的力量有时会让你成为"超人"
(2)敢于放弃,敢于"舍得"
3、培养自己的"领导才能、领袖气质"
(1) 激情感染别人
(2) "三o七法则"实现领袖气质
(3) 拍板决断能力
(4) 人格魅力
4、创造性:不要做循规蹈矩的人
25-35岁是人生最有创造性的阶段,很多成功人士也都产生在这一阶段
5、明智
(1) 知道自己的长处、短处,定向聚焦
(2) 尽量在自己的熟悉的领域努力
6、持之以恒的行动力:在你选定行业坚持十年,你一定会成为大赢家
第七章:七分学习
1、知识改变命运
2、35岁以前学会你行业中必要的一切知识
a) 每天淘汰你自己
b) 在商言商
3、太相信书的人,只能成为打工仔
4、思考、实践、再思考、再实践
第八章:八分交际
朋友多了路好走
1、智商很重要,情商更重要:35岁以前建立起人际关系网
2、人脉即财脉:如何搞好人际关系
3、交友有原则
4、善于沟通:35岁以前要锻炼出自己的演讲才能
第九章:九分习惯
习惯的力量是惊人的,35岁以前养成的习惯决定着你的成功的大小
1、积极思维的好习惯
2、养成高效工作的好习惯
(1) 办公室
(2) 生活可以不拘小节,但要把工作做细
(3) 学习聆听,不打断别人说话
3、养成锻炼身体的好习惯
4、广泛爱好的好习惯
5、快速行动的好习惯
第十章:十分自信
1、自信是成功的精神支柱
2、自信方能赢得别人的信任
3、把自信建立在创造价值的基础上
4、如何建立自信
(1) 为自己确立目标
(2) 发挥自己的长处
(3) 做事要有计划
(4) 做事不拖拉
(5) 轻易不要放弃
(6) 学会自我激励
(7) 不要让自己成为别人
第十一章 11个需要避开的成功陷阱
1、只有功劳,没有苦劳
2、不要"怀才不遇",而要寻找机遇
3、不要想发横财
4、不要为钱而工作,而让钱为你工作
5、 盲目跟风,人云亦云,人做我也做
6、 小富即安,不思进取,知足常乐
7、 承认错误而非掩饰错误
8、 脚踏实地而非想入非非
9、 野心太大而不是信心十足
10、反复跳槽不可取
11、眼高手低
12、不择手段
第十二章 十二分努力
没有人能随随便便成功
1、小不是成功,大不是成功,由小变大才是成功
2、中国社会进入微利时代:巧干+敢干+实干=成功
3、努力尝试就有成功的可能
4、做任何事情,尽最大努力
5、把事情当成事业来做
6、我看打工者
7、祝你早日掘到第一桶金
你可以不爱江山爱美人,但是告诉你,没有一个美人是不爱江山的。
找对象要找有车有房,父母双亡的。(顾小西告诉简佳找男朋友的条件,够绝!)
如果他没有把你介绍给他的家人,那就是把自己还留有余地。
娶妻娶德,纳妾纳色。
一个男人要想对女人有很高的要求,他首先应该对自己有很高的要求,否则他就会像一
个对生活品质有要求的乞丐一样让人生厌!
一个男人如果没有能力使自己立足于世,你有什么资格要求你梦想中的女人按照你的想
法生活?
如果要想知道小鸟是不是属于你的,就别把它关在笼子里。。
谎言有两种,一种是把黑说成白,一种是把黑的隐藏了。(顾小航)
我不是不相信你的真诚,我是不相信你的年龄。(简佳拒绝顾小航时说的话)
已经上了钩的鱼就不用再浪费鱼饵了。(何建国的同事)
结婚——你不是嫁给了某一个人,而是嫁给了这个人的全部社会关系。(顾小西妈妈)
钱有多多,爱有多深。(顾小西)
你是在卖书,还是在卖春。(顾小西-关于陈蓝发书书名被迫改成‘我包养的三年’)
这世界上没有无缘无故的爱!
这个世界上只有两种女人,一种是假正经的,一种是假不正经的。
女人怀孕九个月,生完孩子还要半年,要花一年多时间,你们男人也就出那么十几分钟
的力。
添加代码:
#pragma comment(linker, "\"/manifestdependency:type='Win32' name='Microsoft.VC80.CRT' version='8.0.50608.0' processorArchitecture='X86' publicKeyToken='1fc8b3b9a1e18e3b' language='*'\"")
在VS2005中,如果没有上面这行代码,运行会提示:没有找到 MSVCR80.dll
Visual C++ 如何:在各种字符串类型之间进行转换
C++实现单件
c++按位操作符
预编译头文件
今天在改一个很大的程序,慢慢看,慢慢改。突然发现一个.c文件,里面什么也没有,
就几个头文件,我一看,我靠,这不是把简单的问题搞复杂了吗,随手删掉那个c文件。
结果不能编译了,我靠:
fatal error C1083: Cannot open precompiled header file: \'Debug/v13_3.pch\':
No such file or directory
怎么rebuild all都不行。
上网查了一下,才搞懂了:
----------------总结------
如果工程很大,头文件很多,而有几个头文件又是经常要用的,那么
1。把这些头文件全部写到一个头文件里面去,比如写到preh.h
2。写一个preh.c,里面只一句话:#include "preh.h"
3。对于preh.c,在project setting里面设置creat precompiled headers,对于其他
.c文件,设置use precompiled header file
//
哈哈
我试了一下,效果很明显,不用precompiled header,编译一次我可以去上个厕所,用
precompiled header,编译的时候,我可以站起来伸个懒腰,活动活动就差不多啦
---------转载的文章----------
预编译头的概念:
所谓的预编译头就是把一个工程中的那一部分代码,预先编译好放在一个文件里(通常是
以.pch为扩展名的),这个文件就称为预编译头文件这些预先编译好的代码可以是任何的
C/C++代码--------甚至是inline的函数,但是必须是稳定的,在工程开发的过程中不会
被经常改变。如果这些代码被修改,则需要重新编译生成预编译头文件。注意生成预编
译头文件是很耗时间的。同时你得注意预编译头文件通常很大,通常有6-7M大。注意及
时清理那些没有用的预编译头文件。
也许你会问:现在的编译器都有Time stamp的功能,编译器在编译整个工程的时候,它
只会编译那些经过修改的文件,而不会去编译那些从上次编译过,到现在没有被修改过
的文件。那么为什么还要预编译头文件呢?答案在这里,我们知道编译器是以文件为单
位编译的,一个文件经过修改后,会重新编译整个文件,当然在这个文件里包含的所有
头文件中的东西(.eg Macro, Preprocesser )都要重新处理一遍。VC的预编译头文件
保存的正是这部分信息。以避免每次都要重新处理这些头文件。
预编译头的作用:
根据上文介绍,预编译头文件的作用当然就是提高便宜速度了,有了它你没有必要每次
都编译那些不需要经常改变的代码。编译性能当然就提高了。
预编译头的使用:
要使用预编译头,我们必须指定一个头文件,这个头文件包含我们不会经常改变的
代码和其他的头文件,然后我们用这个头文件来生成一个预编译头文件(.pch文件)
想必大家都知道 StdAfx.h这个文件。很多人都认为这是VC提供的一个“系统级别”的
,编译器带的一个头文件。其实不是的,这个文件可以是任何名字的。我们来考察一个
典型的由AppWizard生成的MFC Dialog Based 程序的预编译头文件。(因为AppWizard
会为我们指定好如何使用预编译头文件,默认的是StdAfx.h,这是VC起的名字)。我们
会发现这个头文件里包含了以下的头文件:
#include <afxwin.h> // MFC core and standard components
#include <afxext.h> // MFC extensions
#include <afxdisp.h> // MFC Automation classes
#include <afxdtctl.h> // MFC support for Internet Explorer 4
Common Controls
#include <afxcmn.h>
这些正是使用MFC的必须包含的头文件,当然我们不太可能在我们的工程中修改这些头文
件的,所以说他们是稳定的。
那么我们如何指定它来生成预编译头文件。我们知道一个头文件是不能编译的。所以我
们还需要一个cpp文件来生成.pch 文件。这个文件默认的就是StdAfx.cpp。在这个文件
里只有一句代码就是:#include “Stdafx.h”。原因是理所当然的,我们仅仅是要它能
够编译而已?D?D?D也就是说,要的只是它的.cpp的扩展名。我们可以用/Yc编译开关来指
定StdAfx.cpp来生成一个.pch文件,通过/Fp编译开关来指定生成的pch文件的名字。打
开project ->Setting->C/C++ 对话框。把Category指向Precompiled Header。在左边的
树形视图里选择整个工程
Project Options(右下角的那个白的地方)可以看到 /Fp “debug/PCH.pch”,这就是指
定生成的.pch文件的名字,默认的通常是 <工程名>.pch(我的示例工程名就是PCH)。
然后,在左边的树形视图里选择StdAfx.cpp.//这时只能选一个cpp文件!
这时原来的Project Option变成了 Source File Option(原来是工程,现在是一个文件
,当然变了)。在这里我们可以看到 /Yc开关,/Yc的作用就是指定这个文件来创建一个
Pch文件。/Yc后面的文件名是那个包含了稳定代码的头文件,一个工程里只能有一个文
件的可以有YC开关。VC就根据这个选项把 StdAfx.cpp编译成一个Obj文件和一个PCH文件
。
然后我们再选择一个其它的文件来看看,//其他cpp文件
在这里,Precomplier 选择了 Use ⋯⋯⋯一项,头文件是我们指定创建PCH 文件的stda
fx.h
文件。事实上,这里是使用工程里的设置,(如图1)/Yu”stdafx.h”。
这样,我们就设置好了预编译头文件。也就是说,我们可以使用预编译头功能了。以
下是注意事项:
1):如果使用了/Yu,就是说使用了预编译,我们在每个.cpp文件的最开头,我强调一遍
是最开头,包含 你指定产生pch文件的.h文件(默认是stdafx.h)不然就会有问题。如
果你没有包含这个文件,就告诉你Unexpected file end. 如果你不是在最开头包含的,
你自己试以下就知道了,绝对有很惊人的效果⋯..
fatal error C1010: unexpected end of file while looking for precompiled
header directive
Generating Code...
2)如果你把pch文件不小心丢了,编译的时候就会产生很多的不正常的行为。根据以上
的分析,你只要让编译器生成一个pch文件。也就是说把 stdafx.cpp(即指定/Yc的那个
cpp文件)从新编译一遍。当然你可以傻傻的 Rebuild All。简单一点就是选择那个cpp
文件,按一下Ctrl + F7就可以了。不然可是很浪费时间的哦。
//
呵呵,如果你居然耐着性子看到了这里,那么再回到帖子最开始看看我的总结吧!
第一句
如果我们之间有1000步的距离
你只要跨出第1步
我就会朝你的方向走其余的999步
第二句
通常愿意留下来跟你争吵的人
才是真正爱你的人
第三句
付出真心 才会得到真心
却也可能伤得彻底
保持距离 就能保护自己
却也注定永远寂寞
第四句
有时候 不是对方不在乎你
而是你把对方看得太重
第五句
朋友就是把你看透了 还能喜欢你的人
第六句
就算是believe 中间也藏了一个lie
第七句
真正的好朋友
并不是在一起就有聊不完的话题
而是在一起 就算不说话
也不会感到尴尬
第八句
没有一百分的另一半
只有五十分的两个人
第九句
为你的难过而快乐的 是敌人
为你的快乐而快乐的 是朋友
为你的难过而难过的
就是那些 该放进心里的人
第十句
冷漠 有时候并不是无情
只是一种避免被伤害的工具
Chris Anderson的长尾理论
说在前面
时下关于长尾的文章很多,但似乎很多人的理解都不一致。刚刚读过Chris关于Long Tail的那篇文章,给了我很多启发。(Chris正在准备关于长尾的书,将于2006年5月出版。)
长尾的渊源
Chris关于长尾的提出是基于他对娱乐市场的观察而得出的。通过对传统娱乐业和网络娱乐业的对比,Chris发现由于成本和规模的限制,传统娱乐业只能覆盖那些20%的主流(Hits)而忽略了后面的尾巴(Misses)。但是,网络技术解决了这个问题,使得在保证收益的前提下,满足了更多消费者的需求。同时,Chris还指出,人们对主流的关注一方面是因为传统娱乐业自身经营的限制(不可能提供所有的选择),另一个重要的方面是因为人们并不知道自己需要的是什么。Chris指出,事实上每一个人的品位都会与主流有所偏离,并且当我们发现的越多,我们就越能体会到我们需要更多的选择。这样,现实的世界(Physical World)是一个短缺的世界。(这也是为什么经济学存在的原因了)。
在这个基础上,Chris看到了Amazon,Vann-Adibé等网络书店和影像店的出现推翻了传统的认知,他们可以以较低的成本去提供更多的选择,这样,当人们越多越多的关注那些被遗忘的事物,他们会发现自己可以有更多的选择。而如果互联网商家能够捕捉的这些被遗忘的角落,就会有比主流市场更大的市场。这就是所谓的长尾。
对于如何抓住长尾市场,Chris提出了三项法则:
Rule 1:让所有的东西都可以获得。(Make everything available)
Rule 2:将价格减半,现在让它更低。(Cut the price in half. Now lower it.)
Rule 3:帮我找到它!(Help me find it!)
从(long tail theory) 看 去中心化的可能 (2006-12-31 16:28:06)
从长尾巴理论(long tail theory) 看 去中心化的可能
作者: 见素
Keso的很多文章提到网络的去中心化的问题. 也就是互联网的主导权不在局限在若干个大的上市公司,更多由平等,独立的中小个体主导.许多人尽管认可这是个好东西,但更多是抱有疑问.如他们的典型观点: 大公司钱多实力大,随便投点钱,也可以把你砸死.去中心化,固然美好,不过是一些人的一厢情愿而已.
每个人都有自己的知识结构,经验积累,看待事物也有自己特定的参考原则或者标准,更系统的就是所谓的意识形态. 同样一个事实,在不同的人看来完全可以有相反的视角和解读.这个post只写一些我对长尾巴理论的看法,我觉得它对于理解去中心化的过程很有启发. 当然 仁者见仁 智者见智,具体意见,欢迎在文章后面评论,共同提高.
(1) 介绍长尾巴理论的背景. 这个概念是 Wired 杂志主编 Chris Anderson 在2004年提出,大家可以 google 或 在wikipedia看详细的英文介绍. 最简单的例子: 在一个 XY的坐标系里面, y 对应销售收入, x对应 同一产业中不同品牌的产品或服务. 一般会出现名列前茅的几个品牌占据大部分的部分, 其他无数的小品牌占据小部分.
推广到其他情况
y 代表 点击数目, x 代表 不同的blogger
我们发现点击集中在少数所谓的opinion leader的上面
这些人属于曲线的头部, 大多数blogger 属于尾部,长长的尾部.
y 代表 购买力 x 代表 人群
也是大部分财富在 少数人手里,这些富人也是属于曲线头部,
其他的人都属于长长的尾巴了.
这些事情都是司空见惯,谈不上特别的地方.Anderson的独到地方 在于指出互联网的作用 能够很大程度上 促进人们对 尾巴部分的开发. 以前不能够实现的尾巴部分的潜力, 在互联网的帮助下可以转化成实际的东西.
比如 amazon的开始卖书, 它卖的书本 更多是以前书店卖不出去的书,
amazon出现了, 潜力化作行动,交易产生了,公司成长了.
还有 apple的iTunes的音乐商店, 它有上百万的歌曲,按每个.99美元出售,下载到ipod上.以前的唱片店铺都是卖最流行的部分,很多人即使想买以前的歌曲,但由于人群规模太小,唱片店铺不会为他们专门进货.但iTunes没有这些限制. 而且它的销售记录实实在在地证明, 所有的歌曲都至少被卖过一次.
以前 局限在尾巴的购买潜力,在iTunes得到实现.
2 对于尾巴市场地分析
有人将 long tail的 tail 部分,对应到 niche market, 中文翻译是缝隙市场.应该本质是一样的东西.
他们看似很小,微不足道,但是他们积少成多,总量可能比 head部分还多. 2004年的两个典型就是google 和craigslist,估计这也是触发Anderson在2004年10月在wired杂志阐述long tail的重要因素.
google不用介绍,大家都用,都很熟悉. google开始成长于niche market 90年代很多人觉得search engine 无钱可赚. google坚持深入开发这个市场的潜力, 几年后adword adsense的服务推出,目前达到 billion 量级的收入.完成了tail 到head的转化, 创造出一个新型的产业.
Craigslist 大家可能比较陌生, 偶尔在一些国内的媒体提及,但不太 深入. 它实际就是大的bbs,信息发布地方.今年国内的kijiji post.sina.com.cn 新业务,都可以看到它的影子. 它上面就是纯粹的信息发布,交流. 比如工作招聘, 房子出租,聚会等. 收入模式也很简单: 只对san Francisco/Los Angeles/New York/ 三个大城市的公司招聘收费, 而且价格比专门的招聘网站如 hotjobs monster等低的多. 目前它的pageview 达到 100M/day 的惊人地步,收入估计10M 美元左右.
他的秘诀也是类似google:执着作一件事情,把它做到更深入,更细致. 尤其是他的管理模式,独具一格. 比如它要对 纽约的房产广告收费, 它会公开post,征求用户的意见. 得到足够的用户反馈后,再
考虑实行. 用户有时候似乎扮演了类似股东,董事会的角色,非常有意思.
目前它的20%股份被ebay购买. 不过从 Craig Newmark(网站的主人) 的blog 看,似乎ebay购买了它以前一个员工的股份.他不情愿,但也没有办法,阻滞那个人的出售.不过主导权利还在craig的手里,
ebay也公开表示,它的购买不是为了其中的利润, 更多是学习 craigslist似乎简单但非常有效的管理模式. 我相信 craigslist 还是会继续保持现在的风格.
3 问题: google msn yahoo 能否击败类似craiglist的公司, 将他们 融入自己的体系?
我的感觉,这些大公司很难进入craigslist的范围:
其一: 社区的聚集和建立,名声的传播,不是短期内部可以用金钱和技术达到的
其二: 即使这些大公司, 可以利用它们的捆绑业务,免费提供给用户, 吸引用户过去.问题是,即使用户过去了,craigslist已经把收入降低到10M规模, 你不可能收取更多,这也从本质上打击了大公司进入craigslist的市场动力. 太小的市场不会对他们产生太大的吸引力.而且他们的资源不是无限的,他们也有各自主要对手的压力. 他们更愿意把资源和精力放在保持自己已经有的优势上面 ,或者还未开发的其他tail market, 而不是在一个已经被人开发的 tail market 争夺对他们来讲很小的市场空间.
4 小结
以前我在给 keso的留言提到: 大概在3-5年内 小网站的存储会转移到 google的集中的存储空间.现在 回过头再想想,感觉有些变化.
也许大部分回迁移, 但 真正面向用户,具有社区实力的niche market leader 应该不会迁移.对他们,硬盘,带宽的成本只是很小一部分因素, 尤其是技术进步,开源的发展,这些成本更会降低.
只要保持用户的信任,让用户有实际的归属,认同感.我相信这样的组织也会类似craigslist一样稳定发展,因为 本质上,它是在niche market上,满足用户需要的运行成本更低的组织形式. 从这种意义看, 长尾巴理论的本质也是 经济成本运行最低的一种表现.
这一点才是真正保证小规模的组织不会被几个大的上市公司吞并, 小公司仍然可以产生,生存,发展,壮大,绝非可以用钱砸死那么简单.
长尾巴市场(The Long Tail)
Posted at 12:13 in 奇文共赏.
Chris Anderson:The Long Tail
传统市场,采用稀缺假设(资源、时间等)和供求关系运作。所谓的2/8定律:80%的顾客只需要20%的商品,剩下长长的尾巴无人问津。主流,流行和品牌主导了市场和人们的视线,也确定了价格。
因特网市场:信息过剩,产品过剩。细分市场变得重要。由于信息、物品和服务可以几乎免费而无风险得获取,商业重点开始转向这个长长的尾巴。所谓个性化的市场。
...most successful businesses on the Internet are about aggregating the Long Tail in one way or another
面对这样的市场,对策有:
1)make everything available;
2)help people to find it;
3)cut the price,(increase the volumn)
长尾理论是有前提的,那就是我成本很小,网络的出现使成本小了,长尾也就成了理论,二八理论也并不意味着终结,两者是有不同的适用范围。
长尾长尾,尾有多长?
长尾如此多娇,引无数英雄竞折腰。面对商机无限的长尾市场,互联网巨擘Google和雅虎近期各显神通,再支高招。
13日,Google推出了视频上传服务。你可以将自己制作的视频节目上传给Google,视频节目不限大小,全免费,更酷的是你可以自主决定要向那些下载你节目的人收多少钱。
—-对DV爱好者、独立电影人来说,这是不是一个大好消息?
雅虎瞄准的是世界各地的小企业,推出了免费网站建设服务。现在,世界各地的小企业在没有任何技术背景的情况下,不费吹灰之力即可在网上安家。
雅虎的这项免费网站建设服务为小企业提供5个页面,你可以把自己公司的一些基本信息诸如公司名、联系人、联系地址、电话、电邮以及公司产品和服务等信息放在网上,这样,消费者通过互联网就可以找到他们需要的世界各地的产品和服务。
整个建站过程很简单,如果你已有一个雅虎帐号,不需5分钟就可搞定。
—-对那些无力建站又希望通过互联网与潜在客户互动的小企业来说,这是不是一个大好消息?
Google的视频托管服务瞄准的是“视频长尾”,在这个潜力巨大的长尾市场中,将造就一批视频长尾的弄潮儿。只要你的节目足够精彩,价格又不失公道,你也许会发现,吃香喝辣其实并不太难。雅虎的免费网站建设服务瞄准的是世界各地的“服务长尾”,一些小企业(包括个人)将成为受益者。而Goolge和雅虎这两个搜索巨人,却在“搜索长尾”中,成为笑到最后的最大赢家。
共赢,让长尾更长。
长尾与中心
华盛顿邮报报道,Google的市值在6月7日这天达到800亿美元,超过时代华纳20亿美元,成为世界第一媒体公司。这距离去年8月Google上市,仅仅10个月。当时,Google股票每股只有85美元,而现在,它的每股价值接近300美元。
这就是互联网的力量。这就是长尾的魅力。
现在,还有另外一家长尾公司Craigslist,无疑也是值得保持高度关注的。这家只有18名员工,目前对很多人来说可能还很陌生的公司,却有着惊人的表现:其网站访问量高居全球第四!
Google把自己做进了词典,把自己做成了全球第一媒体公司,接下去,它还会把自己做成什么?
EPIC那部电影关于未来媒体有一个耸人听闻的预言:
到2014年,我们现在所熟知的媒体将彻底消亡取而代之的是Google和Amazon合并组成的超级中心GoogleZon 2014年超级中心GoogleZon将推出EPIC(Evolving Personalized Information Construct),一个人人可参与,人人可报道,人人可获报酬,人人可定制新闻……的系统这是一个看似不可思议但又合乎逻辑的一种必然/可能?:
代表“去中心”的公民媒体和“中心”因为实现利益最大化的需要达成共谋,而借助互联网聚合了微中心(个人或团队)力量的“中心”演变成一个巨无霸级的超级中心。
目前来看,最具霸主相的“中心”,非Google莫属。
投票原理
对一件关系一个“集体”行动的事情,可以用投票来决定。投票的基本原则是:
1. 自己投票决定自己的命运(他人无权投票决定别人的命运)——自决原则。
2. 承认超过规定的有效票额的一方之选择为该事件的投票结果,也即集体的选择——服从原则。
3.可以不认同基本规则的第二条,即当投票结果并不是自己想要的也不想改变自己的想法时,则也可以“自由行动”。此时个人可以不服从集体的行动但也不享受集体的优势,同时“集体”不可以强行要求个人来服从“集体”,也无义务给个人提供“好处”——正义原则。
原则1(自决原则)其实是“不可否认”的,即每个人都“必须”遵守这个原则,而且“逃脱”不了。这很好理解。这也就是说每个正常的有行为能力的成年人都应该对自己的“命运”负责,自己必须也只能决定自己的命运,当然,如果一个人说“我派某某全权代表我来行使权力”,这其实仍然是自己做了决定的事(把自己的选择交由一个他信赖的人来做并认可/服从此人的选择)。原则2(服从原则)其实是人作为一个社会人从而不可避免需要跟其他人有各种形式的交往而做出的“利益最大化”选择。即当一个人虽然有自己的正当的选择但当一件事情需要一个集体的决策而自己跟“大多数人”的选择不一样的时候,选择服从大多数(也就是集体)通常是比不服从大多数来得更“划算”一些,所以一般人会承认此服从原则。其实从本质上来说,这仍然是自己在决定自己的选择。只不过原则1是对“具体事务”的投票规则,原则2是“规则的规则”,即如何确定一件发生概率在0和1之间的事件规则。因为既然是多人投票,则结果的各方比例肯定会在0和1之间,而最终结果只能选择其一的时候,此时必须有一个规则来进行选择。于是就有了这个服从原则,服从原则中所说的“有效票额”,通常是为50%,有的情况下也可以2/3,或者是“简单多数”。具体采取多大的比例,这又需要在具体投票前根据法律或其他规则进行确定。原则3(正义原则)其实是为了保护集体中任何一个个体在没有伤害到他人的情况下,也不应受到他人(或集体)的伤害,这也是文明发展的最根本指向,我称之为“自由意志的最大化”。简单点说就是,“我不伤害别人,则我也必不可受别人伤害”。近代以来人类文明逐步发展并普及下来的有关“平等,自由,民主,人权”等等“先进”的价值观念,在本质上都可以说是循着这条原则的。
现举案例模型如下:
某学校有个班级(A班)有30个人,某周末组织春游,所有花销AA制。现在有两种主流意见,一种说是去故宫,一种是去颐和园。不管去哪里,人数只要超过20人的团体游,则在景点处吃烧烤可以8折优惠。现在需要投票来表决。结果故宫得票17个,颐和园10个,另3个弃权。根据“投票基本原则”,超过一半有效,于是大家去故宫。通常的投票就应该是这样决定事情。这就是 “投票基本规则”的第1和第2条的应用。另外3个人是这样的:其中一个虽然没有投票(也许正好没时间,也许觉得去哪都行,随大家就可以),但承认规则2(服从原则),于是也去了故宫。而另外2个人并不认同这个原则2,此时就适用于规则3(补充条款),其中一个不想去故宫也不想去颐和园而想去长城(所以弃权,自己去了长城),另一个是只想去颐和园,决不考虑故宫(所以弃权,自己去了颐和园)。这样,在“正义的自由选择状态”下,30个人中28个人去了故宫,另两个没有一起去(也许各自去了想去的地方,或者也有个可能就是根本没有出去)。这就是“自己决定自己命运”的投票过程。
另外有一个大班(B班),有100个人,他们大多数人想去长城(当然其内部也经过类似的投票来决定这件事)。而且,他们知道,去长城满120人的话,吃烧烤可以6折优惠。这样B班就想让A班一起去。于是B班长来说,“走,我们都是一个学校的,一起去长城吧”,但是A班基本反对,不想去长城,B班班长就说,“不去不行,我们是一个学校的,而且,我们人数多,要以我们为主”。于是A班长提出“那我在班上投票看看吧”。他们班长说,“要投票我班也一起来投,看看是去哪里”——这很清楚,B班是不能这么做的。这个事例是说明,“一个人没有权利投票决定别人的命运”。但如果提出B班班长对A班班长说去长城“我们吃烧烤就都可以6折优惠了”,A班班长有点动心(也为了集体更大的利益),回去跟A班同学们说(鼓动说吃烧烤可以6折),A班竟然有很多人动心了,于是A班再次按“规则”进行一次投票,竟然通过了。于是A班和B班联合去了长城。这就是“为了利益最大化所进行的合理选择——联合”。吃完烧烤,他们一起登长城。这时候,B班几乎大多数人都要坐缆车(相对比较有钱吧)。而缆车满100人集体购票的话,可以打8折。但经过投票,发现他们班只有90个人愿意坐,人数不够。于是他们班长又鼓动A班集体购买缆车票。但是A班人可能都比较穷,总共只有5个人愿意做缆车。这样,B班班长也没有办法了,这95个人只好各自购买全价缆车票了并各自支付费用。这说明,当事情可以“单独进行”的时候,任何人都有权选择自己喜欢的方式进行,而不需要服从他人(即不适用规则2)。
以上原则适用于一个地区关于“是否独立”的谈判过程。
==================================
想不明白这天,这地,这人
爱情是人类的人为发明物
我来说说我有关爱情的一点思考。
现在我其实基本上倾向于认为爱情并不是人的“本质”,或者说,爱情这东西,其实不是“人”所原本具有的,而只是人“发明”的,是人类慢慢发展起来的一种文化现象而已。正如商家“发明”了“顾客是上帝”(或类似口号/思想),政客发明了“全心全意为人民服务”(或类似口号/思想)一样,爱情是人类(男人和女人)共同慢慢发明出来的一种“口号/思想”。只是作为商家的口号,通常是单方面即商家来使用(发出要约的行为),而其对手(顾客)会由此要求其提供良好的产品和服务(接受要约);而作为政客的口号,通常也只是政客单方面使用,其对手(人民)会由此来要求政客“做到其所说的”。而实际上,他们之间的关系的本质,就是要约方发出一定的“承诺”以得到对方的认可——得到认可的目的其实就是为了自己得到自己所需要的。爱情双方的关系也大致如此。但对于爱情,稍稍有点不同的是,发出要约方(说“我爱你”的那个),常常在男方和女方都会很多。而对于特定的一对男女,发出要约的一方会随着时间/境地的改变而改变。如现在通常人们所观察到的和大家所基本认同的现象是,通常男方在开始发出要约(说“我爱你”),然后过了一定的时间——人们通常认为是结婚时间——后,发出要约方就换了身份了,变成女方更多发出此要约——她更需要说“我爱你”来维持这样的现状。当然,这其中的要约方和受要约方的转换时间并不是那么清析的,而常常可能是相互纠缠相互作用而进行的。
如果我们考察更多更宽泛的人类历史和现状——文化人类学范畴——的话,我们会发现,所谓爱情,并不是“从来就有”或“自身固有”的。在人类更加漫长的历史(其实也不要太漫长,只要考察近两三千年的“文明时代”就可以)中,人类生活中的绝大部分的“婚姻生活”——实际婚姻也是一种发明,是人类社会发展到一定程的需要,又发展到一定程度的时候也是可以不需要的,但这是另一个问题了——并不是以“爱情”为基础的。当然,这么说并不是说就是否定了古代偶尔出现的“伟大爱情”的存在的事实,只是说,在绝大多数的时间和人群中,人们的“结合”远不是因为爱情,甚至基本不考虑有没有爱情——可能根本就没有这个问题。即使在现在,如果考察稍稍离开现代社会远一点的地区和国家,我们会发现,爱情也通常都是一种很“陌生”的东西。不要说一些地区常有“多姐妹同嫁一男”的风俗,也不要说一些地区“几兄弟共娶一女/多女”的现象,单说我们这个社会上溯百年之前的情形,男女之间的婚事从来都不是他们自己所能决定的,往往的情况都是双方根本未曾谋面或近距离说过话的,而后也是一样的能够“白头偕老”一辈子。甚至,这样长久的“文化传统”其实对现在的很多农村地区仍有着深远的影响,只是程度可能没那么严重了。国外古时候的情况也并没有好到哪里去,嫁女从来首要考虑的都是类似“对方的财产和地位”这样“非爱情”的因素,这就不说了。
“爱情”这个东西,仔细考察起来的话,也就是近几百年来社会发展到一定程度,个人特别是女性的自由度大增了之后才慢慢逐渐普及并“泛滥”了起来的。对于一个有一定“生存实力”又有一定自由的女子来说,其作为个人当然会对其所喜好的男人有所选择,这在“爱情市场”上就是一种“自由购买”行为,比如,她需要对方“英俊潇洒,体格健壮,才华横溢,忠贞不渝”等等。这样,对于一个对其倾慕的男子来说,就上前发出“要约”,说,你看,我“英俊潇洒,体格健壮,才华横溢”,我会对你永远中心耿耿,我会给你幸福——总之,一句话,“我爱你”——于是“爱情”就产生了。因为其实一个人“喜欢”或“接受”另一个人,包含了很多很多的因素,有些因素是一目了然的,有些因素是隐藏难辨的,有些因素是居变不常的。因此,人们就只好用“爱情”这个模糊的字眼来描述这么一个状态,并以此作为一个手段来“获取”对方或要求对方。而其本质上,如果考察人们的生活状态的话,我们发现,爱情,只是人们用来“提升”自己生活质量的一个手段而已。如果相爱的双方因为“获得”了对方而都提升了自己的生命/生活质量,那就是爱情的作用。如果未来社会发展的状态,能够完全有效地保护每一个人的“自由意志”的话,我相信那时候的“爱情”会更加短暂和有趣,而不再象现在爱情的 过渡阶段”的社会所常常伴随着痛苦和遗憾。想想看,如果一个人不爱一个人了,而要离开,被“抛弃”的那个人并不因此而就“没有活路”(当然这是最严重的,只有古代才有这样的现象,现在几乎没有了,但类似的思想和现象还是有很多的,只是程度不同而已。),而只是一般意义上的别人不跟自己“合作”了关系,自己也反而可以有其他更多的机会来选择别人,那世间必定少了许许多多的恩怨情仇。所以,我认为,现在社会还只是处于“没有爱情”和“真实爱情”(人性?)的中间过渡阶段。
——当然,以上所说的爱情,是我们现阶段通常所说的某种爱情,大致具有如下特征:忠贞不渝,为其所狂,排他性,独占性。
“爱情是人类的人为发明物”,这就是我的观点。但这么说,并不是说我们现在所目及的普遍存在的爱情就是假的,不存在的,或是虚伪的,矫饰的。但是,不可避免地,正如我们所能看到的,很多的事情也是假借着爱情的名义而进行的。又如,有关“自由和民主”的概念/思想,也是人类文明发展到一定程度而普及出来的一种观念,而并非真的什么“天赋人权”。在漫长的奴隶社会里,人们是不可能有这样的观念的——当然也正如爱情一样,不排除偶尔的特例,也更有很多的“恶”是假借这自由民主的名义而进行的。
==================================
想不明白这天,这地,这人
© 版权所有,欢迎盗版——记得盗亦有道啊^_^
给你所爱的人以自由
给你所爱的人以自由,这是化解“相爱”的男女两性之间的冲突与矛盾的根本解决之道。
所谓爱情,所谓婚姻,其实往往是人类(动物)私心的一种实现方式。人们总是想在爱或婚姻的幌子下实现“付出更少获得更多”的自私本能。比如,爱,一个人爱上另一个人并“积极追求”的时候,其实总是希望能获得“丰厚的回报”的,至少是“相应的回报”。虽然在开始的阶段,似乎常常是“不求回报”的。但是,在人们内心的“潜意识”里,都知道这只是在做“投资”,是属于未来回报的“前期成本”。如果人们在进行了一定的投入后发现竟然有可能会没有(或几乎没有)回报——对方不太可能认同并选择自己,那人们通常采取的行动就是“终止投资”——这就是单恋者追求的终止。这个过程通常发生在男追女的恋爱前期。当一个人对另一个人的投入相对于他自己来说“过于巨大”而最后竟然只好“放弃”(即没有回报)的时候,经常发生一些“激烈的事情”,如对被追求者的伤害,或是自我伤害(如自杀,酗酒,自暴自弃)。这其实跟商业投资人投资失败表现是类似的。但是,人们往往忘了(?)其实爱的本意是“给与”,是“付出”,就是“希望所爱的人好”。既然自己所追求的人没有选择自己,那只能说明一件事:对方认为这样是“更好的”。既然是更好的,那你作为爱他的人,为什么就不能“高兴”呢?——至少是,应该尊重对方的选择。当然,从这个侧面也证明了,人们通常所谓的爱,其实并不是单纯是“爱”,或者说,其实并不是“单纯的爱”。
另外,从权利义务的逻辑角度来说,一个人爱另一个,只是一种“单方面”的行为(感情),这种行为并没有什么必然的逻辑来要求对方也“爱”自己。或者说,虽然你爱着对方,但对方并不因此有义务来“回爱”你,也就是没有义务来对你的“投资”进行回报。所以,从这个角度来说,爱只能是“宽容”的,不求回报的,没有条件的。当然,现实中的爱为什么常常会“有回报”呢?这很简单,这也是人们在面对“被人”爱的情况下,对“不给与回报”的情况下自己所能获得的“利益”和“给与回报”的情况下所能获得的“利益”的权衡结果。选择前者所获得的利益就是可以有“更多的选择”,但是不一定更多的选择就比“现在的选择”更好,人们自然会有自己的判断。选择后者所获得的利益显而易见就是眼前实实在在的那个人给与自己的“爱”。而且,基于人类的“不变的自私性”,这种接受对方的爱的行为必然要促使自己也付出“相应的爱”,否则自己所获得的这些爱不能保持长久。这些其实完全是基于“计算”而选择的。因为如此,所以,世人往往相爱或“相守一生”都是基于一种付出与回报的权衡的结果,因而往往都是“门当户对”的。但是,虽然如此,我们从这些逻辑来看,也必不能得出爱的付出必须有所回报的道理。所以,爱一个人,不管是男人,还是女人,除了给与一定的“付出”这种积极行为外,更应该做到“给所爱的人以自由”这种消极行为,也就是“不干涉”。要相信对方的所选是他所愿的,而如果没有“如你的意”而干涉对方那其实是你在“要求回报”,这是实实在在的“过渡自私”行为。
在现实中,不管是恋爱中还是婚姻中,男女两性其实都是在“时刻计算着付出与回报”的。在恋爱的时候,如果一方“计算”的结果觉得自己在这场关系中是并“不合算”的,而且如果停止这段关系(也就是停止这里的投资)而很可能能够在其他地方获得“相当的回报”,那这一方就往往会选择结束这段爱情,这就是分手。在分手中,被“抛弃”的一方往往“感觉痛苦”,那就是觉得自己的付出竟然最后“打了水漂”的那种痛心。而其实如果能想想自己的本意是“爱对方”的话,就不应如此痛心才是,因为对方选择离开恰恰是“选择更好的生活”。此时,真正的“爱人”应该是祝福对方,至少是不应该去伤害对方——自然也无有必要伤害自己。在婚姻中,由于现实的原因,男女两性在社会中的“生存能力”的差异,导致男性其实是在一个确定的婚姻关系中往往占有“优势”的。这样,从“付出与回报”的平衡角度来看,男性往往会觉得自己“付出更少一些”也能够值得女性“全身心的付出”,“出轨”或“花心”的行为就是那部分“没有全部付出的爱”的释放行为。社会也就形成了更严格的“妇道”和更宽容的“夫道”的“不平等道德观”——其实从本质上来说,这是平等的。这道德观的“不平等值”基本相当于男性大于女性的那部分“生存能力值”(至于这两个值怎么换算,我也不知道)。随着现代女性的谋生能力的提升,男女两性的生存能力的差值越来越小,两性之间的道德不平等性也越来越少——这是有目共睹的。所以,女权主义的所有诉求,在我看来,其本质和目标都是为了提高女性在这个社会的“生存能力”。这里,生存能力不是指纯粹的“活下来”的能力,而是包含更广泛的“生命质量”的意义。对于具体的个人来说,当家庭里男人有各种“外在的消遣”的时候,除了从“爱”的角度(如果真的是爱的话)给与男人更多的自由外,女人也应该尽可能地学会有自己更多的生活娱乐,提升自己的生命质量(自助式),而不是把希望全都寄托在那个叫做丈夫的男人身上(索求式)。这不但实现了自救,也实现了“真爱”——给对方自由。而且,从现实的考量来说,这样做的效果往往会“迫使”男人回到家里来,因为你的“自助式”的生活质量的提高,另男人会觉得“心慌慌”,因为你的“独立的快乐”另男人担心其要失去“性别优势”甚或“鸡飞蛋打”,这自然不是他希望的结果,因为这样的结果对他而言就是“回报为零”,这显然不是他“分出一部分爱”的初衷,他的初衷只是付出一部分爱而希望能得到你的“全部的爱”。
综合起来,就是,既要“给爱的人以自由”,又要努力自己提升自己的生命质量。而后一点,其实说白了也就是不要要求对方来给自己“爱”——这仍然是爱的本意,那就是“不求回报”。
==================================
想不明白这天,这地,这人
© 版权所有,欢迎盗版——记得盗亦有道啊^_^
图像处理是指将图像信号转换成数字信号并利用计算机对其进行处理的过程。图像处理最早出现于20世纪50年代,当时的电子计算机已经发展到一定水平,人们开始利用计算机来处理图形和图像信息。数字图像处理作为一门学科大约形成于20世纪60年代初期。早期的图像处理的目的是改善图像的质量,它以人为对象,以改善人的视觉效果为目的。图像处理中,输入的是质量低的图像,输出的是改善质量后的图像,常用的图像处理方法有图像增强、复原、编码、压缩等。首次获得实际成功应用的是美国喷气推进实验室(JPL)。他们对航天探测器徘徊者7号在1964年发回的几千张月球照片使用了图像处理技术,如几何校正、灰度变换、去除噪声等方法进行处理,并考虑了太阳位置和月球环境的影响,由计算机成功地绘制出月球表面地图,获得了巨大的成功。随后又对探测飞船发回的近十万张照片进行更为复杂的图像处理,以致获得了月球的地形图、彩色图及全景镶嵌图,获得了非凡的成果,为人类登月创举奠定了坚实的基础,也推动了数字图像处理这门学科的诞生。在以后的宇航空间技术,如对火星、土星等星球的探测研究中,数字图像处理技术都发挥了巨大的作用。数字图像处理取得的另一个巨大成就是在医学上获得的成果。1972年英国EMI公司工程师Housfield发明了用于头颅诊断的X射线计算机断层摄影装置,也就是我们通常所说的CT(Computer Tomograph)。CT的基本方法是根据人的头部截面的投影,经计算机处理来重建截面图像,称为图像重建。1975年EMI公司又成功研制出全身用的CT装置,获得了人体各个部位鲜明清晰的断层图像。1979年,这项无损伤诊断技术获得了诺贝尔奖,说明它对人类作出了划时代的贡献。与此同时,图像处理技术在许多应用领域受到广泛重视并取得了重大的开拓性成就,属于这些领域的有航空航天、生物医学工程、工业检测、机器人视觉、公安司法、军事制导、文化艺术等,使图像处理成为一门引人注目、前景远大的新型学科。随着图像处理技术的深入发展,从70年代中期开始,随着计算机技术和人工智能、思维科学研究的迅速发展,数字图像处理向更高、更深层次发展。人们已开始研究如何用计算机系统解释图像,实现类似人类视觉系统理解外部世界,这被称为图像理解或计算机视觉。很多国家,特别是发达国家投入更多的人力、物力到这项研究,取得了不少重要的研究成果。其中代表性的成果是70年代末MIT的Marr提出的视觉计算理论,这个理论成为计算机视觉领域其后十多年的主导思想。图像理解虽然在理论方法研究上已取得不小的进展,但它本身是一个比较难的研究领域,存在不少困难,因人类本身对自己的视觉过程还了解甚少,因此计算机视觉是一个有待人们进一步探索的新领域。
图像处理主要研究的内容有以下几个方面:
1) 图像变换由于图像阵列很大,直接在空间域中进行处理,涉及计算量很大。因此,往往采用各种图像变换的方法,如傅立叶变换、沃尔什变换、离散余弦变换等间接处理技术,将空间域的处理转换为变换域处理,不仅可减少计算量,而且可获得更有效的处理(如傅立叶变换可在频域中进行数字滤波处理)。目前新兴研究的小波变换在时域和频域中都具有良好的局部化特性,它在图像处理中也有着广泛而有效的应用。
2) 图像编码压缩图像编码压缩技术可减少描述图像的数据量(即比特数),以便节省图像传输、处理时间和减少所占用的存储器容量。压缩可以在不失真的前提下获得,也可以在允许的失真条件下进行。编码是压缩技术中最重要的方法,它在图像处理技术中是发展最早且比较成熟的技术。
3) 图像增强和复原图像增强和复原的目的是为了提高图像的质量,如去除噪声,提高图像的清晰度等。图像增强不考虑图像降质的原因,突出图像中所感兴趣的部分。如强化图像高频分量,可使图像中物体轮廓清晰,细节明显;如强化低频分量可减少图像中噪声影响。图像复原要求对图像降质的原因有一定的了解,一般讲应根据降质过程建立"降质模型",再采用某种滤波方法,恢复或重建原来的图像。
4) 图像分割图像分割是数字图像处理中的关键技术之一。图像分割是将图像中有意义的特征部分提取出来,其有意义的特征有图像中的边缘、区域等,这是进一步进行图像识别、分析和理解的基础。虽然目前已研究出不少边缘提取、区域分割的方法,但还没有一种普遍适用于各种图像的有效方法。因此,对图像分割的研究还在不断深入之中,是目前图像处理中研究的热点之一。
5) 图像描述图像描述是图像识别和理解的必要前提。作为最简单的二值图像可采用其几何特性描述物体的特性,一般图像的描述方法采用二维形状描述,它有边界描述和区域描述两类方法。对于特殊的纹理图像可采用二维纹理特征描述。随着图像处理研究的深入发展,已经开始进行三维物体描述的研究,提出了体积描述、表面描述、广义圆柱体描述等方法。
6) 图像分类(识别)图像分类(识别)属于模式识别的范畴,其主要内容是图像经过某些预处理(增强、复原、压缩)后,进行图像分割和特征提取,从而进行判决分类。图像分类常采用经典的模式识别方法,有统计模式分类和句法(结构)模式分类,近年来新发展起来的模糊模式识别和人工神经网络模式分类在图像识别中也越来越受到重视。
杰作
时域、频域、时频分析与数学分支简介
不论从时域、空域还是从频域来对某一系统进行描述,本来就是一个角度问题,从任何一个域来看都可以给出某种正交完备描述。具体来说,不论是注重粒子性的泰勒展开、还是注重波动性的傅立叶展开,各种正交完备函数族的展开式不过是特定角度的分析,但每一个分析方法都是完备的,能描述宇内宙中一切可能变化性态,而且各分析方法间具有某种变通和映射关系(如傅立叶正逆变换,正逆变换合为一很可能就是双s太极,其中的2п因子是因为整体性圆的缘故),只是描述角度和描述方法的不同,其中所蕴含的系统总能量和总信息量是完全守恒和等价的(如在傅立叶积分变换中有巴塞瓦尔定理保证能量守恒)。
需要指出的是,在傅立叶分析中实部部分对应实物质,虚部部分对应虚物质,它们分别按照一定实虚配比(体现为复相角,对应功界所说“性”)和能量(体现为模,对应功界所说“命”)分布于不同频率上,形成全频谱分布结构(若各频率分量等能量等幅分布,在一维情形整体叠加为时不变常数信号,则为“入道”),这和用随时间或空间坐标变化函数的规律描述形式虽然是完全相通的,在本质上都是从不同角度对变化的描述,但前者由于波动的全域特性,从而更容易体现实空间(非相空间)规律的“整体性”,因此更符合东方传统认知习惯,形成幻假幻真的全频谱波象空间规律的描述。
实际上频谱的分析对应另一套完备的对于世界存在及其演化规律的分析方法(如功修中可能出现的频谱变化,特别是频谱切换和频谱反转现象),各级频谱的交参变化可以解释时间本质(本来并没有时间,时间是频谱扰动变化所造成的假象),只有将两种分析方法互补结合,认识才能更全面,从而正交超越真假分别剖判进入无界域而直参当下(正交的概念最初来源于直线或平面的垂直,比如如果一条直线垂直于一个平面,则该直线垂直于平面内的所有直线,也可以说与平面中所有直线正交,互不存在投影分量;又比如空间直角坐标系三条坐标轴在原点处两两互相正交,人体也可能存在着互相正交的三轴,也有原点),体证真空妙有。
回顾数学发展的历程,在上一世纪的数学家们所孜孜不倦追求的是:数学理论的完美性和数学应用的广泛性。在这两个项目的追求上,数学理论的完备完美性已经不成问题,而对于应用的广泛性,现代分析学的两个分支,即上世纪初创立的泛函分析学和近些年发展起来的小波分析学取得了突出的成就。由希尔布特亲自奠基的泛函分析学,综合的运用了几何学、代数学和分析学(泰勒展开微积分)的观点和方法,统一的处理和论证了许多数学分支的一系列问题。20世纪的分析学开拓了一个又一个新的领域,除了泛函分析外,还有数值分析、傅氏分析、样条分析和小波分析等,今天,现代分析学这个数学面向应用的广泛性的数学分支已经成长为一株枝繁叶茂的大树耸立于学科之林,其中小波分析由于吸取了众多分支的精华并包罗了它们的许多特色,将会是这株大树的主干。小波变换来源于信号分析,是在傅立叶变换的基础上发展起来的。
我们知道,自然界存在各种时间或空间上的周期性现象,在各种各样错综复杂的周期信号中,类似简谐振动的周期变化是最简单的,根据傅立叶级数的研究可以知道,任何周期性现象,不论其周期循环部分表述多么复杂,都可以进行傅氏级数展开而表示成无限多正余弦简谐函数和的叠加,其中各频率分量为某一基频的整数倍(整数取值从0至无穷大)。特别值得指出的是,正余弦函数是圆函数,与圆的关系极为密切,而傅里叶变换乃是将傅立叶级数展开一直推广到一般函数(其周期为无限大,相对应基频变为频率微元----无穷小频率),对于不满足傅里叶级数展开条件的(具有有限个第一类间断点,在无穷大区间上绝对可积)信号分析,则引入狄拉克广义奇异函数(虽然其引入在表面上看来有些牵强,但在自然界中真实存在该类函数所描述的现象,描述的是瞬时过程或点采样,而且也可以无矛盾的纳入数学分析体系,数学分析体系是一个逻辑上自洽完备统一而又自圆其说的理论体系),最后使得傅立叶分析完备起来。而小波分析是傅立叶分析的进一步深入,其主要特征是可以进行多尺度分析与时频结合分析(可以从不同尺度上同时考虑时间和空间看同样一个信号),已经广泛应用在工程实践中。
随着计算机在科学计算领域里的广泛应用,数值计算与分析也作为一个特殊的数学分支而迅速发展起来,很多用传统解析方法难以求解的非线性方程,现在可以用计算机求得其数值解,并进一步研究其存在、演化和作用规律,直接推动了非线性科学的长足发展。在非线性科学所属的混沌、分形科学研究中,多项式方程解的分形流域边界问题是一个很重要的课题。运用群论知识可以证明(群论在前沿物理对称性理论和量子化学配位理论研究中具有重要地位),5阶和5阶以上的多项式方程无求根公式(人们感知空间知是四维空间的一部分,可能是镶嵌于四维空间中的维数大于3的分形空间),因此对于这些多项式方程求解必须要通过数值方法来完成。其中,比较常用的方法就是牛顿迭代法,由于迭代初值的选取是任意的,通过有限次迭代具体收敛到哪一个根(通过数学学习我们知道,在复数域中,一次多项式方程有一个根,2次有两个根,3次三个,。。。n次n个。。。),是迭代流域研究所关注的问题,科学家进一步细化发现,这些边界是模糊的,具体来说其初始值迭代边界具有模糊、对称和分形特征。这里边隐含的哲学含义很深刻,多项式的解对应整体多项式值为0的点,且都均匀对称分布于一个圆周上(还可以一阶通变矩阵---雅可比矩阵的特征值联系起来,复数根对应波动,这是体外话),是整个多项式迭代动力系统中的不动点(奇异点),整体迭代流域对复平面的分割是常空间和分形空间的整体统一,对于研究宇宙时空结构将非常具有启发意义。
[转帖] 二十世纪十大算法
2008-10-12 11:03
二十世纪七大算法:
1946年 蒙特卡洛方法;
1951年 矩阵计算的分解方法;
1959~1961年 计算矩阵特征值的QR算法;
1962年 快速排序算法;
1965年 快速傅利叶变换算法;
1977年 整数关系探测算法;
1987年 快速多极算法。
下面是二十世纪最好的十大算法:
20世纪最好的算法,计算机时代的挑选标准是对科学和工程的研究和实践影响最大。下面就是按年代次序排列的20世纪最好的10个算法。
1. Monte Carlo方法
1946年,在洛斯阿拉莫斯科学实验室工作的John von Neumann,Stan Ulam和Nick Metropolis编制了Metropolis算法,也称为Monte Carlo方法。Metropolis算法旨在通过模仿随机过程,来得到具有难以控制的大量的自由度的数值问题和具有阶乘规模的组合问题的近似解法。数字计算机是确定性问题的计算的强有力工具,但是对于随机性(不确定性)问题如何当时并不知晓,Metropolis算法可以说是最早的用来生成随机数,解决不确定性问题的算法之一。
2. 线性规划的单纯形方法
1947年,兰德公司的Grorge Dantzig创造了线性规划的单纯形方法。就其广泛的应用而言,Dantzig算法一直是最成功的算法之一。线性规划对于那些要想在经济上站住脚,同时又有赖于是否具有在预算和其他约束条件下达到最优化的能力的工业界,有着决定性的影响(当然,工业中的“实际”问题往往是非线性的;使用线性规划有时候是由于估计的预算,从而简化了模型而促成的)。单纯形法是一种能达到最优解的精细的方法。尽管理论上讲其效果是指数衰减的,但在实践中该算法是高度有效的——它本身说明了有关计算的本质的一些有趣的事情。
3. Krylov子空间叠代法
1950年,来自美国国家标准局的数值分析研究所的Magnus Hestenes, Eduard Stiefel和Cornelius Lanczos开创了Krylov子空间叠代法的研制。这些算法处理看似简单的求解形为Ax=b的方程的问题。当然隐藏的困难在于A是一个巨型的n*n 矩阵,致使代数解x=b/A是不容易计算的(确实,矩阵的“相除”不是一个实际上有用的概念)。叠代法——诸如求解形为Kx(k+1)=Kx(k)+b-Ax(k)的方程,其中K 是一个理想地“接近”A 的较为简单的矩阵——导致了Krylov子空间的研究。以俄罗斯数学家Nikolai Krylov命名的Krylov子空间由作用在初始“余量”向量 r(0)=b-Ax(0)上的矩阵幂张成的。当 A是对称矩阵时,Lanczos找到了一种生成这种子空间的正交基的极好的方法。对于对称正定的方程组,Hestenes 和Stiefel提出了称为共轭梯度法的甚至更妙的方法。过去的50年中,许多研究人员改进并扩展了这些算法。当前的一套方法包括非对称方程组的求解技巧,像字首缩拼词为GMRES和Bi-CGSTAB那样的算法。(GMRES和Bi-CGSTAB分别首次出现于1986和1992 SIAM journal on Scientific and Statistical computing(美国工业与应用数学学会的科学和统计计算杂志)。
4. 矩阵计算的分解方法
1951年,橡树岭国家实验室的A1ston Householder系统阐述了矩阵计算的分解方法。研究证明能把矩阵因子分解为三角、对角、正交和其他特殊形式的矩阵是极其有用的。这种分解方法使软件研究人员能生产出灵活有效的矩阵软件包。这也促进了数值线性代数中反复出现的大问题之一的舍入误差分析问题。 (1961年伦敦国家物理实验室的James Wilkinson基于把矩阵分解为下和上三角矩阵因子的积的LU分解,在美国计算机协会(ACM)的杂志上发表了一篇题为“矩阵逆的直接方法的误差分析”的重要文章。)
5. Fortran最优编译程序
1957年,John Backus在IBM领导一个小组研制Fortran最优编译程序。Fortran的创造可能是计算机编程历史上独一无二的最重要的事件:科学家(和其他人)终于可以无需依靠像地狱那样可怕的机器代码,就可告诉计算机他们想要做什么。虽然现代编译程序的标准并不过分――Fortran I只包含23,500条汇编语言指令――早期的编译程序仍然能完成令人吃惊的复杂计算。就像Backus本人在1998年在IEEE annals of the History of computing 发表的有关Fortran I,II, III的近代历史的文章中回忆道:编译程序“所产生的如此有效的代码,使得其输出令研究它的编程人员都感到吓了一跳。”
6. 矩阵本征值计算的QR算法
1959—61年,伦敦Ferranti Ltd.的J.G. F. Francis找到了一种称为QR算法的计算本征值的稳定的方法。本征值大概是和矩阵相连在—起的最重要的数了,而且计算它们可能是最需要技巧的。把—个方阵变换为一个“几乎是”上三角的矩阵――意即在紧挨着矩阵主对角线下面的一斜列上可能有非零元素――是相对容易的,但要想不产生大量的误差就把这些非零元素消去,就不是平凡的事了。QR 算法正好是能达到这一目的的方法,基于QR 分解, A可以写成正交矩阵Q 和一个三角矩阵R 的乘积,这种方法叠代地把 A=Q(k)R(k) 变成 A(k+1)==Q(k)R(k) 就加速收敛到上三角矩阵而言多少有点不能指望。20世纪60年代中期QR 算法把一度难以对付的本征值问题变成了例行程序的计算。
7. 快速分类法
1962:伦敦Elliott Brothers, Ltd.的Tony Hoare提出了快速(按大小)分类法.把n个事物按数或字母的次序排列起来,在心智上是不会有什么触动的单调平凡的事。智力的挑战在于发明一种快速完成排序的方法。Hoare的算法利用了古老的分割开和控制的递归策略来解决问题:挑一个元素作为“主元”、把其余的元素分成“大的”和“小的”两堆(当和主元比较时)、再在每一堆中重复这一过程。尽管可能要做受到严厉责备的做完全部N(N-1)/2 次的比较(特别是,如果你把主元作为早已按大小分类好的表列的第一个元素的话!),快速分类法运行的平均次数具有O(Nlog(N)) 的有效性,其优美的简洁性使之成为计算复杂性的著名的例子。
8. 快速Fourier变换
1965年,IBM的T. J. Watson研究中心的James Cooley以及普林斯顿大学和AT&T贝尔实验室的John Tukey向公众透露了快速Fourier变换(方法)(FFT)。应用数学中意义最深远的算法,无疑是使信号处理实现突破性进展的FFT。其基本思想要追溯到Gauss(他需要计算小行星的轨道),但是Cooley—Tukey的论文弄清楚了Fourier变换计算起来有多容易。就像快速分类法一样,FFT有赖于用分割开和控制的策略,把表面上令人讨厌的O(N*N) 降到令人满意的O(Nlog(N)) 。但是不像快速分类法,其执行(初一看)是非直观的而且不那么直接。其本身就给计算机科学一种推动力去研究计算问题和算法的固有复杂性。
9. 整数关系侦查算法
1977年,BrighamYoung大学的Helaman Ferguson 和Rodney Forcade提出了整数关系侦查算法。这是一个古老的问题:给定—组实数,例如说x(1),x(2),…,x(n) ,是否存在整数a(1),a(2),..,a(n) (不全为零),使得
a(1)x(1)+a(2)x(2)+…+a(n)x(n)=0
对于n=2 ,历史悠久的欧几里得算法能做这项工作、计算x(1)/x(2) 的连分数展开中的各项。如果x(1)/x(2) 是有理数,展开会终止,在适当展开后就给出了“最小的”整数a(1)和a(2) 。欧几里得算法不终止——或者如果你只是简单地由于厌倦计算——那么展开的过程至少提供了最小整数关系的大小的下界。Ferguson和Forcade的推广更有威力,尽管这种推广更难于执行(和理解)。例如,他们的侦查算法被用来求得逻辑斯谛(logistic)映射的第三和第四个分歧点,b(3)=3.544090 和 b(4)=3.564407所满足的多项式的精确系数。(后者是120 阶的多项式;它的最大的系数是257^30 。)已证明该算法在简化量子场论中的Feynman图的计算中是有用的。
10. 快速多极算法
1987年,耶鲁大学的Leslie Greengard 和Vladimir Rokhlin发明了快速多极算法。该算法克服了N体模拟中最令人头疼的困难之一:经由引力或静电力相互作用的N个粒子运动的精确计算(想象一下银河系中的星体,或者蛋白质中的原于)看来需要O(N*N) 的计算量——比较每一对质点需要一次计算。该算法利用多极展开(净电荷或质量、偶极矩、四矩,等等)来近似遥远的一组质点对当地一组质点的影响。空间的层次分解用来确定当距离增大时,比以往任何时候都更大的质点组。快速多极算法的一个明显优点是具有严格的误差估计,这是许多算法所缺少的性质。
三、结束语
2l世纪将会带来什么样的新的洞察和算法?对于又一个一百年完整的回答显然是不知道的。然而,有一点似乎是肯定的。正如20世纪能够产生最好的l0个算法一样,新世纪对我们来说既不会是很宁静的,也不会是弱智的。
|
[转]http://alpswy.spaces.live.com/
By Barry A. Cipra
Algos is the Greek word for pain. Algor is Latin, to be cold. Neither is the root for algorithm, which stems instead from al-Khwarizmi, the name of the ninth-century Arab scholar whose book al-jabrwa’l muqabalah devolved into today’s high school algebra textbooks. Al-Khwarizmi stressed the importance of methodical procedures for solving problems. Were he around today, he’d no doubt be impressed by the advances in his eponymous approach.
Some of the very best algorithms of the computer age are highlighted in the January/February 2000 issue of Computing in Science & Engineering, a joint publication of the American Institute of Physics and the IEEE Computer Society. Guest editors Jack Don-garra of the University of Tennessee and Oak Ridge National Laboratory and Fran-cis Sullivan of the Center for Comput-ing Sciences at the Institute for Defense Analyses put togeth-er a list they call the “Top Ten Algorithms of the Century.”
“We tried to assemble the 10 al-gorithms with the greatest influence on the development and practice of science and engineering in the 20th century,” Dongarra and Sullivan write. As with any top-10 list, their selections—and non-selections—are bound to be controversial, they acknowledge. When it comes to picking the algorithmic best, there seems to be no best algorithm. Without further ado, here’s the CiSE top-10 list, in chronological order. (Dates and names associated with the algorithms should be read as first-order approximations. Most algorithms take shape over time, with many contributors.)
1.蒙特卡洛算法
1946: John von Neumann, Stan Ulam, and Nick Metropolis, all at the Los Alamos Scientific Laboratory, cook up the Metropolis algorithm, also known as the Monte Carlo method. The Metropolis algorithm aims to obtain approximate solutions to numerical problems with unmanageably many degrees of freedom and to combinatorial problems of factorial size, by mimicking a random process. Given the digital computer’s reputation for deterministic calculation, it’s fitting that one of its earliest applications was the generation of random numbers.
2.单纯形法
1947: George Dantzig, at the RAND Corporation, creates the simplex method for linear programming. In terms of widespread application, Dantzig’s algorithm is one of the most successful of all time: Linear programming dominates the world of industry, where economic survival depends on the ability to optimize within budgetary and other constraints. (Of course, the “real” problems of industry are often nonlinear; the use of linear programming is sometimes dictated by the computational budget.) The simplex method is an elegant way of arriving at optimal answers. Although theoretically susceptible to exponential delays, the algorithm in practice is highly efficient—which in itself says something interesting about the nature of computation. In terms of widespread use, George Dantzig’s simplex method is among the most successful algorithms of all time.
3.Krylov子空间迭代法
1950: Magnus Hestenes, Eduard Stiefel, and Cornelius Lanczos, all from the Institute for Numerical Analysis at the National Bureau of Standards, initiate the development of Krylov subspace iteration methods. These algorithms address the seemingly simple task of solving equations of the form Ax = b. The catch, of course, is that A is a huge n x n matrix, so that the algebraic answer x = b/A is not so easy to compute. (Indeed, matrix “division” is not a particularly useful concept.) Iterative methods—such as solving equations of the form Kxi + 1 = Kxi + b – Axi with a simpler matrix K that’s ideally “close” to A—lead to the study of Krylov subspaces. Named for the Russian mathematician Nikolai Krylov, Krylov subspaces are spanned by powers of a matrix applied to an initial“remainder” vector r0 = b – Ax0. Lanczos found a nifty way to generate an orthogonal basis for such a subspace when the matrix is symmetric. Hestenes and Stiefel proposed an even niftier method, known as the conjugate gradient method, for systems that are both symmetric and positive definite. Over the last 50 years, numerous researchers have improved and extended these algorithms. The current suite includes techniques for non-symmetric systems, with acronyms like GMRES and Bi-CGSTAB. (GMRES and Bi-CGSTAB premiered in SIAM Journal on Scientific and Statistical Computing, in 1986 and 1992, respectively.)
4.矩阵计算的分解方法
1951: Alston Householder of Oak Ridge National Laboratory formalizes the decompositional approach to matrix computations. The ability to factor matrices into triangular, diagonal, orthogonal, and other special forms has turned
out to be extremely useful. The decompositional approach has enabled software developers to produce flexible and efficient matrix packages. It also facilitates the analysis of rounding errors, one of the big bugbears of numerical linear algebra. (In 1961, James Wilkinson of the National Physical Laboratory in London published a seminal paper in the Journal of the ACM, titled “ Error Analysis of Direct Methods of Matrix Inversion,” based on the LU decomposition of a matrix as a product of lower and upper triangular factors.)
5.优化的Fortan编译器
1957: John Backus leads a team at IBM in developing the Fortran optimizing compiler. The creation of Fortran may rank as the single most important event in the history of computer programming: Finally, scientists (and others) could tell the computer what they wanted it to do, without having to descend into the netherworld of machine code. Although modest by modern compiler standards—Fortran I consisted of a mere 23,500 assembly-language instructions—the early compiler was nonetheless capable of surprisingly sophisticated computations. As Backus himself recalls in a recent history of Fortran I, II, and III, published in 1998 in the IEEE Annals of the History of Computing, the compiler “produced code of such efficiency that its output would startle the programmers who studied it.”
6.计算矩阵特征值的QR算法
1959–61: J.G.F. Francis of Ferranti Ltd., London, finds a stable method for computing eigenvalues, known as the QR algorithm. Eigenvalues are arguably the most important numbers associated with matrices—and they can be the trickiest to compute. It’s relatively easy to transform a square matrix into a matrix that’s “ almost” upper triangular, meaning one with a single extra set of nonzero entries just below the main diagonal. But chipping away those final nonzeros, without launching an avalanche of error, is nontrivial. The QR algorithm is just the ticket. Based on the QR decomposition, which writes A as the product of an orthogonal matrix Q and an upper triangular matrix R, this approach iteratively changes Ai = QR into Ai + 1 = RQ, with a few bells and whistles for accelerating convergence to upper triangular form. By the mid-1960s, the QR algorithm had turned once-formidable eigenvalue problems into routine calculations.
7.快速排序算法
1962: Tony Hoare of Elliott Brothers, Ltd., London, presents Quicksort. Putting N things in numerical or alphabetical order is mind-numbingly mundane. The intellectual challenge lies in devising ways of doing so quickly. Hoare’s algorithm uses the age-old recursive strategy of divide and conquer to solve the problem: Pick one element as a “pivot, ” separate the rest into piles of “big” and “small” elements (as compared with the pivot), and then repeat this procedure on each pile. Although it’s possible to get stuck doing all N(N – 1)/2 comparisons (especially if you use as your pivot the first item on a list that’s already sorted!), Quicksort runs on average with O(N log N) efficiency. Its elegant simplicity has made Quicksort the pos-terchild of computational complexity.
8.快速傅立叶变换
1965: James Cooley of the IBM T.J. Watson Research Center and John Tukey of Princeton University and AT&T Bell Laboratories unveil the fast Fourier transform. Easily the most far-reaching algo-rithm in applied mathematics, the
FFT revolutionized signal processing. The underlying idea goes back to Gauss (who needed to calculate orbits of asteroids), but it was the Cooley–Tukey paper that made it clear how easily Fourier transforms can be computed. Like Quicksort, the FFT relies on a divide-and-conquer strategy to reduce an ostensibly O(N2) chore to an O(N log N) frolic. But unlike Quick- sort, the implementation is (at first sight) nonintuitive and less than straightforward. This in itself gave computer science an impetus to investigate the inherent complexity of computational problems and algorithms.
9.整数关系探测算法
1977: Helaman Ferguson and Rodney Forcade of Brigham Young University advance an integer relation detection algorithm. The problem is an old one: Given a bunch of real numbers, say x1, x2, . . . , xn, are there integers a1, a2, . . . , an (not all 0) for which a1x1 + a2x2 + . . . + anxn = 0? For n = 2, the venerable Euclidean algorithm does the job, computing terms in the continued-fraction expansion of x1/x2. If x1/x2 is rational, the expansion terminates and, with proper unraveling, gives the “smallest” integers a1 and a2. If the Euclidean algorithm doesn’t terminate—or if you simply get tired of computing it—then the unraveling procedure at least provides lower bounds on the size of the smallest integer relation. Ferguson and Forcade’s generalization, although much more difficult to implement (and to understand), is also more powerful. Their detection algorithm, for example, has been used to find the precise coefficients of the polynomials satisfied by the third and fourth bifurcation points, B3 = 3.544090 and B4 = 3.564407, of the logistic map. (The latter polynomial is of degree 120; its largest coefficient is 25730.) It has also proved useful in simplifying calculations with Feynman diagrams in quantum field theory.
10.快速多极算法
1987: Leslie Greengard and Vladimir Rokhlin of Yale University invent the fast multipole algorithm. This algorithm overcomes one of the biggest headaches of N-body simulations: the fact that accurate calculations of the motions of N particles interacting via gravitational or electrostatic forces (think stars in a galaxy, or atoms in a protein) would seem to require O(N2) computations—one for each pair of particles. The fast multipole algorithm gets by with O(N) computations. It does so by using multipole expansions (net charge or mass, dipole moment, quadrupole, and so forth) to approximate the effects of a distant group of particles on a local group. A hierarchical decomposition of space is used to define ever-larger groups as distances increase. One of the distinct advantages of the fast multipole algorithm is that it comes equipped with rigorous error estimates, a feature that many methods lack.
20世纪10大算法
1、蒙特卡罗算法。1946: John von Neumann, Stan Ulam, and Nick Metropolis
2、单纯形方法。1947: George Dantzig,学过运筹学的人都知道:)
3、Krylov 子空间迭代算法。1950: Magnus Hestenes, Eduard Stiefel, and Cornelius Lanczos。在联想实习的期间看过/Krylov subspace:span{S,A*S,A^2*S,...,A^(k-1)*S}.
4、矩阵分解算法。1951: Alston Householder。
5、Fotran 最优化编译器。1957: John Backus。不知道这个为什么也算作算法里面。Fotran在科学计算中的确是具有里程碑性质的。
6、QR算法。1959–61: J.G.F. Francis
7、快速排序算法。1962: Tony Hoare。看了关于计算机排序的研究还不是很早。
8、FFT算法。1965: James Cooley
9、整数关系确定算法(Integer Relation Detecting Algorithms)。1977: Helaman Ferguson and Rodney Forcade。一个曾让我辗转反测的算法。
10、快速多极算法(Fast Multipole Algorithms )。1987: Leslie Greengard and Vladimir Rokhlin。N体问题仿真的,不太清楚。
谈谈生活中的心理学规则
|
时间: 2008年10月24日 10:51 作者:古典 来源:新东方
|
|
|
给新东方教师教师培训的时候,我发现心理学的一些原理对于教师的培训与个人成长是很必要知道的,列举一些分享。
超限效应
美国著名幽默作家马克•吐温有一次在教堂听牧师演讲。最初,他觉得牧师讲得很好,使人感动,准备捐款。过了10分钟,牧师还没有讲完,他有些不耐烦了,决定只捐一些零钱。又过了10分钟,牧师还没有讲完,于是他决定,1分钱也不捐。到牧师终于结束了冗长的演讲,开始募捐时,马克•吐温由于气愤,不仅未捐钱,还从盘子里偷了2元钱。这种刺激过多、过强和作用时间过久而引起心理极不耐烦或反抗的心理现象,称之为“超限效应”。超限效应在家庭教育中时常发生。如:当孩子不用心而没考好时,父母会一次、两次、三次,甚至四次、五次重复对一件事作同样的批评,使孩子从内疚不安到不耐烦最后反感讨厌。被“逼急”了,就会出现“我偏要这样”的反抗心理和行为。因为孩子一旦受到批评,总需要一段时间才能恢复心理平衡,受到重复批评时,他心里会嘀咕:“怎么老这样对我?”孩子挨批评的心情就无法复归平静,反抗心理就高亢起来。可见,家长对孩子的批评不能超过限度,应对孩子“犯一次错,只批评一次”。如果非要再次批评,那也不应简单地重复,要换个角度,换种说法。这样,孩子才不会觉得同样的错误被“揪住不放”,厌烦心理、逆反心理也会随之减低。
点评:过犹不及的心理学解释:同时也告诉我们,讲课的时候千万不要拖堂……这很容易过学生的底线哦。
3对1规律
说服别人或提出令人为难的要求时,最好办法是由几个人同时给对方施加压力。那么为了引发对方的求同行为,至少需要几个人才能奏效呢?前面的实验结果表明,能够引发同步行为的人数至少为3~4名。当两个人统一口径诱使某人采取求同行为时,几乎没有人会做出错误选择。如果人数增加到3人,求同率就迅速上升。效果最好的是5个人中有4人意见一致。人数增至8名或15名,求同率也几乎保持不变。但是,这种劝说方法受环境的制约较大,在一对一的谈判中或对方人多时就很难发挥作用。当对方是一个人时,你可以事先请两个支持者参加谈判,并在谈判桌上以分别交换意见的方式诱使对方做出求同行为。在纸牌游戏中,经常能看到这种现象。纸牌游戏一般由4个人参加,在游戏过程中如果时机成熟,有人会建议提高赌金或导入新规则,同时也会有人提出异议,这时如果能拉拢其它两人,三个人合力对付一个人,那么剩下的那个人会因寡不敌众而改变自己的主张,被多数的力量说服。克莱乌杰比茨的手下败将拿破仑也曾说过:“胜利在于兵力充足。”由此看来,“以多胜少”的道理应该是在克莱乌杰比茨之前就有的一个规律。
点评:三人成虎的心理学解释。从教学培训来讲,举例子一定要举到3个以上,就开始有说服力了。告诉学员你要讲什么,给他们讲,然后告诉他们你讲了些什么……
贝勃规律
第一次刺激能缓解第二次的小刺激──“贝勃规律” 有一个关于“诱敌深入法”的有趣实验。人们对报纸售价涨了50元或汽车票由200元涨到250元会十分敏感,但如果房价涨了100甚至200万元,人们都不会觉得涨幅很大。人们一开始受到的刺激越强,对以后的刺激也就越迟钝。下面的例子说明了这种“贝勃规律”。一个人右手举着300克重的法码,这时在其左手上放305克的法码,他并不会觉得有多少差别,直到左手法码的重量加至306克时才会觉得有些重。如果右手举着600克,这时左手上的重量要达到612克才能感受到差异。即比前一种情况要多给一倍以上的刺激才会有所反应。所以要想辨别出刺激间的差异,刺激总量越大,其差额也必须越大。 “贝勃规律”经常应用于经营中的人事变动或机构改组等。一家公司要想赶走被视为眼中钉的人,应该先对与这些人无关的部门进行大规模的人事变动或裁员,使其它职员习惯于这种冲击。然后在第三或第四次的人事变动和裁员时再把矛头指向原定目标。很多人受到第一次冲击后,对后来的冲击已经麻木了。从一开始就提出令人难以拒绝的优厚条件,等谈判基本结束后再指出一些不好的细节并使对方接受的“诱敌深入法”基本上也是以“贝勃规律”为基础的。对方被一开始的优厚条件所诱惑,对后来才知道的不好的部分也就会较轻易地接受了。
点评:先提小要求,然后再提大要求。等到你的内容提高了,你的要求慢慢加大。这样所有人都不会感到有难度…… (编辑:姚阿珊)
|
关于追女孩子的技巧
好长一段没有上站了,今天心情很不错。其实一直以来,我都想把个人在感情方面的一些经验传授给大家,但是要系统地写出一篇心得来,实在是非常费劲的一件事情,所以一拖再拖。今天好不容易定下心来决定写一点东西,希望能令到各位看了本文的男同胞,有所感悟和启发。 ?
??
??
??
?????1、关于爱情。 ?
??
???曾经有个粗人对我说过一句堪称经典的俗话:“谈恋爱,就是一男一女凑在一起说胡话。” ?
???个人以为,这句话非常深刻。 ?
??
???因为如果没有两个人在一起的那些缠绵情话、海誓山盟,其实剩下的那些恋爱中需要两个人一起来完成的事情,照样是可以做,而且是可以做的很好的。你们照样可以约会、可以接吻、可以上床、可以结婚生孩子,但是这样一来,似乎就不是在谈恋爱了。 ?
??
???因此,之所以说到有“爱情”,并不是因为你们约会了、接吻了、上床了,亦或是结婚生孩子了,两个人之间的爱情的产生,就是因为有了你们在一起时所说的这些缠绵情话、海誓山盟。拿掉这些,恋爱就不再是恋爱;而只要保留这些,即使剩下的全部都没有,仍然可以称作是柏拉图式的精神恋爱。 ?
??
???遗憾的是,偏偏这些恋爱中最重要的内容,却往往是最最靠不住的。即使两个人最后真的走到了一起,恐怕当初头脑一热脱口而出的所有那些情话、胡话,能有十分之一会最终实现,就算相当地不错了。 ?
??
???这是为什么一段失败的感情总是会让人受伤的原因,说的胡话多也许不要紧,但要是信的多了,最后痛苦的必然就是你自己,不管你们分不分开。 ?
??
???爱情最为矛盾的地方就在于:不说胡话的话,就不能称之为爱情;可是一旦说的多了,难免有的人就会把有的话信以为真,到最后害人害己。如何把握好这个尺度,既能享受到恋情如火时口无遮拦的快感,又能在感情回归平淡甚至破裂时免受伤害,需要不断的人生历练。 ?
??
??
??
?????2、关于女人。 ?
??
???男人们总是说自己不懂女人,呵呵,这个其实并没有关系。因为女人们根本也不懂她们自己。 ?
??
???很多年轻的男人都会有这样的一个困惑:为什么女人说的话会这么容易就不算数了呢?是她们天生爱撒谎,又或是女人的天性就是善变的? ?
??
???其实都不是。 ?
??
???女人说话不算话,是由两个她们与生俱来的特质所决定的: ?
???第一,女人的智商天生就没有男人高,而且她们尤其不擅长象男人那样理性地去思考问题,说白了,就是在大多时候,她们自己也不知道自己在想什么; ?
???第二,女人非常感性,感性到脑子里正在想这个,但是脱口而出的却会是另外的一句话,比如:“你真讨厌!”。傻子都知道说这句话的女孩这个时候脑子里一定不是在想我很讨厌你,但是具体在想什么呢,则不一定。所以简单地说,就是女人很多时候自己都不知道自己在说什么。 ?
??
???如果你是一个足够聪明的男人,千万不要相信女人所说的话。道理很简单,因为大部分的时候,她们自己也不知道自己在想什么,在说什么。试图以男人的逻辑,去解开女人所说的话背后的真实含义,结果只能有两个:你彻底地疯掉;或者你成功证明了自己的极度愚蠢。 ?
??
??
?????3、关于男人。 ?
??
???下面是我给男同胞们的忠告: ?
??
???如果你觉得自己爱上了一个女人。千万不要去相信那些女人们所说的鬼话:“要真喜欢的话,就拿出行动来啊;就勇敢地表达出来啊;就象个男人一样大胆地展开追求啊…………” ?
??
???如果你相信这些话,并且把它付诸行动。很不幸,你的智商肯定在80以下。 ?
??
???女人对待追求者的态度,就象女孩对待洋娃娃的态度一样,那就是越多越好。因为追求者的数量和追求方式的不断推陈出新,可以极好地满足女人与生俱来的虚荣心和炫耀心理。 ?
??
???举个例子,王子和公主的童话每个小孩都听说过,但是几乎没有一个小男孩会在听完这个故事后,成天傻兮兮地幻想自己是一个王子。而几乎每个小女孩在听完故事后,都会幻想自己成为一个公主,有一天王子会骑着白马来娶她,这就是典型的虚荣心和炫耀心理在作怪。 ?
??
???现在说回到洋娃娃的问题上来,你要想让一个女人不在内心里面企盼有更多的追求者,就如同要劝说一个小女孩,永远也不要妄想把百货公司的洋娃娃全部买回家一样地费力和徒劳。对于一个男人而言,如果你真的喜欢上了一个女人,最优的策略就是,千万不要成为她众多洋娃娃中的一个,因为如果是,她永远也不可能爱上你。 ?
??
???如何征服一个女人的心??? ?
??
???很简单,让她明白,你和所有其它追求她的男人都不同。当然要做到这一点,你首先需要一点自知之明。也就是,如果你在她的追求者中没有任何突出之处的话,你永远也不可能取得成功。也许,经过你漫长的等待和付出,当她行将年老色衰、受尽各种比你优秀的男人的伤害之后,她会选择你与她共渡一生,但是我说过了,你永远也不可能得到她的心。 ?
??
???所以我说,世界上本来就不应该存在追女孩这种事情,之所以变成现在这个样子,还是因为很多男人在雄性激素的作用下,丧失了起码的理智。身边有着众多的优秀男人追求,要远比听到一两句诸如“你真漂亮”之类的赞美她们的废话,更能满足女人们的炫耀心理。但这仅仅是在满足女人的虚荣心而已,她不会因为你追她而爱上你。 ?
??
???记住,如果一个女人会爱上你的话,只需要1到2分钟的时间就足够了,当然,这两分钟可能不是出现在你们第一次见面的时候,但是绝不会出现在你们认识一周或者见面7次以后。如果你在这个期限里不能够打动她,征服她,那你这辈子也不可能真正地征服她。 ?
??
???如何征服一个美女呢??? ?
??
???还是很简单,首先就是你要有自知之明。不要听信女人们说的那些我没有什么硬性的择偶标准之类的屁话,在她们不喜欢的男人面前,她们是永远也不会说真心话的。 ?
??
???绝大部分的女孩对于男人的身高、长相、学识、特长、工作、家庭都是会有硬性的要求或曰最低的门槛的,尤其是前三样,如果你有一样达不到还要硬追的话,最后的结果就一定是你自取其辱。 ?
??
???征服美女其实也并不困难,如果你足够优秀的话。但是也有不少很优秀的男士,在这方面就遇到了问题。这些优秀男士之所以会遭遇挫折,主要还是因为没有明白我前面所讲的那个道理,就是征服一个女人一定要在7天以内。 ?
??
???如果你能在她的面前表现出很短时间内把她拿下的自信心的话(注意,不是用嘴巴说的),要知道每个女人在内心里都是会很渴望被男人征服的,美女们因为身边优秀的男士太多了可能会挑花了眼,而这个时候你以这样强烈的自信出现在她的面前,她肯定会认为你才是她的真命天子。 ?
??
???而且,自信的男人本身就很吸引女人。 ?
??
???如果你按照我说的去做了,还是虏获不了美女的芳心,那说明你对自己了解的还不够。
???去换个容易一点的吧。 ?
??
???当然,要追到美女很容易,要保住就会很难,原因就在她身边的那些曾经输给过你的象苍蝇一样围着她乱转的“优秀男士”们,一旦你们的感情出现裂痕,苍蝇们就会很快地见缝插针。不过没有关系,我说过了,即使她以后嫁给了别的人,她一生中在心底里最爱的那个人始终还会是你,那个曾在瞬间虏获她芳心的男人。 ?
??
??
??
?????4、失恋和谎言。 ?
??
???当恋情结束时,所有的甜言密语,都顷刻之间变成了谎言,这会是令人痛苦的事情。不过有两种男人,可以不用体验这种痛苦,那就是浪子和王八。 ?
??
???我前面已经说过了,女人说话不算话、善变,是因为她们与生俱来的特质使然。可是既然上帝已经把女人给创造成了这个样子,我们又离不开女人,有一个解决的办法:就是始终保持清醒的头脑,看清楚在你面前说话的是一个女人,不必相信她们说的每一句话,把分析她们内心活动的精力节省下来,去做你自己喜欢做的事情。 ?
??
???当有一天她移情别恋了,不必表现的比她更加惊讶,顺便把你的新女朋友介绍给她,她一定会爱你胜过爱她现在的那个男人。 ?
??
???当然了,如果你不具备做一个浪子的条件,那么做只王八其实也是个不错的选择。如果说浪子们是以不投入自己的感情来避免被女人伤害的话,王八们则是以死猪不怕开水烫的架势,来迎接未来可能会遭受的各种变化。 ?
??
???如果你是这样的一个男人:当你的女朋友编尽各种前后矛盾的谎言(女人的说谎能力都很差因为她们天生逻辑能力就差),在一周不和你在一起的那5天里面,分别和5个不同的男人约了会、上了床。你在知道真相后,仍然不觉得难过,反而觉得很高兴:她和我在一起的时间是最多的了,她最爱的那个人是我耶。那么,恭喜你,你是一只不会受到失恋和谎言伤害的好王八。 ?
??
???至于具体要成为什么样的男人,各位可以在看了我的文章后,自己决定。??
|
数学的无限与有限或无穷与有穷
无限只可以是认识的对象,却不可以是计算的对象。如对无限进行计算,那么就是对于无限这个概念进行破坏,而失去无限的本来意义。也应该定义有限的范围,即进行归一化处理,因为在自然真实中总是存在有限范围,人们的认识可以达到无限,可是实际的接触范围总是有限的。即在自然真实中只存在有限自然整数集合的连续统,不存在无限自然整数集合的连续统。
从严格的概念定义上来说,无限是不属于集合的。众所周知,凡是集合则属于封闭有限范围,情况无限属于无限开放情况,封闭性无穷属于人为性规定,开放性无限属于真实自然。从语义上来讲,无限集合违背了语言规则规定,又不符合逻辑演绎规则,集合是属于有极限意义,而不是具有无极限意义。我们所谓的无穷并不是真正意义上的无穷,而是具有人为任意性的无穷。是代数逻辑符号掩盖了算术上的有限性界限,使有限与无限混合起来。人的认识已知的能力是可以能够达到无限的,但是所能够接触具体的事物的范围却是有限的。知无止境,为有止境。
无限小量并不是等于零,而是永远接近零,零就是没有,准确的说是不存在无限小量,而是有限小量,与无限小量是两回事。如果在有限时可以存在最,无限时不存在最,这是首先应该明确的。虽然都是无限,可内容上却存在很大区别,如无限大是真正意义上,而无限小却是有极限的,即为零,有些所谓的无限大不是真正意义上的,而是有极限内的无限大。真无限是为无限大,假无限是永远接近而又永远达不到的极限的无限小。最小是无限小,最大却不是无限大,因为物体不存在无限大,所以粒子也不存在无限小,只是有限小,而这个有限小,目前还无法准确定义。终极没有最小只有更小,否则就不会存在无限这个概念定义了。什么叫做最?根本就没有一个限制性的约束,完全是人为任意性的规定。
古人曾经说过:至大无外,至小无内,是指空间范围。一日之棰,日取其半,万世不竭,在认识上是可行的,可是在实际中却是行不通的,因为永远肯定做不到。不存在最大却存在空间延展无限大,存在最小却不存在无限小,因为必然会存在大于零或接近零,却永远不等于零。无穷小量是人们原则灵活性的机智,不是精确的,是近似的,却达到了类精确的效果。微积分充其量也不过是个具有近似值的经验公式。自然存在有些本来就不是精确的,我们也没有办法,也只能而已。用半衰期计算,不管是什么物质总是存在岂不荒谬?无限,无论是在人的想象或现实中都是存在着的,证实或证明当达到时还又没有达到时的以此类推。
无限大可以是自然真实存在着的,可是无限小在真实自然中却是不存在的,完全是人为理想化的结果,至于小到什么程度只能由自然事实来决定,可以认识但却无法操作,这是人们的能力所不能及的地方,但对人类活动毫无影响。无究与有限概念的产生首先是选择类不同结果,首先在逻辑上就不一致,直接挑战逻辑使逻辑失效,严重违反逻辑规则,也更是逻辑所无法解决的。就是数学恒等式中的那个等号也是不精确相等的,也只不过是个近似值而已,因为自然界不存在完全精确大小或完全一样的两个1。
整体大于部分的本义应该是指整体是无限的,部分是有限的。有限的与有限的相加也永远还是有限的,但如果是无限的相加那么就也是无限的了。大数进行无限的相加并不比小数进行无限的相加大,因为一旦纳入被无限的相加时那么即完全相等,其不同是大数先接近无限的范围,而小数则后接近无限的范围。即使在有限的前提下也存在着无限的可分性,但这个无限是建立产生在有限的前提上的,目前我们人类的认识就是属于这种认识无限,而是在有限性前提下的。别说是超出太阳系,就是在太阳系本身体系内还没有认识清楚。无限只能在人的想象或理想中存在,在现实存在中存在是我们无法验证和能够达到的,因为我们的生命或活动能力是有限的,但是并不妨碍我们对无限的思考与认识。理想或认识可以达到无限,而实际性操作却是有限,无论不管什么先进技术都是存在有限的极限。
连续统假设
连续统假设:在可数集基数和实数集基数之间再没有别的基数。
所有的数或表示几何的数都可以在连续统序列中存在,用整体观念来看数学体系则是相容的。虽然集合与集合之间存在一定一致的对应或序列关系,都是属于连续统假设,然而其中的子集合基数却不相同,在不同的集合中是不相容的,是各个不同部分领域具有各自不同的特征特点罢了。混淆了子集合与自然整数集合之间的基数不同的区别,导致有限与无限之间没有明显的界限,二者的任意某一阶段或定域是并不相等,成了一个令人模糊的连续统,连续统假设已经失去真实意义。(超穷数理论只是康托尔本人的误会。)
连续统假设建立在比较集合元素个数的基础上。但是要比较集合元素个数,首先要明确集合元素的意义和集合之间的关系是否相容。同样的连续统在时间、空间、几何、数量的表示关系上是不一样的。例如{长度:1*1,2*2…}和{面积:1*1,2*2…}表示的实际意义是不一样的,虽然它们在数字上的结果相同。同样,对于复杂的问题之间,若存在着某种不可比较性,数量上的一一对应关系也就失去了意义。
如果两个有限定性实际意义的集合,它们之间的意义相同,可以相容,那么我们可以构造建立对应法则,讨论基数问题。如果两个有限定性条件实际意义的集合,它们各有各的意义,其关系不能相容,那么我们不能建立数量上的一一对应关系,讨论基数问题。
数学一方面要考虑形式上的构造,另一方面也要考虑实际意义,因为数学最终还要应用于自然。那么对于连续统假设,我们看到它提出了研究集合基数关系的问题,但是对于是否两个集合之间能相互比较基数,以及集合的实际意义问题没有给出解释。
那么连续统假设需要另外补充条件,即集合的实际意义,以及集合之间的关系,根据实际情况,我们可以判断其基数的大小,而对于没有现实意义的集合,这样做没有意义。
数学连续统假设的独立性存在任意性,有限与无限之间应该设定一个界限,绝不可以任意无原则的等同。(哥德尔曾经指出:)集合永远不能属于自身,全集合是不存在的,但概念也许适用于自身,全概念是存在的。哥德尔认为:集合是外延,概念则是内涵。类只有一个主题,但大类有交叉迭代复合性,许多分类的小主题。连续性或与整体性的关系,被任意割裂成许多零碎的关系。希尔伯特关于建立不同公理系统的相容性问题是最基本的想法是不存在的,特征与具体事实是对立着而存在的,所谓的公理只是特征,特征与特征根本就不相容。我们应该充分发现特征而不应该在规定特征。
连续统任意性的将自然语言中的概念定义给破坏了,在人们的思想中造成严重的影响,无穷再也不具有无穷的准确意义了。n到底属于那个数,是+1以前还是以后的呢?还要看怎么数,若以大数为数一下子就到头了,是一个封闭的大1,因为只有一个无限。无限可分与无限整合的关系是不一样,是以整体前提,还是以部分为前提?
一个数可以用作被计算的数,还可以被用作计算后的数,整个数连续序列中的其中任意的一个也都是可以的,我们可以根据应用的实际情况进行无穷性的选择方法,各种数学结构都被包含在连续的数列之中。
超越数是改变了实数概念的结果,这里的自然数列是人为性规定划定的一个数列。把实数轴与自然数轴作了一次混合,构造了一个新数列,仍叫做自然数列。否则自然数列后怎么可能有大于无穷大的第一个数W。
无穷套根在自然中是不存在的,因为平直空间最多是三维。无穷连分数或无穷小数也是只可认识无法操作的,极限是人们所能满足的需要为止。
集合连续统是关于以什么基数为标准单位关系。中国古人对于无限的认识是非常明确的,用不着反复讨论,否则无论基数多大都是不可数的。就是小1,如果具有可分性,那么也就微分,那样也可以无限的分下去。用老话讲叫不着边不靠谱,过分讨论无限性是无意义的,是以满足实用为目的的。
微积分
总之微积分的有效作用是类似最小的近似量,然后再求总的近似量,永远也不会有精确量,来达到实际应用计算的目的。知道某些初始,知道结果,然后通过计算过程来达到结果。
微积分的实质就是相似的比率关系。函数的目的是求不变量,然后再用不变量来代入,由于变量而引起总量的变化。函数的目的无非是想要建立起一种对应关系,这种对应关系也可以称为比例关系或线性关系。将一个数看作是由若干函数组成,是由若干因素的关系所组成的现代微积分关系。函数所定义的恰恰是总数其中的常量系数的不变量,也可以当作类比求1的问题处理,即可以将100看作是由100个1所组成的。物质最小的不变量就是基本粒子所具有的虚设的量,如普朗克常量,类似微积分的求最小的近似量。微积分将分立的差异,用数学手段把它们变成具有连续性的一个过程。
本来有些图形属于不可展开体,所以永远也没有精确的展开解,只有求近似解,如球面等双曲线,圆周率的精确度是永远没有尽头的。微积分在有些应用上具有不完备的任意性,在有些地方适用,有些地方不适用。由微积分的近似性可以看出现代数学并不是一门精确准确确定性的学科,自我标榜严密清晰精确等,实则存在许多方面的疏漏,本身是不完善的。微积分有很多不能自圆其说的地方,后来人们为了补充完善,被弄出了实变函数。
分析数学的偏微分方程并没有对于运动的原因给予解释,而只是相似近似地描述了运动的状态和类比相似几何图形的关系,那个等号应该是约等于号,无论怎么近似但都不是精确的,并且永远不会有精确解,而只能如此永远是近似解。
非线性偏微分方程是否不可解,有多少解?关键是它的未知的是太多,无法确定,只是揭示了关系。本来就应该用物质的观念去对待湍流现象就会简单多了,就不会混乱了,然后再用数学,否则为什么会是非线性呢?为什么不稳定。现在数学界流行非线性,混沌说明数学遭遇存在挑战。不论怎么说用非线性偏微分方程来描述宇宙引力状态是不准确的,因为非线性方程各项中的未知量的具有物理意义的原因是不清楚的。
偏微分方程的求解还存在一定困难,那么它表示的物理意义不得而知?惯性系的非线性为什么不遵守惯性系自身的限定?混沌模糊不清的非线性,存在非常真切不明的原因。引力场非线性偏微分方程的解要满足是初始或边界条件之后的唯一性,在数学上还没有得到证明,理论上无法实现而实验上更无法实现。
变分法的最小作用原理虽然接近事实,但还是没有或不能将自然作用关系揭示出来,还是在人为作用下的惯性运动前提基础上来对待问题。引力场方程是如何解释两极处问题的?无法考虑,因为不遵守方程规则。
非线性方程
非线性因为是代数方程,高次方程或多元未知数它们之间必然存在着相互制约的条件联系关系。即如果一个未知数一旦确定,那么其它也与之对应,完全可以根据实际情况或需要而进行试商,存在有限解。如果是算术式,则不会有这个麻烦了,都是代数惹的祸,没有具体的数字怎么计算。各种求解四次以上的高次方程,如果是算术则可解,即化乘法为加法,然后再求平均数;可以采用两头试商的方法,即通过试商的大小可选择再试的方法。实际上并没有太大的实用意义,并不是不可行,也还可以通过列表方便可查。
这样的代数方程是没有实际计算意义的,即没有计算功能,只有表示或揭示关系的功能。如果按照现在的非线性处理只能得到近似解,即按照微积分或偏微分的函数法求最小子集,将一个本来具有精确解的算术式强制性的整成一个具有近似性的方程关系,改变确定性为不确定性。与其说是具有非线性还不如说是具有任意性。这种方法是很灵活,即是一个没有办法的办法,可是现在却被当作对物理等现象无法解释的有效描述,把一些不理解的因素变化归结为非线性。
有些事物出现因果不相同的情况,那一定是又增加了新的原因因素我们还不知道,如孤波是受到冲击运动的水又与在空气的作用下形成的。而不是什么非线性本质,或什么对称性破缺,其实也并不是什么复杂,所谓的复杂只是有些情况还不清楚而已。如什么不确定性、混沌、蝴蝶效应、吸引子、分叉、分形、随机涨落、粗粒化细粒化等。
为什么非线性成为现代数学的思潮,因为为性理想化规定规则在真实自然中只是某些特殊情况。如水面、笔直的植物主干、各种球体、蜂窝、雪花、某些矿物结晶体等线面规则体,在真实自然中不规则线面体才是普遍存在着的,以试图满足所有方面的需要。
几何图形
概念翻译不准确问题,几何本来就是具有多少的意思,非要加上图形的意思,拓扑等于变形,这样更加直观说明问题和更符合简单性原则,这些命名应该不应该修正。
欧几里得《原本》几何的原始定义存在问题,如果非欧几何是对欧几里得几何的否定,那么非欧几何所面临的将是同样的命运。三维绝对平直空间并没有错,它是约定最简单的说明问题的,而是怎么用的问题,黎曼几何也同样面临适用范围问题。
黎曼几何是空间立体几何,欧几里得几何是平面几何,是分属于两个不同的概念范畴的,是不能互换与等同的,作为数学是可以的,但是作为物理却是不可以的。数学只能知道几何图形,但是为什么形成几何图形的物理过程和原因却不清楚。物体球形结构说明物体是处于在周围均衡相等的压迫作用之中而形成的。自然几何是在自然力的作用下的一种结果,作为技术反推是有效的,作为认识,无论如何我们也不能把结果当作原因来对待。图形特征与人为规定应该区别,某种图形具有某种特征是事物自身所具有的,与我们的人为性规定完全是两回事。
滥用维度数的概念其结果必然导致错误认识,空间概念只能为三维,这是约定俗成,难道不去证明一下就不可以了吗?三维以上的维数是有悖于常识的。动态图像并非不能用图像来描述,如动画的图像。四维准确地说是什么样的图像?不能用图像描述的图像有什么作用?算不算作图像?维度是不是应该统一下认识?多维空间是有限的空间,绝对空间却是无限广延的。
不应该混淆三维和投影的关系,它们是不一样的,三维是按绝对比例,投影是按相对实际投影比例,前者接近绝对空间,后接近自然相对空间。活动的标架,可以将各种不同的多维空间嵌入到三维平直空间,否则是无法嵌入的。如当一个小球嵌入大球的某一位置时我们不知道小球还能否成为球状,因为在大球不同位置的空间里的曲率不同的,那么势必会对小球曲率形成影响。在大球中因为曲率关系直线变成曲线,那么说小球的直径也可以弯曲了?如果在某一方向小球的直径弯曲,那么这个小球还是标准的球吗?违背球的定义,任何位置的直径都相等。三维是可兼容,多维是无法相容或兼容的,如兼容其真实性的形体会被破坏。有人说拓扑学家像蚂蚁一样趴在圆周上,看到的只是局部结构,却没有认识到整个圆周被嵌入到三维空间中。黎曼空间是能被三维立体空间所包容,拓扑的整体背景是三维的。
拓扑规则是有限性其中的一种情况或几种情况,而在真实世界中则是具有很多种情况。拓扑为几何代数化。拓扑犹如能够变形的面团,具有相当大的灵活性与任意性,以满足各种需要。用拓扑数学方法也可以用一根线把所有不同形态的物质按开启化顺序或相互作用关系,将它们一一地穿起来而连成一个完整无限循环的整体,拓扑就是关联。在这方面宇宙是有限的,可是在别的方面也还是存在无限的。
几体问题的解最终不是数学问题而是机理问题,机理问题解决其数学问题是也有解了。数学只是对某些现象的形式做了描述,而不是对形成机理进行描述内容原因解释。大自然中物体有它自身构成数学几何的原因,这是数学几何自身无法解释清楚的,它可以量化自然,却无法解释产生自身的原因。
衡量代数几何化或几何代数化的关键原则是方便简单性,而且能直观容易说明或解决应用问题。例如把运动几何化的某些微积分,但也容易造成误会,把不是这么回事硬解释成了这么回事。几何的物理基础是物质存在,固态刚体流体空间也是,不要忘记这才是它存在的前提条件,即它不是完全抽象的脱离实际的与现实无关;数学也是如此,它有它的实在意义,不是毫无关系。几何图形的函数关系是本身固有的关系,然后将运动的轨迹流形也类比作几何图形,或也用函数关系来解决却是不合适的。竟然将时间也空间化或几何化成为了流形。常微分或偏微分方程彻底将物理学几何化了,大家不去追求物理运动原因或变化原因内容,而是去关心运动或变化的数学几何形式方面去了。难道几何空间就不可以描述物理空间的内容了吗?是数学几何的思想影响了我们的观念,由公设公理推出定理定律。任何极端孤立的几何是无任何内容意义的,在现实中也是不存在的,只在数学领域存在。
微积分或变分法或泛函分析将某些不规则形线段和图形或空间被看作为点和线的任意性的连续性集合或函数空间。由于抽象空间或泛函分析的兴起,更增加了把点集作为空间来进行研究,进而在泛函分析中起作用的性质又被归结为拓扑性质。主要因为点集序列的极限居重要位置,完全脱离了物理作用的空间成为纯数学的几何空间。即泛函分析的算子就是从一个空间到另一个空间的变换。我们不应该以没有物理内容的人为性数学几何空间中的同胚或拓扑变换来取代真实自然具有物质内容变化的空间。
如果有些人为性的规定恰好近似接近某些自然现象,那只能是一种偶然巧合。例如数学张量分析和微分几何不是依据自然现象去进行认识解释,而是利用数学建模的方法而对自然进行任意性处理:什么任意维任意阶任意张量任意分量等解释。Ricci在爱因斯坦之前有关张量分析就早已存在应用这一物理目的了。如果恰好近似接近或满足了某些自然现象就是正确的,如果不近似接近还可以再任意性的加上各种规定,直到满意为止,但是这个坐标系与另外坐标系并不是完全相等,如地球月亮太阳或各种星体之间。
理论数学是人类思维游戏活动的陷阱。如果作为游戏活动,对于启发智力是具有极大的帮助,但也难免具有一些负面影响;如果作为混饭吃的职业也是可以的,但也容易误人子弟;如果作为事业,那将是对人们的极大误导。现在仍然有大批的数学家们在津津乐道的从事这种游戏活动,岂不知宝贵的生命时间被残酷的牺牲。
本人酷爱数学,是这种热情使我走上数学道路。当我一步步继续深入时,有时却感觉很恐怖,今日说出来以供大家参考。本人的数学学得并不是太好,至于对错只能由个人审视定夺,与本人毫无关系。
哈佛图书馆自习室墙上的训言(快考试了,大家加油)
1.此刻打盹,你将做梦;而此刻学习,你将圆梦。
2.我荒废的今日,正是昨日殒身之人祈求的明日。
3.觉得为时已晚的时候,恰恰是最早的时候。
4.勿将今日之事拖到明日。
5.学习时的苦痛是暂时的,未学到的痛苦是终生的。
马斯洛需求层次理论
http://baike.baidu.com/view/690053.htm 有详细介绍
爱因斯坦的建议
2008年07月26日 星期六 21:08
阿尔伯特•爱因斯坦是20世纪最伟大的物理学家。他提出了很多的普遍定理和方程式,使他一直超越其他科学家。但是,人们也因为另一件事而记住他:一种令人 们都称他为天才的才能:他所说过的话。爱因斯坦教授是一位哲学家,他清楚懂得什么是成功法则,他能像解释他的方程式那般解释这些法则。这里有10句话是从 他以前所说过的无数极精彩的话语中提取出来的;这是十条你能用在平时生活之中的宝贵建议。
1. A person who never made a mistake never tried anything new. 不曾犯错的人从来不曾尝试新事物
Most people don’t try new things because of their fear of failure. Failing is not something to be afraid of. It is often the losers who learn more about winning than the winners. Our mistakes always give us opportunities to learn and grow.
大多数人因为害怕失败而不会去尝试新的事物。失败并不可怕,因为败者往往会比胜者更能认识胜利所蕴含的意味。而错误总是会给予我们机会去学习和成长。
2. Education is what remains after one has forgotten what one has learned in school.教育是一个人在学校学到的唯一不被遗忘的东西
30 years from now, you won’t possibly remember what chapters you had in your science book; you’d only remember what you learn on your way. Life lessons stay with you forever. Real education starts from within.
30年之后,你将不会记得曾经在教科书中学过哪些章节;你只会记得在过程中你学到什么。生活所带给你的经验和教训将陪伴你终生。真正的教育从自身内部开始。
3. I am enough of an artist to draw freely upon my imagination. Imagination is more important than knowledge. Knowledge is limited. Imagination encircles the world.我已经受够了作为一个能自由地控制想象力的大师。想像力比知识更重要。因为知识是有限的,而想象力却能畅游整个世界
When you reflect on how far we humans have come from the prehistoric caves to mind-blowing technological advancements, you would feel the power of imagination. What we have now was built from the imagination of our forefathers. What we will have in future will be built from our imagination.
当你思考我们人类发展,从史前的洞穴生活到现在令人惊叹的科学技术的突飞猛进,你会感到想象力的威力。我们现在所拥有的一切都来源于祖辈的想象力;而我们的想象力又将构筑世界的未来。
4. The secret to creativity is knowing how to hide your sources.创意的奥秘是知道如何隐藏你的创意来源
Creativity and uniqueness often depends on how well you hide your sources. You can get inspired and influenced by other great people; but when you are on stage with the whole world watching, you must become a unique, individual force that learnt different values from different people.
创意和独特性往往取决于如何隐藏你的创意来源。你可以从其他伟人身上受到启发和影响;但当你站在全世界都注视你的舞台上的时候,你必须成为一个独特的、个人的力量去从不同的人身上学习不同的价值观。
5. The value of a man should be seen in what he gives and not in what he is able to receive. Try not to become a man of success, but rather try to become a man of value.一个人的价值,在于他贡献什么,而不是他能取得什么。不要渴望成为一个成功的人,而是应该努力做一个有价值的人 。
If you think of all the top people in the world, they would have added something of value to the world. You must give in order to take. When your purpose is contributing or adding value to the world, you will be elevated to a higher level of living.
当你回顾全球最顶尖人物的一生之后,你会发现他们都曾经为世界创造过某些价值。要得到回报,你得先付出。当你的目标是为世界做贡献或者创造价值时,无论你的精神生活或物质生活都将会被提升到一个更高的层次。
6. There are two ways to live: you can live as if nothing is a miracle; you can live as if everything is a miracle.天下只有两种生活方式:人生不存在奇迹;人生处处孕育着奇迹
When nothing is a miracle, you gain the power of doing anything you want and you have no limits. And when everything is a miracle, you stop by to appreciate even the smallest of beautiful things in the world. Thinking both ways will give you a productive and happy life.
当你认为人生不存在奇迹的时候,你会得到力量去做任何你想要做的事情,而且你会超越极限。而当你认为人生处处孕育着奇迹的时候,你甚至会停下来为一件小小的美好事物而驻足欣赏。这两种思考方式都能让你拥有充实而幸福的生活。
7. When I examine myself and my methods of thought, I come to the conclusion that the gift of fantasy has meant more to me than any talent for abstract, positive thinking.在我审视我自己和我的思考方式时,我的结论是:在吸收有益的知识方面,奇思玄想的天赋对我而言,比我的才干更重要。
Dreaming about all the great things that you can achieve is the key to a life filled with positivity. Let your imagination run amuck and create the world that you would wish to be in.
幻想着所有你可以完成的伟大事业能够使你的生活充满积极性。让你的想象力任意驰骋,尽情创造你想要的一切吧。
8. In order to be an immaculate member of a flock of sheep, one must above all be a sheep oneself.要成为羊群中优秀的一员,你就必须先成为一只羊。
If you want to become a very successful entrepreneur, you must start a business right away. Wishing to become one, but fearing the consequences will not help. The same applies to everything – in order to win a game, one must above all play the game.
如果你想成为一名成功的企业家,你就必须现在立刻创立你的公司。只是希望成为企业家,但又害怕面对失败后果,这样一点用处也没有。同理,很多事情也一样——要赢比赛,首先得参加比赛。
9. You have to learn the rules of the game. And then you have to play better than anyone else.你必须去学习游戏规则。然后,你还要比别人玩得更好
Learn the rules of your game and start playing it best. Keep competing like your life depended on it. And after a while you will have no one else but you to compete against. At that point, better your best.
了解游戏规则,然后开始游戏并做到最好。一直保持竞争的状态就好像押下你的生命作为赌注那样。不久后,你的对手可能只剩下你自己。到那时,超越自己!
10. The important thing is not to stop questioning. Curiosity has its own reason for existing.最重要的是不要停止问问题。好奇心的存在,自有它的道理
Intelligent people ask. Keep questioning yourself and others to find solutions. This will help gain knowledge and analyze your growth in all walks of life.智者总是好问。不停地对自己和他人发问以寻求解决方法。这将会帮助你在人生进程中获得更多知识与智慧,并全方位地分析自己的成长。
|
假定矩形是用一对点表达的(minx,miny)(maxx, maxy)
那么两个矩形rect1{(minx1,miny1)(maxx1, maxy1)}, rect2{(minx2,miny2)(maxx2, maxy2)}
相交的结果一定是个矩形,构成这个相交矩形rect{(minx,miny)(maxx, maxy)}的点对坐标是:
minx = max(minx1, minx2)
miny = max(miny1, miny2)
maxx = min(maxx1, maxx2)
maxy = min(maxy1, maxy2)
如果两个矩形不相交,那么计算得到的点对坐标必然满足
minx > maxx
或者
miny > maxy
判定是否相交,以及相交矩形是什么都可以用这个方法一体计算完成
从这个算法的结果上,我们还可以简单的生成出下面的两个内容:
1 相交矩形: (minx, miny) (maxx, maxy)
2 面积: 面积的计算可以和判定一起进行
if ( minx>maxx) return 0;
if (miny>maxy) return 0;
return (maxx-minx)*(maxy-miny)
qq公司的08年招聘面试题,下面的链接中有人给出了一些答案,可以看看
http://topic.csdn.net/u/20081101/13/4854a6b9-8adb-4813-bcba-68708dc539ef.html
1000瓶药水,其中至多有1瓶剧毒,现在给你10只小狗在24小时内通过小狗试药的方式找出哪瓶药有毒或者全部无毒(小狗服完药20小时后才能判断是否中毒)
找规律填字母
Z H A
M E ()
A. K
B. Y
C. B
D. W
网站上的媒体资源(图片、音频、视频等)很容易被盗链,相对比较安全的防范措施是:()
A 检查refer
B 为资源文件添加数字签名
C 添加基于session的判断
D 以上说法都正确
使用视频软件进行聊天时,视频数据几乎都通过udp协议传输。关于udp协议,下列说法错误的是______
A 数据通过udp协议传输存在丢包的可能,安全性不如tcp协议
B udp协议传输执行速度比tcp快
C udp协议的数据传输是无序的,tcp协议的数据传输是有序的。
D 视频、聊天、邮件等数据的传输都可以使用udp协议。
局域网甲内的主机A开启了p2p下载工具(如bt,emule等),他如何同局域网乙中的主机B建立连接______
A 通过主机B的内网ip建立连接
B 通过主机B的物理地址建立连接
C 通过NAT穿越技术建立连接
D 无法建立连接
Windows将遵循下面的那种搜索来定位DLL()
1 进程的当前工作目录
2 包含EXE文件的目录
3 列在Path环境变量中的一系列目录
4 Windows系统目录
5 Windows目录
A 12453 B 12543 C 21453 D 21345
设有一个递归算法如下
int x(int n)
{
if(n <=3) return 1;
else return x(n-2)+x(n-4)+1;
}
试问计算x(x(8))时需要计算______次x函数。
至少列举5种windows下进程间通讯的方式
不用中间变量,实现strlen函数。(strlen为C语言中求给字符串长度库函数)
int strlen(const char *str)
读后感:醍醐灌顶!
转帖自 反对异化——亲亲小猫咪 的博客
http://zhenmafudan.ycool.com/post.2878014.html
重贴一组流传大江南北的旧文----科研随想录
Zhenmafudan @ 2008-05-31 23:37
这是我在国内读硕士时候写的一组旧文,2001年发表于复旦bbs化学系版。出国后发现这组文章被大江南北100多个网站广泛转载,不幸的是,大多数转载者都没有注明出处。现在重新在我的博客上贴出来。用现在的眼光看,有些观点还是很有参考价值的,有些观点已经随着时间的变化改变了。我现在在这里(用[...]的形式)加适当的评注。用红笔显示的观点,是现在的我觉得还是有用的。
(注:因为转帖过来的,没有把原作者标注红色的内容原搬过来。下面红色的文字是我自己觉得有参考意义的,蓝色是心得。—— chenyusiyuan)
科研随想录(1)——民营企业家的精神
真正做学问,是要一种精神的。民营企业家有种为自己干活的务实精神,有种猛冲猛打、锐意进取、死死咬住项目不放的精神,有一种从早干到晚、星期天也不休息、有家不回有孩子不抱的精神,是现在的研究生做科研所缺乏的。
(心得:的确,就是要有这种冲劲和韧劲,不把实验做好誓不罢休;当结果出来的时候,多苦多累都值得!—— chenyusiyuan)
学生不是老板的打工仔。不要把自己默认为老板的打工仔,如果把自己默认为老板的打工仔,则不能真正发挥自己主观能动性,不利于培养独立工作能力。老板是董事长,手下的学生应该把自己默认为项目经理,要把老板交给自己的工作真正当作自己的事情,真正落到实处。要独当一面,做好可行性分析、项目设计、药品管理、经费管理、时间管理和文字处理,在科研中培养管理能力和独立工作能力。
(心得:受教了,以后也要锻炼出独当一面的能力。科研有时候和做生意是相通的。—— chenyusiyuan)
充分发挥主观能动性,做不好实验,连觉也睡不着,中午也不要休息了。只有有这样的心态,才能做好科研,否则把自己当作国营企业职工,下班铃一响就吃饭,今天没干完的事情留到明天去做吧,实验做不好就做不好,自己也不急,只故自己打游戏上网看录象,这样怎么能做出出色的科研呢?
总之,我的观点是:民营企业家的那股锐气,那种为自己干活的精神,那种死死咬住不放精神,对于做科研的人来讲是有很大启示作用的。科研和管理其实有很多相通之处。
科研随想录(2)--对出文章态度的再认识
一个人对钱的观念和文明程度会随着拥有财富的增加而变化。我从小生活在贫民区,那里的人很穷,越是穷的人越是把一点钱看得比什么都大,涉及金钱利益的时候非常斤斤计较,看电视不开灯,冲马桶用掏米洗菜水,热死不乘空调车,在菜场里为了便宜五分钱还要讨价还价老半天,临走前还趁人不注意从摊贩那里捞上一把。子女为了房子展开激烈争夺的屡见不鲜!而当一个人有一千万的时候,对钱的认识和文明程度会有新的变化,人们会为了成就感而工作,为了自己的兴趣爱好而工作,而不是为了吃饭而工作。人们会更加慷慨,更加心胸宽广。至于象李嘉诚那样,就更是一种新境界了。
同样,我对出文章的态度也随着出文章数的增加而变化。没有文章的时候很喜欢出文章,觉得文章多很扎台型,现在不是到处搞攀比吗?为了出文章,据复旦校报上讲,现在很多人不是流行一篇文章拆成三篇来写吗?不是流行“快报 + 长文章”吗?评奖学金不是要文章吗?出国不是要文章吗?
以前有人批评我的文章是短文章,我忿忿不平地说:“短文章也是文章!有总比没好!”,但是随着文章数的增加,我觉得文章多又不能当饭吃。如果我要出国,那么两页的中国文章也拿不出去啊。如果我将来要当教授,那么底下的评委又不是傻瓜,文章档次当然很重要。看了外面一些学校一些人的博士论文最后一页“文章发表目录”,发现有的人文章很多,三十几篇,但都是名字也没有听到过的杂志和会议论文,而且一大半都是第10作者,一篇外国文章也没有。这样的“文章多”,给人一种什么感觉呢?
随着阅历的增加,我更多地接触了Journal of Catalysis上的文章,更多地了解了我的美国老板——Zaera教授文章和老板的老板——Somorjai的第一流的文章。Zaera的文章并不多,一年只出10篇,起初我带着一些嘲笑的眼光看这个数字“10篇”,但是查到原文,发现这所谓“10篇”,真是一篇抵得上中国人10篇,文章长得不得了,每篇文章印出来15-20页左右,数据多得难以想象,讨论占文章长度的1/2。至于内容,更是有意义的。看了这些文章,的确对我出文章的态度产生很大影响,即:我希望我将来的 Paper List 上都是长文章,都是高质量的文章,这也是中国老板经常教育我的。
科研随想录(3)——两种不同的科研风格
我们实验室今年有两个人出国——我和我师兄。我们从主观上讲都想搞好科研,但我们的科研风格,是两种各有千秋的风格。
我师兄是那种沉得住气的人。他喜欢做那种难度大得惊人的课题,而对“不做也能想象得出大致结果”的课题显然不感兴趣。他可以容忍一年甚至更长时间实验毫无进展,他能够忍受成百次的失败,他能从容不迫地坚持做实验到硕士论文写作前几天,他能卧薪尝胆待业考托福GRE联系出国。
而我的科研风格,受做生意影响很大。6-7年前的两个暑假,我在舅舅的公司当销售员。做零售就是这么一种心态,就是“每天要确保营业额”,如果今天没有什么生意,宁可降价也要确保营业额,如果当天不完成一定的营业额,心里很是不安,如果几天没有做到生意,更是急死了。做生意还有另外一种心态,就是总归拣好做的来做,不好做的不做。
于是,到目前为止,我的科研风格就是喜欢做那些每天都有数据进帐的实验,哪怕是机械操作。我不大喜欢做难度大得惊人、连影子也没有的课题。我倒比较喜欢做工作量大得惊人,但至少能做出来、每天都有收获、每天都知道明天该做什么的课题。
我师兄和我科研风格的不同,除了和彼此个性有关以外,可能和专业特点有关。他搞的是材料合成,我搞的是催化。材料合成要动脑子的,失败的可能性大;而催化是“苦功型”的。你说真正有多少特别的创造发明在里面?很少有。催化就是不厌其繁地做做做,焙烧温度的影响、负载量的影响、稳定性考察,或者是TG结果、TEM结果、XPS结果、IR结果、XRD结果、反应测试结果......
(心得:做实验要耐心、细致、坚持、考虑周全。—— chenyusiyuan)
我难以区分这两种科研风格,哪种更好些。也许我们以后也要做生意的,这两种风格照样还会体现在彼此的做生意风格中......
科研随想录(4)——发表文章和积累
很多同学都希望出引用因子高的文章,其实出文章也有积累效应的。催化界文章的最高境界是Journal of Catalysis,这个杂志并不是随便投投就一投即中的。
在Journal of Catalysis发表文章是需要工作积累的。这包括两层意思:一层是在这个课题上做过很多铺垫性的工作,获得了很多经验,在自己经验和积累的基础上,在自己体会深刻的领域,往往能够取得突破;第二层意思是你在这个领域做多了,发表了很多文章,到最后这个领域的专家都认识你了,知道你的工作的系统性、可靠性和对这个领域的重要性,那么给予发表乃是顺理成章的事情了。即审稿人就是搞这一行的,也看人头的,也知道做这一行有这么个小有名气的人,而假设一个“某某师范高等专科学校教务处”的名字也没听到过的人也来投这个杂志,多半是退稿;如果审稿人是大同行而不是小同行,也会看投稿人的“参考文献”部分,以前有无在这个领域发表过文章,在这个领域的国际杂志上发表很多系列工作的人比什么也没发表过的“新面孔”录取机会高得多。
(心得:科研要沉得住气,要有系统性,注意积累。十年树木,百年树人。—— chenyusiyuan)
2000年,我们课题组实现了Journal of Catalysis零的突破,而为了这个零的突破,我们在固体超强酸方面做了10年的铺垫,形成了一套成熟的催化剂制备、表征方法,搭好了装置,并熟透了文献。10年来发表了一系列工作,逐渐从国内走向国外,工作被国外多篇REVIEW引用,国外一些做超强酸的大家也来函索取发表在中国杂志上的文章。正是在这样一种好氛围的熏陶下,才能够形成一定的飞跃,厚积才能薄发。当时设想我们组如果能有突破的话,最有希望在这个领域突破,可以说那篇Journal of Catalysis是偶然中的必然。
(心得:想起了蚁群算法之父Dorigo,1991年提出蚁群算法的时候,学界一点反应都没有,但Dorigo一直在坚持着,对蚁群算法进行了系统研究,建立模型、实验验证、应用探索……踏踏实实地夯实根基,终于有了1995年那篇蚁群算法里程碑意义的经典论文。—— chenyusiyuan)
一回生,二回熟。同一个杂志投多了,编辑也知道你投过来的稿子都是很有意思的,而不是“戳一枪”混一篇文章。老客户了嘛,因此就很好通过了。这也是一种累积效应。
科研随想录(5)——“废数据” (推荐!)
大家硕士毕业了,完成了薄薄的一本硕士论文,但是回过头去想想,这三年里面,人也天天在实验室,但是为什么硕士论文那么薄?吉林大学徐如人小组的学生人人出一堆文章,而我们为什么出文章那么慢?
大家一样在做实验,但是我们的数据的“有效利用率”是多少呢?起码1/3-1/2的的数据都是废数据!科研是要能够耐得住失败的,但是很多失败都是自己主观原因造成的!!!
首先,不看文献不做实验。不要文献也不查查好,急着做实验想一星期出篇文章,结果做了老半天,再看看文献,发现几年前别人已经做过了。或者文献的实验部分也不看看清楚就做实验,等到写文章了才发现自己的反应条件全部都是错误的,全是废数据。还有,文献也不看看清楚,等实验做完了才发现自己的结果和前人结果有严重矛盾,自己又不是什么一言九鼎的催化大师,写好的文章也只能往垃圾桶里扔了。
其次,药品纯不纯啊?不要跟我说你从实验室角落里随便拿了一瓶什么“1970年国营**化工厂”的药品来做实验噢。在有些精细的实验中,即使是买来的“分析纯”的药品,都要事先检验纯净度的。提纯是难免的。别到了最后才发现药品不纯,结果做的数据全废了。
再次,不要节约用钱啊。在家里不要把水龙头拧成滴水成线而水表不转的状态,在实验室不要把气相色谱记录仪的走纸速度调成只出峰面积而不走纸的状态。光看峰面积,你叫我如何判断这个数据有用没用?假设基线没走稳,则数据没用,但是如果记录仪不走纸,我如何判断基线有无走稳?
善于观察的人能发现新现象,实验中往往能发现微量的新物种,这些物种对判断反应机理有重要作用。比如有人发现在固体超强酸催化烷烃异构化中有微量烯烃生成,于是新的反应机理就突破了。而假如你把气相色谱的最小峰面积设得很大,那么你怎么判断有没有新物种生成?如果有,量又是多少?
还有,实验条件事先设计好了没有啊?不要对我说你的这个系列催化剂负载量是10%、20%、30%、40%,而那个系列催化剂负载量是0.1、0.2、0.3、0.4 g/g 载体噢!!这两种计量方法是不同的,在同一篇文章中出现两种计量方法是非常可笑的,把一种换算成另外一种,就会带来“负载量为 9.09%, 16.67%, 23.08%, 28.58%”这样难看的数字。而且两个系列催化剂之间根本无法对比,因为它们的计量是不同的。
做实验还真是一门学问,没有猛干精神不行,光有猛干精神更不行。“多动脑筋少动手”,不错不错!!
科研随想录(6)——出文章秘诀 (推荐!)
系里规定硕士毕业要一篇SCI,博士要两篇SCI,能否完成?很多同学愁眉苦脸怕完不成,其实是不知道“行情”,吉林大学、大连化物所、南京大学有些牛人的学生,出起文章来速度很快。博士毕业10篇外国文章都不希奇。
出文章,的确有窍门!!别的我不敢说,我来说说催化吧!!
首先,“鲜花需要绿叶陪衬”,你研制出一种好催化剂,你就要拿10种不做也知道没有活性的催化剂来衬托它的好。大家都是这么做的,否则审稿人就会说:“空白实验做过了吗?不加催化剂有没有活性啊?你的二元金属氧化物活性很高,你和它们各自的母体氧化物比较过吗?不比较你怎么证明二元比一元好?你的是二元固熔体,你做过二元氧化物机械混合的催化剂吗?你的是Si-Al,你做过Si-Ti吗?你做过Si-V吗?你怎么知道Si-Al最好?还有,你的催化剂和文献报道的最好的催化剂比较过吗?退稿!!”
(心得:这审稿人一连串的发炮,够震撼啊!由此也加深了一个认识,研究的成果不能“黄婆卖瓜——自卖自夸”,有比较才有优劣,看看那些十几二十页的论文,一半版面都是在比较、分析、讨论的,这就是严谨、认真。—— chenyusiyuan)
其次,数据越多越好,有些东西也许是你不做也知道的,但是不能因为不做也知道规律而不做,越是做得出的东西越是要做。文章里不能老是有标新立异的东西,大路货也要有,这是文章的血,这是文章的肉,这是稳拿的数据,这是体现工作量的,没有功劳也有苦劳。
比如外国催化大师做杂多酸铯盐的新反应,每开发一个新反应,自然先要把杂多酸铯盐表征一番。这种东西不做也知道什么样,但做了更好。XRD,红外,热重,酸量......这种稳拿的数据先做好,然后做一个别人从来也没做过的反应,就可以发篇好文章。
还有,外国有的人机械研磨法做LiMn2O4尖晶石,用来做电池。那种文章很好出。要是轮到一些不会混文章的人来做实验,准保是“一点法”,即给出一个最佳配方,然后测测电化学性质。那个外国人会做,他考察了研磨时间的影响:不研磨、研磨2, 4, 6, 8, 10, 小时,看它们的XRD、比表面、TEM变化,很有规律;然后考察了焙烧温度的影响:不焙烧、200,400,600,800,1000,1200度焙烧,看它们的它们的XRD、比表面、TEM变化,很有规律,并用TG/DTA和前面结果关联;最后考察了样品的电化学性质,就出了篇好文章。
这可不是投机混文章,这是科学的严谨态度!这是不厌其烦!!很多科学家都是这么做的!!比如 Surface Science 上面很多文章都是这么做条件实验的:改变吸附气体的吸附量,改变脱附温度......
[2008评注: 科研认真精神是需要的,但是做实验前要想清楚这个体系有没有意思?没有意思就不要详细考察条件的影响,而是应该放弃。]
要想出长文章就是要苦做,数据往多里做,文章往长里写。想省力,最好做两个星期就出篇文章反而适得其反。做实验不一定是速率决定步骤,审稿才是。与其数据不丰满而被退稿,来回四个月过去了,还不如静下心来把数据补补全,把文章写写好。把工作量调整到正好够发“某某学报”的程度而把工作嘎然而止是可惜的。要“法乎上,取其中”,数据能充实尽量充实,文章能丰满尽量丰满。
还有,写文章要“你有我有大家有”,充分引用他人工作。这可不是拍审稿人的马屁。文献没有引用好只能说明你文献把握不全,不能正确领会这个课题的意义和动向。另外,数据规律也要和别人大致吻合,提出一个观点要能找出三篇文献来证实我的观点,这是一种保险文章的写法。如果实验现象反常而没有合理解释,那只有退稿的份了。老实说很多文章都没有特别大的新异,要全文通篇有新意很难。中国人发发文章,往往是催化剂和别人不一样,但规律和前人的工作基本吻合,那也就可以了。
科研随想录(7)——合作精神
是不是希望写文章的署名栏人越少越好啊?一开始我也是这么想的,但是时间长了,第一作者的文章多了,就不这么想了。
有些人真把天下看成漆黑一片,仿佛天下老板都是什么事情都不做而挂名的。我当然不赞成随便挂名,但至少在复旦,主流还是好的嘛!!现在的老板又不是傻瓜,他不会随便给别人挂名而去冲淡自己的贡献。
对所谓“挂名”的态度,表面上打着“反对挂名”的旗号,实际上是拒绝合作。表现在实验中拒绝和别人交流讨论,怕别人知道自己的实验情况,有些实验明明可以叫别人轻车熟路帮忙做一做,却偏偏要自己活受罪从头学起耽搁了实验进度,为的就是少署个名字;有的表征明明可以去做,做了有助于提高文章质量,把蛋糕做大,但自己的私心在那里作怪,怕别人“篡党夺权”而忍痛割爱不去做表征。以上都是“岛国文化”、小家子气,钻进小楼成一桶,一辈子都走不出自己的这个圆。
年轻人,把什么署名先后拉,什么署多少人拉看得那么种有什么用?你要评院士,你并不会因为这两篇文章而评得上;你要找工作,回过头想想文章又有什么用,赚点钱不比你发篇文章强啊?不要老是把文章看做是自己的私人财产,没有课题组的积累,哪来的个人成就?没有人帮你搭仪器装置,没有人帮你测试样品,哪来的你的文章啊?理科不是文科,不是你坐在小房间里看看书动动脑子文章就出来的。
这样私心这么重,这样怕合作(因为一合作,就必然涉及到作者名单的增长),以后谁还来和你合作啊?
[2008评注: 与人合作是很困难的事。Making the right moves一书介绍了与人合作的注意事项。]
科研随想录(8)——文献是个宝
不读文献不做实验。否则,一是做了老半天发现别人做过了;二是做了老半天发现实验条件都是错误的。做了也白做。
文献读一遍是远远不够的,每读一遍都有新的收获。初次接触一个课题,往往看文献如坠入九里云雾中,不能深刻体会其精髓和实验细节的奥妙之处,只留连于具体的实验结果;做了实验,碰到难题了,回过头来再去分析、比较、仔细体会,方知奥妙之所在,对这个课题才会有更深的认识;等到写文章了,再看看文献,比较自己和文献的结果,庞征博引,使感性认识上升到理性高度;文章发表了,自己的文章也成了文献大海中的一朵小浪花。
只有做了实验,才会真正读懂文献。也就是说,如果要写综述,自己没有做过这个课题,很难写好综述。而一旦读了很多文献,又做好了实验,研究生还是完全有能力写一篇综述的。很多同学抱怨出文章难,其实文献不能白看,看看文献也能在中国杂志出篇文章呢。这篇文章又可以算硕士论文第一章,真是一举两得。
科研随想录(9)——老板剥削论?
我曾经说过到国外去干活,做出成绩都是老板的,这是剥削;别人还对我说我们研究生做实验,发表专利算老板的,不合算云云。其实我脑子早就变了,没有什么“被剥削”的概念。
首先,出文章对你自己的前途有好处啊。出国看文章,我回国当长江学者黄河教授也看文章啊。没有老板的正确指导、流利写作和把关,没有老板的名字做招牌,你一个人能达到这种效果吗?老实说外国某教授的有些文章,是学生做实验老师写文章,在这种情况下即使老师挂第一作者也很正常嘛!!什么“剥削”啊,“剥削”啊。你看看那些文章嘛,讨论占一半以上!!没有老师那支笔、那个脑袋、那个名字,文章只能往低档次里投了。学生这样被“剥削”还是合算的。
其次,干活培养你自己的能力啊。老板经常教诲我要热心公共事物,要做得多,手要勤脚要快,勇挑重担多做“额外”的事情。对于好学生就是要压担子,做得越多就越熟悉,就做得越快,别人赶也赶不上。几年来我深深感到老板的话是对的,我也在努力地做事。哪怕是跑跑财务科、采购采购仪器照样可以接触更多、培养能力!我的能力提高地飞快这些能力是抢也抢不走的。老板也非常乐意做很多“额外”的公共事情,同样是速度飞快,越做越快,任何人都赶不上。
再次,老实说学生发表几篇文章,出了专利,本来就不产生什么巨大的经济效益。一般的,发表也只是发表了,所以剥削也无从谈起。
做学徒就是要做的,脑子里不要有“被剥削”的感觉,才能学到真本事为我所用。三年研究生,你说你被老板剥削了,其实也未必,你也在为你的将来打造资历(文章)和能力(经验)的基础,这是千金不换的。特别是后者,一辈子受用啊!!
也许有的人说我中毒了、着魔了,可我要说只有经历了,才真正会有体会——多做没错。
科研随想录(10)——一体化理论 (共鸣,同感,这样的科研是一种自得其乐)
看来现在很多同学和老师的观念需要更新。如前文所说,科研中需要一种民营企业家精神。如果把这个观念再外推,就成了一体化理论,即:(1)科研和生活一体化;(2)科研和学习一体化。
(1)科研和生活一体化:不严格按照国营科研单位“坐班时间”,而是跟着实验安排自己的休息时间,围着仪器转。仪器一转,午饭都可以不出去吃而呆在实验室一边看着仪器一边吃干粮;今天下午实验做完了,哪怕是“上班时间”照样可以回寝室睡上一觉,养足精神晚上好看文献动脑筋。或者可以去家乐福采购点东西,反正早晚都要采购的,现在有了“货物储备”,过几天就可以不去采购而安心做实验了。别人休息星期天,我偏要休息星期五而星期天工作,因为这时候仪器空闲。平时人多,仪器挤,走廊里电话响个不停,真是吵也吵死了!
(2)科研和学习一体化:我的论调是在实验室里看TOEFL、GRE也没有什么不好的。这是年轻人积极奋发、志向远大的象征,总比在寝室里搓麻将或者在花园里搂搂抱抱强吧。一边看TOEFL、GRE,一边实验做得呱呱叫的人确有其人(不是我。)特别是对于催化实验,不就是半小时打一针吗。这是苦力活,从早做到晚。总不能叫我守在仪器旁边干坐着吧,看看英语,很正常嘛!再说暑假寒假,本来可以休息的,现在在实验室开着空调一边半小时打一针一边看我的英语书,公私兼顾嘛!!文章也出了,英语也看了,一举两得嘛!!
现在很多老板都想通了。不让我看GRE我不来了,或者出工不出力,或者出一堆废数据浪费药品仪器,这不两败俱伤吗?再说现在出国的人希望多出文章好出国,不出国的人混篇文章毕业就行了。所以阻止学生出国是种荒谬的想法,不利于学生,也不利于老板效用最大化。
科研随想录(11)——能垒效应
对于刚开始搞科研的人来说,绝对存在能垒效应。有的人做出成果的活化能大一点,有的人小一点,这和自己自身的功底有很大关系。基础没打好,活化能特别大,甚至连英语阅读、文章写作、图表绘制都会成为能垒的一部分。
老师是催化剂,可以降低活化能。学生一旦开窍,再加上自己用心,就一发不可收拾。第一篇文章最难写,一旦突破能垒,以后投外国文章不再是不可逾越的鸿沟。
科研随想录(12)——科研逆境
科研逆境是不可避免的,是我们所不愿意遇到的。本命年的时候我遇到过科研逆境,而且还是在科研顺境之后的科研逆境,其对比反差之强烈,令我寝食难安——整整一年都没有实验进展,在实验室里晃来晃去就象光吃米不下蛋的。我选择了放弃那个课题,另起炉灶。
实验室里,谁没有走过弯路?少则半年,多则一年。有时候调仪器调了半年都没有调好,有时候做了一年都没有得到任何有价值的数据。我曾经问师兄,有没有遇到科研挫折,遇到了以后是如何消除的。他说的确遇到过,挫折就放在那里,做着做着就自然消除了。
老板绝对不是那种随随便便就允许放弃的那种人。“活要见人,死要见尸”,你说实验遇到困难了,无法贯彻下去了,准备混过去了,老板就一定要知道为什么做不下去,而不是你说另起炉灶就另起炉灶。因为你做了几个月放弃了,那么即使你换了课题,说不定又做了几个月又放弃了,这就表明不是实验课题难,而是实验者自己的问题。在老板这种契而不舍的督促下,原先已经“做死”的很多题目没有被放弃,死死咬住,反而又获得了生机。这使我明白:
实验逆境并不是不可逾越的,科学总是科学,该做得出的总归做得出,尽管存在能垒。如果做不出,也要明白为什么做不出,“活要见人,死要见尸”。静下心来好好分析实验失败的原因,静下心来做一做,而不要有急着“赌输了急着翻本”的心理,那么最后总归是做得出的。
科研随想录(13)——失活和再生
我是研究催化的。催化剂有失活和再生,而作为科研主体的人,同样也有“失活和再生”现象!!
科研者不是金刚,研究做长了在某段时间内会有“失活”现象,人累了,心倦了,灵感没有了,一拿起烧杯就厌烦。这就象谈恋爱时间长了,天天在一起,该干的事情都干了,就觉得不过如此,一点意思都没有了。
做一个课题,绝对需要一鼓作气,设计实验的时候宁可做全一点,不要“敬酒不吃吃罚酒”,等到退稿了才去补数据。这时候一种厌倦的心情油然而生,“又要补数据啊”,而且仪器工作也改变了,仪器也坏了,实验结果和一年前做的不一定有精确的可比行性。
长时间没有实验结果导致毕业压力大,同样也会产生“失活”现象,拿起烧杯的时候就想“别又是一堆废数据”,对科研彻底失去信心。再加上看看其他同学文章多,导师又催得紧,心理压力就更大了。
科研热情的“再生”,有时可以通过“偏离”(deviation),即离开实验室,不去想任何实验问题,到外面社会上去走走看看,做不出实验就休息一段时间,让脑子充分地放松,然后再回到实验室做实验,有“小别胜新婚”的效果。
可是,这种“再生”是“引发剂”,如果还是做不出东西,科研热情还是会熄灭。最好的再生是:做实验走上正轨,每天都出有用的数据,文章雏形更加清晰,这样的科研是不会疲倦的。
我曾经“失活”过,后来又“再生”了。最好的实验安排,是整理完一篇文章,然后自由休息半个月。这半个月的休息比在实验室里继续泡着效果好得多。休息,是为了更好地工作。
科研随想录(14)——出文章和成就感
歌星以新专辑层出不穷为成就感,民营企业家以开了10个公司为成就感,而我从出文章中获取成就感。
《封神演义》中总有这样情节:“敌方”布下夺命的阵,“我方”一开始总是肉包子打狗有去无回,这时总有得道的仙人从容应对,凭着一朵莲花也能如入无人之境,任阵势险恶,能耐我何?
投外国文章也是这样的。混篇中国文章很容易的,随便做做就有了;可要出篇外国文章需要很大的努力,要憋着一股气,做上半年才能实现。看中国多少人在国内杂志号称“首次发现......,突破了外国文献公认的观点”,可是这些人中国文章一大堆,还号称催化大师,怎么连篇外国文章都没有?所以,如果能达到投外国杂志指东打东,指西打西的境界,也是一种从容。为人所不能为,则有成就感。
想想有些学校凭借三篇《化学学报》也能评个教授,难得出个《**师院学报》也要争先恐后地挂名,视其为油水,在复旦这么浓郁的科研气氛中成长,在不同的起点进步,我怎么没有成就感呢?这种成就感超越了工资的需要,超越了“出篇文章够毕业就行了”的态度,成为了我科研的驱动力之一。老实说,以出文章为科研驱动力之一也是正常的,真正“为了科学而科学”,做了实验只是自己探索科学奥妙而不发表的人绝对是少见的。
最美丽的景色往往在最险峻的地方,自己征服了最险峻的地方才会有成就感,而花钱雇别人抬我上去,或者仅仅从照片上看到则没有这种真实的感觉。对于出文章,只有自己“为伊消得人憔悴”,在艰难中杀出一条血路才会体会到真正的成就感。所以,我是不喜欢互相交换挂名的。不做实验而交换挂名,文章是多,但是当文章一大堆的时候,那些第三作者的文章又有什么用?把我真正花力气辛辛苦苦做的第三作者文章都淹没在文章堆里了!
************************************************************
[1] Chemistry Letters 第一作者 (1999)
[2] Journal of Molecular Catalysis A 第一作者 (2000)
[3] Chinese Journal of Chemistry 第一作者 (2000)
[4] Catalysis Letters 第三作者 (2000)
[5] 化学通报(综述) 第一作者 (2001)
[6] Journal of Molecular Catalysis A 第一作者 (2001)
[7] Journal of Catalysis 第二作者 (2001)
[8] Journal of Molecular Catalysis A 整理中 (2002)
科研随想录(15)——科研的心理屏障
以前前进GRE教材第一篇文章就是方守成的文章,他指出以前从来没人考过2000分,所以大家都认为自己考不过2000分,以至于诱导了你的复习和临场发挥,最终果然不过2000分;自从第一个人过了2000分,以后又有一群人过了2000分,于是大家都认为考2000分如屡平地,冲破了这个“心理屏障”,所以人人都超过了2000分。
我们复旦化学系绝对存在心理屏障。评奖学金的时候谁文章稍微多一点,下面的先生就跳出来说“不正常”云云。而在实验室里出文章有“极限效应”,这个极限是12-13篇。一般的博士出个三五篇文章以后,“心理屏障”效应就开始发挥作用了,不再向极限冲刺。
其实,你要是看看外面的科研单位,如今的那些杰出青年、长江学者在当年做博士的时候就显现出来了。南京大学毕业的金国新,戴安邦院士的学生,博士论文219页,博士期间发表文章第一作者20篇;大连化物所毕业的肖丰收,郭燮贤院士的学生,博士期间发表第一作者文章16篇;大连化物所毕业的赵东源,郭燮贤院士的学生,博士期间发表文章15篇;吉林大学徐如人院士的学生,个个文章一大把。
达到这样的高度没有什么“不正常”的,我们复旦完全能达到同
样的高度,很多时候是“心理屏障”在作祟而阻挡了前进的脚步。有种人做实验有股“凶”劲,杀气腾腾,死死盯住不放,猛冲猛打、掘地三尺,抱定“与众不同”的决心,对自己高标准严要求,这样就可以达到以上各位同样的高度了。
[2008评注: 不能以文章数目和杂志的名称来论英雄。有的人发了很多文章,别人也不承认;有的老外发了很少文章,却被尊为国际权威。对于研究生来说,首先要把重心放在学到什么东西。如果没有学到什么东西,出再多文章也没有用。让我们想象一个情景:一个研究生在做自己研究课题的同时,还东打一枪、西打一枪做了很多无关的文章。那么,这就是没有形成体系化,没有学到东西。在做自己课题的同时读英语都比在做自己课题的同时做无关的科研文章强。]
from http://bbs.matwav.com/
数学建模竞赛中应当掌握的十类算法
排名如下:
1、蒙特卡罗算法(该算法又称随机性模拟算法,是通过计算机仿真来解决问题的算法,同时可以通过模拟可以来检验自己模型的正确性,是比赛时必用的方法)
2、数据拟合、参数估计、插值等数据处理算法(比赛中通常会遇到大量的数据需要处理,而处理数据的关键就在于这些算法,通常使用Matlab作为工具)
3、线性规划、整数规划、多元规划、二次规划等规划类问题(建模竞赛大多数问题属于最优化问题,很多时候这些问题可以用数学规划算法来描述,通常使用Lindo、Lingo软件实现)
4、图论算法(这类算法可以分为很多种,包括最短路、网络流、二分图等算法,涉及到图论的问题可以用这些方法解决,需要认真准备)
5、动态规划、回溯搜索、分治算法、分支定界等计算机算法(这些算法是算法设计中比较常用的方法,很多场合可以用到竞赛中)
6、最优化理论的三大非经典算法:模拟退火法、神经网络、遗传算法(这些问题是用来解决一些较困难的最优化问题的算法,对于有些问题非常有帮助,但是算法的实现比较困难,需慎重使用)
7、网格算法和穷举法(网格算法和穷举法都是暴力搜索最优点的算法,在很多竞赛题中有应用,当重点讨论模型本身而轻视算法的时候,可以使用这种暴力方案,最好使用一些高级语言作为编程工具)
8、一些连续离散化方法(很多问题都是实际来的,数据可以是连续的,而计算机只认的是离散的数据,因此将其离散化后进行差分代替微分、求和代替积分等思想是非常重要的)
9、数值分析算法(如果在比赛中采用高级语言进行编程的话,那一些数值分析中常用的算法比如方程组求解、矩阵运算、函数积分等算法就需要额外编写库函数进行调用)
10、图象处理算法(赛题中有一类问题与图形有关,即使与图形无关,论文中也应该要不乏图片的,这些图形如何展示以及如何处理就是需要解决的问题,通常使用Matlab进行处理)
多吃些粗粮。
给别人比他们自己期许的更多,并且用心去做。
和别人分享自己的知识,那才是永恒之道!
熟记喜欢的诗歌。
不轻信听到的每件事,不要花光自己的所有,不要想睡多久就睡多久。
无论何时说“我爱你”,要真心实意。
无论何时说“对不起”,要看着对方的眼睛。
不要相信接吻时从不闭眼的伴侣。
相信一见钟情。
深情热烈地爱,也许会受伤,但这是使人生完整的唯一方法。
找一个爱聊的人结婚 ,因为当年龄大了以后,我们会发觉喜欢聊天是一个人最大的优点。
无论是烹调还是爱情,都用百分之百的负责态度对待,但是不要期求太多的回报。
家庭的融洽氛围是难能可贵的。
尽全力让家平顺和谐。
和亲近的人吵嘴的时候,试着就事论事,不要扯出那些陈芝麻,烂谷子的事。
给妈妈打电话。如果不行,至少在心里想着她。
当别人打喷嚏时,说一声“菩萨保佑”。
记住:最好的关系存在于对别人的爱胜于对别人的索求之上。
永远不要忽视别人的梦想。
当别人问自己不想回答的问题时,笑着说“你为什么想知道?”
用一种明确的方法解决争议,不要冒犯。
永远不要以貌取人。
记住三个“尊”:尊重自己;尊重别人;保持尊严,对自己的行为负责。
不要让小小的争端损毁了一段伟大的友谊。
无论何时发现自己做错了,竭尽所能去弥补。动作要快!
无论什么时候打电话,摘起话筒的时候要微笑,因为对方能感觉到!
慢慢地说,但要迅速地想。
只有那些敢于承担最大风险的人才能得到最深的爱和最大的成就。
如果失败了,要记住及时汲取教训。
找点时间,单独呆会儿。
欣然接收改变,但是不要摒弃自己的个人理念。
记住,沉默是金。
多看点书,少看点电视。
过一种高尚而诚实的生活。当年老时回想起过去,我就能再一次享受人生。
相信上帝,但是别忘了锁门。
不要摆脱不了昨天。
多注意言下之意。
忙自己该做的事。
每年至少去一个从没去过的地方。
如果赚了很多钱,在活着的时候多行善事。
记住:有时候,不是最好的收获也是一种好运。
深刻理解所有的规则,合理地更新他们。
回头看看我发誓取得的目标,然后评判自己到底有多成功。
善待我们的地球。
不要愚弄自然母亲。
晨宇思远:这篇文章应该是台湾或香港一位学者的生活感言,对我影响挺大,特在此和大家一起分享。人生,应该注重的,是积累,是过程……
【原文】
许多同学应该都还记得联考前夕的焦虑:差一分可能要掉好几个志愿,甚至于一生的命运从此改观!到了大四,这种焦虑可能更强烈而复杂:到底要先当兵,就业,还是先考研究所?
我就经常碰到学生充满焦虑的问我这些问题。可是,这些焦虑实在是莫须有的!生命是一种长期而持续的累积过程,绝不会因为单一的事件而毁了一个人的一生,也不会因为单一的事件而救了一个人的一生。属于我们该得的,迟早会得到;属于我们不该得的,即使侥幸巧取也不可能长久保有。如果我们看清这个事实,许多所谓人生的重大抉择就可以淡然处之,根本无需焦虑。而所谓人生的困境,也往往当下就变得无足挂齿。
我自己就是一个活生生的例子。从一进大学就决定不再念研究所,所以,大学四年的时间多半在念人文科学的东西。毕业后工作了几年,才决定要念研究所。硕士毕业后,立下决心:从此不再为文凭而念书。谁知道,世事难料,当了五年讲师后,我又被时势所迫,整装出国念博士。
出国时,一位大学同学笑我:全班最晚念博士的都要回国了,你现在才要出去?两年后我从剑桥回来,觉得人生际遇无常,莫此为甚:一个从大一就决定再也不钻营学位的人,竟然连硕士和博士都拿到了!属于我们该得的,哪样曾经少过?而人生中该得与不该得的究竟有多少,我们又何曾知晓?从此我对际遇一事不能不更加淡然。当讲师期间,有些态度较极端的学生会当面表现出他们的不屑;从剑桥回来时,却被学生当做不得了的事看待。这种表面上的大起大落,其实都是好事者之言,完全看不到事实的真相。从表面上看来,两年就拿到剑桥博士,这好像很了不起。但是,在这两年之前我已经花整整一年,将研究主题有关的论文全部看完,并找出研究方向;而之前更已花三年时间做控制方面的研究,并且在国际著名的学术期刊中发表论文。
而从硕士毕业到拿博士,期间七年的时间我从不停止过研究与自修。所以,这个博士其实是累积了七年的成果,或者,只算我花在控制学门的时间,也至少有五年),根本也没什么好惊讶的。
常人不从长期而持续的累积过程来看待生命因积蓄而有的成果,老爱在表面上以断裂而孤立的事件夸大议论,因此每每在平淡无奇的事件上强做悲喜。可是对我来讲,当讲师期间被学生瞧不起,以及剑桥刚回来时被同学夸大本事,都只是表象。
事实是:我只在乎每天二十四小时点点滴滴的累积。拿硕士或博士只是特定时刻里这些成果累积的外在展示而已,人生命中真实的累积从不曾因这些事件而终止或加添。常有学生满怀忧虑的问我:
”老师,我很想先当完兵,工作一两年再考研究所。这样好吗?”
”很好,这样子有机会先用实务来印证学理,你念研究所时会比别人了解自己要的是什么。”
”可是,我怕当完兵又工作后,会失去斗志,因此考不上研究所。”
”那你就先考研究所好了。”
”可是,假如我先念研究所,我怕自己又会像念大学时一样茫然,因此念的不甘不愿的。”
”那你还是先去工作好了!”
”可是……”
我完全可以体会到他们的焦虑,可是却无法压抑住对于这种话的感慨。其实,说穿了他所需要的就是两年研究所加两年工作,以便加深知识的深广度和获取实务经验。先工作或先升学,表面上大相迳庭,其实骨子里的差别根本可以忽略。在朝三暮四这个成语故事里,主人原本喂养猴子的橡实是早上四颗下午三颗,后来改为朝三暮四,猴子就不高兴而坚持改回到朝四暮三。其实,先工作或先升学,期间差异就有如朝三暮四与朝四暮三,原不值得计较。但是,我们经常看不到这种生命过程中长远而持续的累积,老爱将一时际遇中的小差别夸大到攸关生死的地步。
最讽刺的是:当我们面对两个可能的方案,而焦虑的不知何所抉择时,通常表示这两个方案可能一样好,或者一样坏,因而实际上选择哪个都一样,唯一的差别只是先后之序而已。而且,愈是让我们焦虑得厉害的,其实差别越小,愈不值得焦虑。反而真正有明显的好坏差别时,我们轻易的就知道该怎么做了。可是我们却经常看不到长远的将来,短视的盯著两案短期内的得失:想选甲案,就舍不得乙案的好处;想选乙案,又舍不得甲案的好处。如果看得够远,人生常则八,九十,短则五,六十年,先做哪一件事又有什么关系?甚至当完兵又工作后,再花一整年准备研究所,又有什么了不起?当然,有些人还是会忧虑说:我当完兵又工作后,会不会因为家累或记忆力衰退而比较难考上研究所?
我只能这样回答:一个人考不上研究所,只有两个可能:或者他不够聪明,或者他的确够聪明。不够聪明而考不上,那也没什么好抱怨的。假如你够聪明,还考不上研究所,那只能说你的决心不够强。假如你是决心不够强,就表示你生命中还有其他的可能性,其重要程度并不下于硕士学位,而你舍不得丢下他。既然如此,考不上研究所也无须感到遗憾。不是吗?
人生的路这么多,为什么要老斤斤计较著一个可能性?我高中最要好的朋友,一生背运:高中考两次,高一念两次,大学又考两次,甚至连机车驾照都考两次。毕业后,他告诉自己:我没有人脉,也没有学历,只能靠加倍的诚恳和努力。现在,他自己拥有一家公司,年收入数千万。
一个人在升学过程中不顺利,而在事业上顺利,这是常见的事。有才华的人,不会因为被名校拒绝而连带失去他的才华,只不过要另外找适合他表现的场所而已。反过来,一个人在升学过程中太顺利,也难免因而放不下身段去创业,而只能乖乖领薪水过活。福祸如何,谁能全面知晓?
我们又有什么好得意?又有什么好忧虑?人生的得与失,有时候怎么也说不清楚,有时候却再简单不过了:我们得到平日累积的成果,而失去我们不曾努力累积的!所以重要的不是和别人比成就,而是努力去做自己想做的。功不唐捐,最后该得到的不会少你一分,不该得到的也不会多你一分。
好像是前年的时候,我在往艺术中心的路上遇到一位高中同学。他在南加大当电机系的副教授,被清华电机聘回来开短期课程。从高中时代他就很用功,以第一志愿上台大电机后,四年都拿书卷奖,相信他在专业上的研究也已卓然有成。回想高中入学时,我们两个人的智力测验成绩分居全学年第一,第二名。可是从高一我就不曾放弃自己喜欢的文学,音乐,书法,艺术和哲学,而他却始终不曾分心,因此两个人在学术上的差距只会愈来愈远。反过来说,这十几二十年我在人文领域所获得的满足,恐怕已远非他所能理解的了。我太太问过我,如果我肯全心专注于一个研究领域,是不是至少会赶上这位同学的成就?我不这样想,两个不同性情的人,注定要走两条不同的路。不该得的东西,我们注定是得不到的,随随便便拿两个人来比,只看到他所得到的,却看不到他所失去的,这有什么意义?
有次清华电台访问我:老师你如何面对你人生中的困境?我当场愣在那里,怎么样都想不出我这一生什么时候有过困境!后来仔细回想,才发现:我不是没有过困境,而是被常人当作困境的境遇,我都当作一时的际遇,不曾在意过而已。刚服完兵役时,长子已出生却还找不到工作。我曾焦虑过,却又觉得迟早会有工作,报酬也不至于低的离谱,不曾太放在心上。念硕士期间,家计全靠太太的薪水,省吃俭用,对我而言又算不上困境。一来,精神上我过的很充实,二来我知道这一切是为了让自己有机会转行去教书(做自己想做的事)。三十一岁才要出国,而同学正要回系上任教,我很紧张(不知道剑桥要求的有多严),却不曾丧气。因为,我知道自己过去一直很努力,也有很满意的心得和成果,只不过别人看不到而已。我没有过困境,因为我从不在乎外在的得失,也不武断的和别人比高下,而只在乎自己内在真实的累积。
我没有过困境,因为我确实了解到:生命是一种长期而持续的累积过程,绝不会因为单一的事件而有剧烈的起伏。同时我也相信:属于我们该得的,迟早会得到;属于我们不该得的,即使一分也不可能加增。假如你可以持有相同的信念,那么人生于你也会是宽广而长远,没有什么了不得的困境,也没有什么好焦虑的了。
哈佛馆训
哈佛馆训
1.现在睡觉的话会做梦而现在学习的话会让梦实现
This moment will nap, you will have a dream; But this moment study, you will interpret a dream.
2.我无所事事地度过的今天是昨天死去的人们所奢望的明天
I leave uncultivated today, was precisely yesterdayperishes tomorrow which person of the body implored.
3.感到晚了的时候其实是最快的时候
Thought is already is late, exactly is the earliest time.
4.不要把今天的事拖到明天
Not matter of the today will drag tomorrow.
5.学习的痛苦是一时的而没有学习的痛苦是一辈子的
Time the study pain is temporary, has not learned the pain islife-long.
6.学习不是人生的全部但连学习都征服不了你还能做什么?
The study certainly is not the life complete. But, sincecontinually life part of - studies also is unable to conquer, what butalso can make?
7.学习不是因为缺少时间而是缺少努力
Studies this matter, lacks the time, but is lacks diligently.
8.所有人的成功都不是偶然的
Nobody can casually succeed, it comes from the thoroughself-control and the will.郭澧葱
9.无法避免的痛苦就去享受吧!
Please enjoy the pain which is unable to avoid.
10.早起的鸟儿有虫吃
Only has compared to the others early, diligently diligently, canfeel the successful taste.
11.成功并不属于每个人
Nobody can casually succeed
12.时间在流逝
HOW time flies
13.今天流下的口水将变成明天流下的泪水
Now drips the saliva, will become tomorrow the tear
|
从马思伟那里看过来的,此君不是一般牛人也,其在视频编码方面成就令人仰慕,吾若可略有所成,便是万幸,会感天谢地。
下在是网站对这个性格测试的说明:
由美国的心理学家Katherine Cook Briggs (1875-1968) 和她的心理学家女儿Isabel Briggs Myers根据瑞士著名的心理分析学家Carl G. Jung (荣格)的心理类型理论和她们对于人类性格差异的长期观察和研究而著成。经过了长达50多年的研究和发展,MBTI已经成为了当今全球最为著名和权威的性格测试。
主要应用于职业发展、职业咨询、团队建议、婚姻教育等方面,是目前国际上应用较广的人才甄别工具。
人的性格倾向,就象分别使用自己的两只手写字一样,都可以写出来,但惯用的那只写出的会比另一只更好。每个人都会沿着自己所属的类型发展出个人行为、技巧和态度,而每一种也都存在着自己的潜能和潜在的盲点。本次测试主要探讨各种性格类型与相关职业的匹配程度。
MBTI倾向显示了人与人之间的差异,而这些差异产生于:
– 他们把注意力集中在何处,从哪里获得动力(外向、内向)
– 他们获取信息的方式(实感、直觉)
– 他们做决定的方法(思维、情感)
– 他们对外在世界如何取向;通过认知的过程或判断的过程(判断、知觉)
用字母代表如下:
精力支配:外向 E — 内向 I
认识世界:实感 S — 直觉 N
判断事物:思维 T — 情感 F
生活态度:判断 J — 知觉 P
其中两两组合,可以组合成16种人格类型。
我的测试结果:
Psytopic分析:您的性格类型是“ ISTJ”(内向+实感+思维+判断)
沉静,认真;贯彻始终、得人信赖而取得成功。讲求实际,注重事实和有责任感。能够合情合理地去决定应做的事情,而且坚定不移地把它完成,不会因外界事物而分散精神。以做事有次序、有条理为乐---不论在工作上, 家庭上或者生活上。重视传统和忠诚。
ISTJ型的人是严肃的、有责任心的和通情达理的社会坚定分子。他们值得信赖,他们重视承诺,对他们来说,言语就是庄严的宣誓。 ISTJ型的人工作缜密,讲求实际,很有头脑也很现实。他们具有很强的集中力、条理性和 准确性。无论他们做什么,都相当有条理和可靠。他们具有坚定不移、深思熟虑的思想,一旦他们着手自己相信是最好的行动方法时,就很难转变或变得沮丧。ISTJ型的人特别安静和勤奋,对于细节有很强的记忆和判断。 他们能够引证准确的事实支持自己的观点,把过去的经历运用到现在的决策中。他们重视和利用符合逻辑、客观的分析,以坚持不懈的态度准时地完成工作,并且总是安排有序,很有条理。他们重视必要的理论体系和传统 惯例,对于那些不是如此做事的人则很不耐烦。ISTJ型的人总是很传统、谨小甚微。他们聆听和喜欢确实、清晰地陈述事物。ISTJ型的人天生不喜欢显露,即使危机之时,也显得很平静。他们总是显得责无旁贷、坚定不变 、但是在他们冷静的外表之下,也许有强烈却很少表露的反应。
您适合的领域有:工商业领域、政府机构 金融银行业、政府机构、技术领域、医务领域
您适合的职业有:
· 审计师
· 会计
· 财务经理
· 办公室行政管理
· 后勤和供应管理
· 中层经理
· 公务(法律、税务)执行人员
· 银行信贷员
· 预算分析师
· 保险精算师
· 税务经纪人
· 税务检查员
· 机械、电气工程师
· 计算机程序员
· 数据库管理员
· 地质、气象学家
· 法律研究者
· 律师
· 外科医生
· 药剂师
· 实验室技术人员
· 牙科医生
· 医学研究员
· 信息总监
· 电脑编程员
· 证券经纪人
· 会计
· 文字处理专业人士
注:本测试为beta版,答案供参考,不妨给本次测试结果的准确度给予百分比评价(100%为完全符合)
同时为更好地帮助后来的测试朋友,如果您觉得有不合适或者遗漏的职业,欢迎一起 参与这个测试的改善。
yuv和yCbCr的差异
Peter Lee 2006.02.28 videosky.9126.com
今天在看intel ipp tutorial的时候,看到了讲色彩模型的部分。以前,一直没明白yuv和YcbCr之间的差异,想必有些朋友也会有同样的疑惑。所以,我看完之后就记载下来了。
一、和rgb之间换算公式的差异
yuv<-->rgb
Y'= 0.299*R' + 0.587*G' + 0.114*B'
U'= -0.147*R' - 0.289*G' + 0.436*B' = 0.492*(B'- Y')
V'= 0.615*R' - 0.515*G' - 0.100*B' = 0.877*(R'- Y')
R' = Y' + 1.140*V'
G' = Y' - 0.394*U' - 0.581*V'
B' = Y' + 2.032*U'
yCbCr<-->rgb
Y’ = 0.257*R' + 0.504*G' + 0.098*B' + 16
Cb' = -0.148*R' - 0.291*G' + 0.439*B' + 128
Cr' = 0.439*R' - 0.368*G' - 0.071*B' + 128
R' = 1.164*(Y’-16) + 1.596*(Cr'-128)
G' = 1.164*(Y’-16) - 0.813*(Cr'-128) - 0.392*(Cb'-128)
B' = 1.164*(Y’-16) + 2.017*(Cb'-128)
Note: 上面各个符号都带了一撇,表示该符号在原值基础上进行了gamma correction
二、来源上的差异
yuv色彩模型来源于rgb模型,
该模型的特点是将亮度和色度分离开,从而适合于图像处理领域。
应用:basic color model used in analogue color TV broadcasting.
YCbCr模型来源于yuv模型。YCbCr is a scaled and offset version of the YUV color space.
应用:数字视频,ITU-R BT.601 recommendation
ps:
通过上面的比较可以确定,我们在h.264,mpeg等编码标准中用的yuv其实是YcbCr,大家不要被名称搞混淆了。
知人者智,自知者明。此二句文全出自老子《道德经》。
智,是自我之智。明,是心灵之明。“知人者”,知于外;“自知者”,明于道。智者,知人不知己,知外不知内;明者,知己知人,内外皆明。智是显意识,形成于后天,来源于外部世界,是对表面现象的理解和认识,具有局限性和主观片面性;明,是对世界本质的认识,具有无限性和客观全面性。欲求真知灼见,必返求于道。只有自知之人,才是真正的觉悟者。
老子说了,知道别人,你是智慧。你了解别人,你是智慧;你知道自己,了解自己,这是高明。同志们想,知道别人是智慧,知道自己是高明,合起来就是明智,你这个人很明智。
圣人孔子说过:“知人者智,自知者明,胜人者有力,自胜者强。”意思是说,能认识别人的叫做机智,能认识自己的才叫做高明,能战胜别人的叫做有力,能克制自己的人才算刚强。
知人者智,自知者明。胜人者有力,自胜者强。
大意是说:了解他人是一种智慧,而了解自己更是一种智慧;战胜他人表明自己有力量,而战胜自己则表明自己很强大。
在老子看来,了解他人和了解自己都是智慧,然而了解自己比了解他人更进了一步。
为什么这样说?
其一是因为,了解自己要比了解他人难,之所以说难,那是因为自己看不到自己,自己想不到自己;而要看到自己,想到自己,就无原则要有更大的智慧,需要有以他人为鉴的能力。
这一点,战国时期的哲学家韩非用具体事例做了说明。他说:
楚庄王欲伐越,杜子谏曰:“王之伐越何也?”曰:“政乱兵弱。”杜子曰:“臣愚患之。智如目也,能见百肯之外而不能自见其睫。王之兵自败于秦、晋,丧地数百里,此兵之弱也。庄路为盗于境内而吏不能禁,此政之乱也。王之弱乱非越之下也,而欲伐越,此智之如目也。”王乃止。故知之难,不在见人,在自见。故曰:“自见之谓明。”
楚庄王只看到越国朝政混乱、兵力薄弱,而看不到自己国家朝政混乱和兵力薄弱,因此想去讨伐越国。杜子认为这是不明智的,并且用眼睛只能看到外物而看不到自己为比喻,使他明白了自己的缺陷,停止了愚蠢的行动。韩非通过这个事例说胆老子“自知者明”。并且下结论说:达到有智是很难的,之所以难,不是难在了解他人,而是难在了解自己。
其二是因为,了解自己以具有自我意识为前提,而自我意识一旦产生,这就将会把人的智慧由个体自我意识引向类别自我意识:当人有了个体自我意识的时候,也就在人的头脑中树立起了一个自我的标的,形成了一个全新的认识目标;向着这个目标前进,就会在深入了解个体自我的基础上,逐步形成类别自我的意识。
《道德经》“知人者智”有感
知人者智,自知者明。胜人者有力,自胜者强。知足者富。强行者有志。不失其所者久。死而不亡者寿。
——《道德经》第三十三章
在读这一章的时候,我总是感觉每两句之间是一种递进的关系,细细忖度,似又不全是,前四句倒可以这么判断,后四句就未必了。产生这种模糊的感觉可能与恰好每两句的第二句给我的感触更深有关系。
“自知者明,自胜者强,强行者有志,死而不亡者寿”。自知比知人更难,自胜比胜人更艰,这是现时为人普遍认可的真理性的结论。“知足者富”则成为有些人挂在嘴边聊以自慰的麻醉剂,使得这一句总是让人联想到停步不前与不思进取。其实从“为”的广义论,老子无为即是有为,因为饯行“无为”的行为就是“有为”。所以“知足者富”更强调的是控制欲望,对结果淡然处之的境界。与此同时,便是要有志,要强行。所以人言:老子的哲学是无为,就是消极避世,是消极哲学,我深不以为然,这是对老子的思想一知半解的产物,是没有读懂老子的主张。否则老子怎么会在“知足者富”后马上阐明“强行者有志”?怎么会还提到“言善信,正善治,事善能,动善时”?
“死而不亡者寿”是老子对生命价值的阐述,也引发了我对生死问题的思考。人从出生一刻起就在经历死亡的过程。死亡是死亡过程的终结,也是死亡过程的高潮,就如同新年午夜的最后一声钟鸣。所以,所有活着的人都无时无刻不是在体验死亡的过程。长寿不单纯是以存活时间来计算的,如果用整个人类的历史来衡量,活到二百岁,与活二十岁的区别小到可以忽略不计。对于个体来讲,多活几十年在生命终结时也是没有多大差别的,遗憾也罢,没有遗憾也罢,都要撒手的。而生命的价值则是长寿的矫正值。老子的思想存活到现在,历经约2500多年而不朽,老子的寿命应是实际生存时间加上这还在延续的2500多年。普通百姓一生疼儿疼女,他的寿命则应是实际生存时间加上儿女怀念他的时间。而如果生命特征仍在,但凡事以一己私利为本,全然无惠及他人之处,那么,他的寿命就要做减法了,需要用实际生存时间减去开始自私自利的时间。左派诗人臧克家的那句诗是有道理的:有的人活着,他已经死了。有的人死了,他还活着。我们都要反省,我们还活着吗?我们要怎样活?
一个可爱男人对老婆的忏悔
2008-08-08 10:20
遵照您的旨意,我在书房里反省了一个小时四十三分零七秒,喝了一杯白开水,上了一次卫生间,没有抽烟,以上事实准确无误,请审查。附上我的检讨报告,不当之处可以协商。
经过3个月的婚姻生活,我认为老婆同志温柔贤良,勤奋聪颖,是不可多得的好妻子,而身为丈夫的我却举止乖张,态度轻狂,所作所为确有值得商榷之处。
以下是我对自己恶劣行径的剖析,请领导批阅:
1.昨天的事情是我不对。你做的红烧茄子虽然有点咸,但是香醇可口,瑕不掩瑜,我不该指责你浪费盐。我这么求全责备,完全是暗藏嫉妒之心。不过再加点水是可以的。
2.你说喜欢陆毅的时候,我不该信口雌黄说我喜欢梁咏琪,害得你两天不能理我,极其痛苦 。仔细一想,我的回答确实很不妥当,因为你的花心还局限于内地,我却冲到了港台,我还是喜欢周迅好了。
3.你喜欢看韩剧里的小政哥,我不该百般阻挠,你拿我和他比较我也不该表示抗议,因为人家小政哥都没有抗议。
4.星期六的那次婚礼,我说我开会,不知道能不能去,你准备了两个红包,一个100的,一个200的,结果我没去,你不小心送出去了厚的。亲爱的,我不该笑你,你已经做得很好了,换作我,可能将两个都一块儿送出去了。
5.上次你买来黄花鱼,我不该信誓旦旦,冒充大厨,结果你帮厨时欢呼雀跃,闻味时垂涎欲滴,吃的时候却垂头丧气,对于你脆弱的心理而言,这是难以承受的。
6.你剪短了头发,问我好不好看,我说好看,你很高兴;进一步求证,我说还行;你追问到底好不好,我回答,不如以前好,使你非常难过。这是我的错,以后此类的回复均以第一次为准。
7.你在网上认识了很多优秀的朋友,一时间鸿雁传书,玉照纷飞,我不该用报纸上的报道打击你 。不过你穿白裙子的那张照片真的不好看,还是穿高领衫的那张好,旁边有我当保镖,显得气派。
8.探望你外甥那次,你回来和我讨论谁应该洗尿布,我的确不该推卸责任,惹你生气。不过亲爱的,这项任务过于遥远,我们还是讨论谁负责生好了。他们家是谁生的?
9. 你指责我把袜子到处乱放时,我不应该反诬你到处放书,毕竟袜子是臭的,书是香的。
10.你请雪儿吃麦当劳的时候,我不该在桌子下面偷偷踢她,让你大发雷霆,可是她踩坏了我那么多皮鞋,你为什么都不管?
11.你说我长得不如你漂亮的时候,我不应该顽固抵赖,你说得很对,证据确凿,可以让瞎子作证。
12.我下楼倒垃圾回来,你围着我转了好几圈,问我抽了几根,我说一根,你就大生其气。亲爱的,我真不知道你的鼻子如此灵敏,其实我抽了两根。
你一直是善解人意的女孩,希望你能够原谅我,给我改过自新的机会。为了家庭安定,经济繁荣,顺便提几个小小的建议:
1.不要指着电视里的帅哥说他像你从前的男友,你第一次近距离接近男士是在大二的舞会上,慌慌张张地狂踩别人的脚,很不幸那个人是我。
2.逛商店的时候,不要总是突发奇想,比如要买一个粉碎机回去做蒜泥,你不觉得我这个机器比较经济吗?
3.吃饭的时候,你总是嫌我吃得少,照相的时候却又嫌我胖,亲爱的,这真的让我很为难。
4.不要给我出一些刁钻古怪的问题,说那是脑筋急转弯,结果让我逻辑混乱。
5.不要在我看枪战片的时候给我讲笑话,而且不笑不行。
以上种种,请老婆大人明鉴。友情提示:卧室里昨日有蜘蛛出没,如需护驾,请联系客厅西面休闲区组合沙发一号,竭诚为您服务。
|
喜欢过很多东西,喜欢学很多东西,因为好奇,因要寻找不确定中的确定之美。歌德的话始终在心中萦绕“一个聪明而又好学的人,通过他所做好的一个事,可以做好每一件事”。
人生却是充满了不确定。被拉着进入小学教室,不知怎么上了初中,一不小心还考上高中,上了大学,又读了研,或许会再读。是啊,人很多时候不知道自己要做什么,甚至其实很多时候都不知道自己正在做什么。可一个人如果能把这些都想清楚了,那他就不是人了,是人精了。我们活着就是要不断的经历。
我却又常是要寻找确定性,于是喜欢数学,相信我能做好一件事因为我都能把它做坏。于是颠覆了好与坏的原义,超越了观念的阻挠,直接面对事情本身。这是好的,它简化了我了解事情本原的过程。
很多的信念在心里慢慢的变成了原则,于是就顺理成章,理所当然,自然而然的做事,不对人。是好也有坏。
我不是在写《忏悔录》,但发现我用了它的语气。
想自己或许可以写小说,至少懂得怎么玩语言,有些想象,有些经历,也会瞎编。可什么时候写呢?我没有时间?
曾经给自己定下规划,要常常问自己在做什么,要自省,要整理思路,可时常却不会。毕竟吾非柏拉图之辈,乃一介平民。求事事尽心,求我心泰然,求稳健求成熟,目标有甚多。目标分解,大事化小,小事个个击破,思路也常有,行动却迟缓。
常思人生苦短,应趁有心有力之时,有所建树,有所累积,有一专能,却未能。钱老说二十岁不狂者无志,三十岁仍狂者无智,可我处中间者应如何。生活的要素不多也不少,却也常使人困惑,常不能专心。坚持是成功的必要条件,却不曾实践之。忘记是沉浸另一件事的需要,却鲜有做到。这或许且称之为人生的第一个四份之一的结束,究竟意味着什么呢,我却还不知道。
简单的道理,丰富的生活。有很多时候却是“老人(指我以前的老师们)言“终究是对的:
王玉国老师说:没有做不到,只不想不到。
张老师说:能改变自己的人是成功的人,能改变别人的人是一个伟大的人。
高老师说:做人其实低头比抬头更难。艰难困苦,于汝玉成。
有幸初生牛犊就见到了我”高高在上“的导师,也给四点忠告,说在研究生阶段很重要的要着力发展的四点
一、人际关系;
二、扩大知识面;
三、英语;
四、术业要有专攻。
还有很多,时常在经意间想起,感触良多。但是过后却也如云烟,许是道理懂得太多,行动却是太少吧。努力行动吧!
『VC++技术内幕』(第四版)读书笔记
关键字:VC++
原作者姓名:loose_went
文章原出处:vczx.com
写在前面:
站长所看的『VC++技术内幕』版本为--潘爱民和王国印译清华大学出版的第四版,因有时工作忙碌,不能及时更新,请大家见谅!
第一天 Windows的编程模式
Windows程序中必须要有WinMain函数,因为该函数最重要的任务是创建该应用程序的主窗口。Windows程序与基于MS-DOS程序的最大差别就在于:MS-DOS程序是通过调用操作系统的功能来获得用户输入的,而Windows程序是通过操作系统发送的消息来处理用户输入的。Windows消息都是经过严格定义的,并且适用于所有的程序。
WINDOWS提供通用的图形设备接口(GUI),我们通过调用(GDI)函数和硬件打交道,不必理会设备环境,WINDOWS会自动将设备环境结构映射到相应的物理设备。
Windows程序设计中所需要的数据是存储在资源文件中的,这样,连接器就可以把编译好的二进制代码和二进制资源文件结合起来生成可执行程序。资源文件可以包括位图、图标、菜单定义、对话框设计,甚至可以包含用户自己定义的格式。
Windows程序允许动态的连接目标模块,并且多个应用程序可以共享同一个动态连接库。
VC++的源程序浏览器能够使我们从类或函数的角度来了解或编辑程序,而不是直接从文件入手。在看别人的源代码时如果能熟练的使用源代码浏览器将会事半功倍。源程序浏览器主要的查看状态有以下几种:
Definitions and References--选择任何函数、变量、类型、宏定义可以看到它在项目中的定义,并且在何处和什么地方用到它。
Call Graph/Caller Graph--对于所选择的函数,给出它的调用与被调用函数的图示。
Derived Class Graph/Base Class Graph--给出类层次关系的图形表示,可以看到所选择的类的派生类和基类以及成员。
File Outline--对于所选的文件,列出文件中的类、函数和数据成员,同时还显示它们定义的位置和使用位置。
可见Source Brower比起Class View来功能多了很多也更加好用。
对于本章学习loose_went建议大家在VC++6中用AppWizard生成一个空的程序,然后试着看看都有哪些文件,和他们的类层次、函数、宏、结构的定义,我就是这样干的,学编程不动手是不行的。
第二天 MFC应用程序框架
?MFC是C++的Microsoft Windows API
?MFC产生的应用程序使用了标准化的结构。
?MFC产生的应用程序短而运行速度快。
?VC++工具降低了编码的复杂性,这当然了,很多代码都由它代劳了,呵呵。
?MFC库应用程序框架的功能非常丰富。
以上说的都是MFC库的优点,虽然说MFC有着这样多的优点,但我个人认为不能盲目的学习它,要想学好,那么您必须先掌握C++,这是毋庸置疑的。可能刚开始的时候,您觉得收获很大,也很有趣,但要进一步提高,没有C++基础是很难的。所以站长建议大家学习的时候要有先有后,这样才能学好!
应用程序框架是一种类库的超集。
我们现在先来看一个例子,看看MFC有多么强大!您只需加一行代码,甚至一行都不用加只需要点几下鼠标就可以创建一个windows 程序,不信,试一下:
1、打开VC++6从菜单选择NEW,给项目命名为"MyApp "。
2、选择MFC AppWizard[exe] 选项,除STEP 1选择单文档外其他STEP缺省。
3、在Class View选择CMyAppView类的OnDraw()成员函数双击会在C++编译器看到以下内容
void CMyAppView::OnDraw(CDC* pDC)
{
CMyAppDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}
在 // TODO: add draw code for native data here的位置增加一行代码
void CMyAppView::OnDraw(CDC* pDC)
{
CMyAppDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
pDC->TextOut(10,10,"愿vc在线能成为您学习vc最好的朋友!"); //增加的一行
// TODO: add draw code for native data here
}
完了,就这么简单。编译运行。看到了吗?这个程序具备WINDOWS程序的所有特性,例如有菜单、工具条、状态栏、最大化、关闭、甚至还有关于对话框、打印预览.....全了,这就是AppWizard通过MFC动态创建的一个应用程序。从这个小例子可以看出用VC/MFC设计WINDOWS程序多么方便。
下面我们看看书上的例子,以便更进一步了解应用程序框架。
1、先建立一个Win32 Application的应用程序。
2、选择Project->Add to project->Files,分别创建一个名为MyApp.h和一个名为MyApp.cpp的文件。
3、添加代码:(最好照敲一下代码到编译器,别用Ctrl+C/Ctrl+V)
//***********************************************
// MyApp.h
//
class CMyApp:public CWinApp
{
public:
virtual BOOL InitInstance();
};
class CMyFrame:public CFrameWnd
{
public:
CMyFrame();
protected:
afx_msg void OnLButtonDown(UINT nFlags,CPoint point);
afx_msg void OnPaint();
DECLARE_MESSAGE_MAP()
};
//*****************************************************
// MyApp.cpp
//
#include "afxwin.h"
#include "myapp.h"
CMyApp theApp;//建立一个CMyAPP对象
BOOL CMyApp::InitInstance ()
{
m_pMainWnd=new CMyFrame();
m_pMainWnd->ShowWindow (m_nCmdShow);
m_pMainWnd->UpdateWindow ();
return TRUE;
}
BEGIN_MESSAGE_MAP(CMyFrame,CFrameWnd)
ON_WM_LBUTTONDOWN()
ON_WM_PAINT()
END_MESSAGE_MAP()
CMyFrame::CMyFrame(){
Create(NULL,"MYAPP Application");
}
void CMyFrame::OnLButtonDown (UINT nFlags,CPoint point)
{
TRACE("Entering CMyFrame::OnLButtonDown - %lx,%d,%d\n",
(long)nFlags,point.x ,point.y);
}
void CMyFrame::OnPaint ()
{
CPaintDC dc(this);
dc.TextOut (0,0,"Hello World!");
}
4、编译运行,报错。为什么呢?原来还没有添加MFC的支持,在Project Setting选项General属性页选择"Use MFC in a Static Library"
5、再按Ctrl+F5,怎么样,简单吧?
让我们看看这个程序中的一些元素。
①WinMain函数:Windows总是要求每个应用程序都要有WinMain函数的,您之所以看不见,是因为它已经隐藏在应用程序框架内部了。
②CMyApp类:CMyApp类的对象代表一个应用程序,CWinApp基类决定它的大部分行为。
③应用程序的启动:当开始运行应用程序时WINDOWS会调用WinMain函数,WinMain会查找该应用程序的全局对象theApp。
④CMyApp::InitInstance成员函数:发现theApp后自动调用重载的虚函数InitInstance来完成主窗口的构造和显示工作。
⑤CWinApp::Run成员函数:WinMain在调用InitInstance之后紧接着调用Run函数,它被隐藏在基类中负责传递应用程序的消息给相映的窗口。
⑥CMyFrame类:此类的对象代表着应用程序的主窗口。它的构造函数调用基类CFrameWnd的Create函数创建具体的窗口结构。
⑦CMyFrame::OnLButtonDown函数:演示消息处理机制,当鼠标坐键被按下这一事件被映射到CMyFrame的OnLButtonDown函数上,如果你选择F5进行编译运行的话可以在调试窗口看到TRACE宏显示的类似下面的信息
Entering CMyFrame::OnLButtonDown - 1,309,119
Entering CMyFrame::OnLButtonDown - 1,408,221
⑧CMyFrame::OnPaint函数:应用程序每次重新绘制窗口都需要调用此函数,将显示"Hello World!"放在这里是因为每次窗口发生变化时保证"Hello World!"被显示,你可以试着将语句:
CPaintDC dc(this);
dc.TextOut (0,0,"Hello World!");
写在别出,例如写在
void CMyFrame::OnLButtonDown (UINT nFlags,CPoint point)
{
TRACE("Entering CMyFrame::OnLButtonDown - %lx,%d,%d\n",
(long)nFlags,point.x ,point.y);
CPaintDC dc(this);
dc.TextOut (0,0,"Hello World!");
}
运行后当点击左键时显示"Hello World!",但当窗口最小化再最大化时"Hello World!"不见了。
⑧关闭应用程序:用户关闭应用程序时会有一系列事件发生。首先CMyFrame对象被删除,然后退出Run,进而退出WinMain,最后删除CMyApp对象。
通过上面的示例我们看见程序的大部分功能包含在基类CWinApp和CFrameWnd中,我们只写了很少的函数,便可以完成很复杂的功能。所以应用程序框架不仅仅是一种类库,它还定义了应用程序的结构,除了基类外还包括WinMain函数,以及用来支持消息处理、诊断、DLL、等都包含在应用程序框架中。
第三天 消息映射和视图类
MFC库应用程序框架没有采用虚函数来处理windows消息,而是通过宏将消息映射到派生类相应的成员函数上。文档-视图结构是应用程序框架的核心,它把数据从用户对数据的观察中分离出来,这样做最大的好处就是同一个数据可以对应多个视图。比如同一个股票报价数据,既可以有报表观察窗口,也可以有图形观察窗口,明白了否?
视图简单来说就是一个普通的窗口,对于程序员来说就是一个从MFC库中Cview类派生出来的类的一个对象。视图类分为两个源文件模块:头文件(H)和源代码文件(CPP)。
用Appwizard创建一个SDI应用程序,产生了如下文件(假设工程名为Exc01):
Exc01.dsp 项目文件,Visual Studio用它来创建应用程序
Exc01.dsw 工作空间文件,包含一个项目Exc01.dsp
Exc01.rc ASCII码资源描述文件
Exc01View.cpp 包含CExc01View类成员函数和视图类文件
Exc01View.h 包含CExc01View类定义的视图类头文件
Exc01.opt 二进制文件,告诉Developer Studio本项目的哪些文件是打开的,又是如何排序的
Readme.txt 用来解释所产生的所有文件的文本文件
Resource.h 包含#define常量定义的头文件
从Exc01View.cpp和Exc01View.h的代码中可以看出,这两个文件已经完全定义了CExc01View类,而该类正是此应用程序的核心。CExc01View类的对象与应用程序的视窗相关联,应用程序的所有"动作"都会在这个视窗中显示出来。
CExc01View类的两个最重要的基类是CWnd和CView类。CWnd类提供了CExc01View的窗口属性,而CView类则提供了它和应用程序框架的其它部分之间的联系,特别是和文档以及框架窗口之间的联系。这一点一定要记住。
下面我们来看一下如何在视窗内绘图。最重要的一个函数是OnDraw()函数,它是一个虚函数,每次窗口被重画时,应用程序都要先调用这个函数。注意:尽管可以随时对窗口绘制,但最好还是等变化内容积累到一定程度后再教给OnDraw()函数处理,这样效率会高一些。
在MFC中,设备环境是由C++的CDC类对象来表示的,该对象被作为参数传给Ondraw()函数,这样,我们就可以调用CDC的许多成员函数来完成各种绘制了。
找到OnDraw()函数,用以下语句替换函数原来的内容:
pDC->TextOut( 0, 0, "Hello World!" );
pDC->Ellipse(CRect(0,20,100,120));
再编译运行,看到了什么?
TextOut和Ellipse都是设备环境类CDC的成员函数,MFC库提供了一个用来表示windows矩形的类CRect,在这里CRect的一个临时对象被作为参数传递给 了Ellipse函数,当外接矩形的宽和高相等时,Ellipse函数就画出个圆。
第四天 资源和编译
资源文件(就是以应用程序名和扩展名是.rc的文件)很大程度上决定了应用程序的用户界面。在VC++中资源文件包括以下内容:
Accelerator //模拟菜单和工具栏选择的键盘定义
Dialog //对话框的布局及内容
Icon //图标有两种一种是16X16一种是32X32。
Menu //应用程序的主菜单及所属的弹出式菜单
String table //一些字符串,不属于C++源代码部分
Toolbar //工具条。
Version //程序的描述、版本号、支持语言信息。
除了以上信息,.rc文件还包含了以下语句: #include "afxres.h" #include "afxres.rc" 它们的作用是把适合于所有应用程序的一些通用MFC库资源包含进来,其中包括字符串、图形按钮以及打印所需的一些元素。
关于资源编辑器的使用就不多说了,因为它的操作很简单,需要注意的是虽然resource.h是一个ASCII码文件可以用文本编辑器进行编辑,但如果使用文本编辑器进行编辑的话,下次再使用资源编辑器时所做的修改有可能丢失,所以我们应该在尽量在资源编辑器中编辑应用程序的资源,新增的资源内容回自动的添加在我们的程序相应位置,例如resource.h而不用我们操心。
编译在VC++中有两种模式,一种是Release Build另一种是Debug Build。它们之间的区别在于,Release Build不对源代码进行调试,不考虑MFC的诊断宏,使用的是MFC Release库,编译十对应用程序的速度进行优化,而Debug Build则正好相反,它允许对源代码进行调试,可以定义和使用MFC的诊断宏,采用MFC Debug库,对速度没有优化。所以我们应该在Debug模式下开发应用程序,然后在Release模式下发布应用程序。在我们的工程文件夹下会有一个Debug文件夹和一个Release文件夹分别存放输出文件和中间文件。
诊断宏是我们编译程序时检测程序状态的有利工具,例如上两篇用到的TRACE宏,可以在Debug窗口获得你需要的诊断信息,而不用设置对话框之类的方法,在发布时Release会自动滤掉此信息。
为了更好的管理项目,最好理解系统是如何处理预编译头文件的。VC++有两个预编译系统:自动的和手工的。这一部分笔者就不多说了,建议读者好好看看。
第五天 基本事件处理
用户在视窗中的任何一个操作,都会引起Windows自动发送一个消息给该视窗。我们以一个例子来说明:比如我们在视窗中按下鼠标左键,Windows就会发送ON_LBUTTONDOWN消息给视窗,那么在视窗类中就必须包含下面的成员函数:
Void CmyView::OnLButtonDown(UINT nFlags, Cpoint point)
{
//event processing code here
}
在类头文件中也要包含相应的函数声明:
afx_msg void OnLButtonDown(UINT nFlags, Cpoint point)
在代码文件中还要有一个消息映射宏,用于将OnLButtonDown函数和应用程序框架联系在一起:
BEGIN_MESSAGE_MAP(CmyView, CView)
ON_WM_LBUTTONDOWN()
// other message map entries
END_MESSAGE_MAP
最后,在类库头文件中包含如下语句:
DECLARE_MESSAGE_MAP()
以上这些步骤,我们都可以借助于ClassWizard来完成。这就是消息映射的过程。
MFC库对140种windows消息直接提供了消息控制函数,并且我们还可以自己定义自己的消息,下面列出的五种消息是我们应该特别注意的(MSDN上有更详细的内容)。
WM_CREATE
该消息是Windows发给视图的第一个消息。当应用程序框架调用create函数时该消息便会被发送,此时窗口还未创建完成,不可见,因此在消息控制函数OnCreate内不能调用那些依赖窗口处于完全激活状态的Windows函数。如果需要可以在重载的OnInitialUpdate函数内调用。不过注意在SDI应用程序OnInitialUpdate函数可能被多次调用。
WM_CLOSE
当用户关闭窗口时,系统会发送WM_CLOSE消息。如果派生类重新定义了OnClose函数,就可以完全控制关闭过程,可以将提醒用户存盘之类的工作放在这里完成。我们可以通过重载CDocument::SaveModified虚函数达到相同的目的。
WM_QUERYENDSESSION
从字面的意思看就可以看出,当用户退出Windows时,或者调用了ExitWindows 函数时。Windows会发送WM_QUERYENDSESSION消息给所有的正在运行的应用程序,由OnQueryEndSession消息映射函数对消息进行处理。在它之后应该是WM_ENDSESSION 消息。
WM_DESTROY
在Windows发送WM_CLOSE消息后,紧接着会发送WM_DESTROY消息,虽然窗口已经Close但实际上并没有完全清除,在任务管理器中还可以看见应用程序的进程(我想很多木马或病毒都是无窗口的程序,它们的做法是生成了已经活动状态的窗口但不显示出来),利用这个消息控制函数便可以对依赖于当前窗口存在的东西做清除工作,不过一定要注意,应该调用基类的OnDestroy函数,而不能在用户自己的视图的OnDestroy函数中终止窗口的析构过程,终止析构过程应该在OnClose函数中。
WM_NCDESTROY
当窗口被取消所发送的最后一个消息就是这个消息。我们可以在OnNcDestroy函数中做一些不依赖该窗口是否处于活动状态的最后的处理工作,(我实在想不出还需要做什么?那位朋友能给个例子),注意一定要调用基类中的OnNcDestroy函数。
MFC库中非静态数据成员的名字以m_为前缀。
一个窗口具有一个矩形的"客户区域",CWnd中的GetClient成员函数可以给出客户区域的大小,只允许在客户区域内绘图。
标准的windows应用程序会首先登记一个窗口类,这不同于C++类,同时在处理过程中,还需要对每个类指定窗口过程。每次应用程序调用CreateWindow建立一个窗口时,都要指定一个窗口类作为参数,这样就把新建立的窗口和窗口过程函数连接起来了,每次windows给窗口发送消息的时候,这个函数就会被调用,以检查用参数传进来的消息码。
第六天 映射模式
所谓映射模式,说白了就是坐标系。在默认情况下,Windows所绘图像单位为像素,这是因为设备环境用了默认的映射模式MM_TEXT,所以如下语句所绘图形为长和宽都为200像素的方块: pDC->Rectangle(CRect(0,0,200,200));
那么我们要绘制一个长和宽都是4厘米的方块该怎么做呢?这就必须改变设备环境的默认映射模式为MM_HIMETRIC,它的图像单位为1/100mm,而不是像素了。它的y轴方向和MM_TEXT的相反,它的向下为递减的,因此用如下语句就可以绘出4×4cm的方块了:
pDC->SetMapMode( MM_HIMETRIC);
pDC->Rectangle(CRect(0,0,4000,-4000));
下面我们再来了解一下Windows都提供了哪些映射模式。
1、MM_TEXT映射模式
这种模式下,绘图单位为像素,x轴向右递增,y轴向下递增,我们可以用CDC的SetViewPortOrg和SetWindowOrg函数来改变坐标原点的位置,下面的代码就是把坐标原点设在了(100,100)处,画了一个200×200像素的方块,此时逻辑坐标点(100,100)被映射到了设备坐标点(0,0)处,下一篇的滚动窗口使用的就是这种变换。
Void CmyView::OnDraw( CDC *pDC ){
pDC->SetMapMode(MM_TEXT);
pDC->SetWindowOrg(Cpoint(100,100));
pDC->Rectangle(CRect(100,100,200,200));
}
2、固定比例映射模式
Windows提供了一组非常重要的固定比例影视模式,所有这种模式都遵循x轴向右递减,y轴向下递减的规则,而且我们无法将其改变。固定比例模式之间唯一的差别就在于实际的比例因子。下表列出了影视模式和比例因子的对应情况:
映射模式 |
逻辑单位 |
MM_LOENGLISH |
0.01英寸 |
MM_HIENGLISH |
0.001英寸 |
MM_LOMETRIC |
0.1mm |
MM_HIMETRIC |
0.01mm |
MM_TWIPS |
1/1440英寸 |
MM_TWIPS模式常用于打印机。
3、可变比例映射模式
Windows还提供了两种映射模式MM_ISOTROPIC和MM_ANISOTROPIC,这两种模式允许我们修改比例因子和坐标原点。在MM_ISOTROPIC模式下,纵横比总是1:1,就像改变图像时锁定比例一样,而MM_ANISOTROPIC模式则可以独立的改变x和y的比例因子,即圆可以变成扁圆。
以上就是常见的映射模式,笔者建议:我们没必要死记住这些模式,只是到用的时候会用就可以了,哪怕查查MSDN,这个东东真好!
在设置了映射模式和相应参数之后,我们可以用CDC的LPtoDP函数将逻辑坐标转换为设备坐标,用DptoLP函数将设备坐标转换为逻辑坐标。那么我们什么时候用什么样的坐标呢?有一些规则如下:
① 可以认为CDC的所有成员函数都以逻辑坐标为参数
② 可以认为CWnd的所有成员函数都以设备坐标为参数
③ 所有选中测试都应该选用设备坐标,区域的定义应采用设备坐标,某些像CRect::PtInRect之类的函数只有采用设备坐标才能有正确的结果
④ 将一些长期使用的值用逻辑坐标来保存,如果用设备坐标,那么只要用户对窗口进行一下滚动,坐标就不再有效了
一般情况下,我们在CView的虚函数OnPrepareDC中设置映射模式,应用程序框架在调用OnDraw函数之前调用这个虚函数。
第七天 滚动视窗
CView类并不直接支持窗口滚动,如要实现窗口滚动,就要用到CView的派生类CScrollView类,CScrollView的成员函数能够处理滚动条并发送给视图WM_HSCROLL和WM_VSCROLL消息,从而实现窗口的滚动。
在文档-视图结构中,视图窗口建立以后,框架最先调用OnInitialUpdate虚函数,在框架第一次调用OnDraw函数前也是先调用OnInitialUpdate函数,因此在OnInitialUpdate函数中设置滚动视窗的初始化最合适。
下面我们就来创建一个滚动示例程序a:
1、 用AppWizard创建一个文档-视图程序a,注意在第六步时设置CAView的基类应为CScrollView而不是CView。
2、 在CAView中加入数据成员m_rectEllipse和m_nColor。
3、 修改OnInitialUpdate函数如下:
void CAView::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();
CSize sizeTotal( 20000, 30000 ); //逻辑窗口大小20×30cm
CSize sizePage( sizeTotal.cx/2, sizeTotal.cy/2 );
CSize sizeLine( sizeTotal.cx/50, sizeTotal.cy/50 );
SetScrollSizes( MM_HIMETRIC, sizeTotal, sizePage, sizeLine );
}
4、 用ClassWizard产生对消息WM_KEYDOW控制的OnKeyDown函数,并编辑代码如下:
void CAView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
switch( cChar ){
case VK_HOME:
OnVScroll( SB_TOP, 0, NULL );
OnHScroll( SB_LEFT, 0, NULL );
break;
case VK_END:
OnVScroll( SB_BOTTOM, 0, NULL );
OnHScroll( SB_RIGHT, 0, NULL );
break;
case VK_UP:
OnVScroll( SB_LINEUP, 0, NULL );
break;
case VK_DOWN:
OnVScroll( SB_LINEDOWN, 0, NULL );
break;
case VK_PRIOR:
OnVScroll( SB_PAGEUP, 0, NULL );
break;
case VK_NEXT:
OnVScroll( SB_PAGEDOWN, 0, NULL );
break;
case VK_LEFT:
OnHScroll( SB_LINELEFT, 0, NULL );
break;
case VK_RIGHT( SB_LINERIGHT, 0, NULL );
break;
default:
break;
}
}
5、 编辑构造函数和OnDraw函数如下:
CAView::CAView():m_rectEllipse( 0, 0, 4000, -4000 )
{
// TODO: add construction code here
m_nColor = GRAY_BRUSH;
}
…
void CAView::OnDraw(CDC* pDC)
{
pDC->SelectStockObject( m_nColor );
pDC->Ellipse( m_rectEllipse );
}
6、 映射WM_LBUTTONDOWN消息并编辑消息处理函数OnLButtonDown如下:
void CAView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CClientDC dc( this );
OnPrepareDC( &dc );
CRect rectDevice = m_rectEllipse;
dc.LPtoDP( rectDevice );
if( rectDevice.PtInRect( point ) ){
if( m_nColor = GRAY_BRUSH )
m_nColor = WHITE_BRUSH;
else
m_nColor = GRAY_BRUSH;
}
InvalidateRect( rectDevice );
}
编译并运行看看结果吧。
另外,我们要特别注意下面五种比较特殊的windows消息:
1、 WM_CREATE消息
该消息是windows发给视图的第一个消息,由于应用程序框架调用Create函数时该消息就会被发送,而此时窗口创建还未完成,因此在Create函数内不能调用那些依赖于窗口处于完全激活状态的windows函数。不过对于SDI应用程序,在视图生存期间,OnInitialUpdate函数可以被调用多次。
2、 WM_CLOSE消息
当用户从系统菜单中关闭窗口或者父窗口被关闭时,windows会发送WM_CLOSE消息。
3、 WM_QUERYENDSESSION消息
当用户退出windows时,windows就会发送WM_QUERYENDSESSION消息给正在运行的程序,处理这个消息的映射函数为OnQueryEndSession。
4、 WM_DESTROY消息
Windows在发送完WM_CLOSE消息后,紧接着就发送WM_DESTROY消息,消息映射函数为OnDestroy。当程序接收到该消息时,它将假定此时视窗已经消失,但仍处于活动状态。利用这个消息控制函数,就可以对依赖于当前窗口的所有东西作清除工作,不过一定要记住,应该用基类的OnDestroy而不能在自己视图中的OnDestroy中"终止"窗口的析构过程,终止析构的处理应该在OnClose函数中。
5、 WM_NCDESTROY消息
当窗口被取消时发送的最后一个消息就是这个消息,由于此时所有的窗口都被关闭,所以我们可以在OnNcDestroy函数中做一些不依赖于窗口是否处于激活状态的最后处理工作,不过一定要调用基类的OnNcDestroy函数。不要在OnNcDestroy中取消动态申请的窗口对象,这一工作是由CWnd的一个特殊虚函数PostNcDestroy来完成的,它是由基类的OnNcDestroy来调用的。何时取消窗口对象最为合适呢,去看MFC的联机文档吧!
第八天 设备环境类
任何程序在画图时都需要调用图形设备接口( GDI )函数, GDI 包含了一些绘制点、线、矩形、椭圆、位图以及文本的函数。 Windows 的设备环境是 GDI 的关键元素,它代表了物理设备,每一个 C++ 设备环境对象都有与之对应的 Windows 设备环境,并通过一个 32 位的 HDC 句柄来标识。
MFC 中的基类 CDC 包含了绘图所需要的所有成员函数,并且除了 CMetaFileDC 类外,所有的派生类都只有构造函数和析构函数不同。对于显示器来说,常用的派生类有 CClientDC 和 CWindowDC 。
显示设备环境的类 CClientDC 和 CWindowDC , CClientDC 类绘图只局限于客户区域内,即不包含边框、菜单栏和标题栏,而 CWindowDC 类可以。简单来说,如果创建 CclientDC 对象,点( 0,0 )指客户区域的左上角,如果创建的是 CWindowDC 对象,则点( 0,0 )指整个屏幕的左上角。
在创建 CDC 对象的时候,不要忘记在合适的时候将它删除,不然程序在退出之前有小部分内存就会丢失。要保证设备环境对象能够被适时的删除,可以有两种方法:
一种是在堆栈中构造对象,比如在 OnLButtonDown 函数中,它的析构函数在函数返回时自动被调用。
void CMyView::OnLButtonDown(UINT nFlags,CPoint point){
CRect rect;
CClientDC dc(this); //constructs dc on the stack
…
} //dc automatically destroyed
另一种是通过调用 CWnd 的成员函数 GetDC 来获得设备环境指针,但此时必须要调用 RleaseDC 来释放设备环境。
void CMyView::OnLButtonDown(UINT nFlags,CPoint point){
CRect rect;
CDC *pDC=GetDC();
pDC->GetClipBox(rect);
ReleaseDC(pDC); // 不要忘了这句
}
注意:千万不要删除作为参数以指针形式传递给 OnDraw 函数的 CDC 对象,应用程序框架会自动控制它的删除。
在绘图时我们离不开设备环境,那么在绘图时我们就要依赖于设备环境的当前状态,这种状态包括:
• 被选中的 GDI 绘图对象,如笔、刷子和字体等
• 绘图时的缩放尺寸的映射模式
• 其他各种细节,如文本的对齐方式,多边形的填充状态
创建设备环境对象时,通常会有些默认的特性,而其他特性都是通过 CDC 类的成员函数来设定的,可以通过重载 SelectObject 函数来将 GDI 对象选进设备环境中。
如果我们要重新编写 OnPaint 函数,就需要使用 CPaintDC 类,这个类是比较特殊的,它的构造函数和析构函数所完成的工作都是针对显示用的,当我们一旦获得一个 CDC 指针,就可以把它当成任何设备环境指针来用。
第九天 GDI对象
所有 GDI 对象类都是由抽象基类 CGdiObject 派生出来的。下面是 GDI 派生类列表:
CBitmap - 位图是一种位矩阵,每一个显示像素都对应一个或多个位,我们可以用位图来表示图像,也可以用它来创建刷子。
CBrush - 刷子定义了一种位图形式的像素,用它可以对区域内部填充颜色。
CFont - 字体是一种具有某种风格和尺寸的所有字符的集合。
CPalette - 调色板是一种颜色映射接口。
CPen - 笔是一种画线和有形边框的工具,可以指定画线的宽度,以及画虚线,实线等。
CRgn - 区域是一种范围,可以用它来填充、裁剪以及鼠标点中测试。
我们只需要构造 CGdiObject 类的派生类对象,而无需构造它的对象,有些 GDI 派生类允许构造函数一步完成创建对象的任务,如 CPen 和 CBrush 。而有些派生类的对象要两步,如 CFont 和 CRgn ,首先要调用默认的构造函数,然后还要调用相应的创建函数,如 CreateFont 、 CreatePolygonRgn 等。
CGdiObject 类有一个虚析构函数,如果构造了一个它的派生类的对象,则在程序退出之前要将其删除,为了删除它,要先将其从设备环境中分离出来。那么如何分离呢?其实, CDC 类的 SelectObject 成员函数在将 GDI 对象选进设备环境的同时,它已经从设备环境中分离出来了,但在未选中新的对象前,还不能将旧的对象分离。所以在选进自己的 GDI 对象时,将原来的 GDI 对象也保存起来,任务完成后,再将其恢复,这样就可以将自己的 GDI 对象分离并删除了。下面看一个例子:
void CMyView::OnDraw( CDC *pDC ){
CPen newPen( PS_DASHDOTDOT, 2, (COLORREF)0); //black 2 pixels wide
CPen * pOldPen = pDC->SelectObject( &newPen );
pDC->MoveTo( 10, 10 );
pDC->LineTo( 110, 10 );
pDC->SelectObject( pOldPen ); //newPen 被分离
} //newPen 在函数退出时自动删除
对于一些库存的 GDI 对象,由于它们是 windows 系统的一部分,因此我没有必要删除它们。 MFC 库函数 SelectStockObject 可以将一个库存对象选进设备环境中,并返回原先被选中对象的指针,同时使该对象被分离。在上例中,我们就可以用库存对象代替“旧”对象:
void CMyView::OnDraw( CDC *pDC ){
CPen newPen( PS_DASHDOTDOT, 2, (COLORREF)0); //black 2 pixels wide
pDC->MoveTo( 10, 10 );
pDC->LineTo( 110, 10 );
pDC->SelectStockObject( BLACK_PEN ); //newPen 被分离
} //newPen 在函数退出时自动删除
对于显示设备环境来说,在每个消息控制函数的入口处,设备环境都是未被初始化的,因此每次都必须从头开始设置设备环境,由于 SelectObject 返回的 GDI 对象指针的临时性,而应用程序框架在函数返回时会删除 C++ 临时对象指针,所以不能简单地将设备环境指针保存在类的数据成员中,而要借助于 GetSafeHandle 成员函数来将它转换为 windows 句柄(唯一能够持久存在的 GDI 标识)。
注意,当删除由 SelectObject 返回的指针所指向的对象时,一定要当心,如果该对象是我们自己申请的,可以删除,如果是临时的,则不能随便删除。 |
摘要: (1) 如何通过代码获得应用程序主窗口的 指针?
主窗口的 指针保存在CWinThread::m_pMainWnd中,调用AfxGetMainWnd实现。
AfxGetMainWnd() ->ShowWindow(SW_SHOWMAXMIZED)
//使程序最大化.
... 阅读全文
中国绝美情诗名句排行榜TOP100
1 柳永 凤栖梧 衣带渐宽终不悔,为伊消得人憔悴。
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 佚名 绸缪《诗经.唐风》 今夕何夕,见此良人。
32 白居易 长恨歌 天长地久有时尽,此恨绵绵无绝期。
33 白居易 长恨歌 在天愿作比翼鸟,在地愿为连理枝。
34 文廷式 蝶恋花 重叠泪痕缄锦字,人生只有情难死。
35 曹雪芹 枉凝眉 一个是阆苑仙葩,一个是美玉无瑕。若说没奇缘,今生偏又遇著他;若说有奇缘,如何心事终虚话?
36 李商隐 无题 春蚕到死丝方尽,蜡炬成灰泪始乾。
37 况周颐 减字浣溪沙 他生莫作有情痴,人间无地著相思。
38 欧阳修 玉楼春 尊前拟把归期说,未语春容先惨咽。
39 佚名 关雎《诗经.周南》 关关雎鸠,在河之洲。窈宨淑女,君子好逑。
40 欧阳修 玉楼春 人生自是有情痴,此恨不关风与月。
41 柳永 雨霖铃 此去经年,应是良辰好景虚设。便纵有,千种风情,更与何人说。
42 李之仪 卜算子 只愿君心似我心,定不负相思意。
43 晏几道 临江仙二首其二 落花人独立,微雨燕双飞。
44 陈陶 陇西行 可怜无定河边骨,犹是春闺梦裏人。
45 辛弃疾 摸鱼儿 千金纵买相如赋,脉脉此情谁诉。
46 温庭筠 更漏子三首其三 梧桐树,三更雨,不道离情正苦。一叶叶,一声声,空阶滴到明。
47 苏武 结发为夫妻 结发为夫妻,恩爱两不疑。
48 聂胜琼 鹧鸪天 寻好梦,梦难成。况谁知我此时情。枕前泪共帘前雨,隔箇窗儿滴到明。
49 柳永 昼夜乐 一场寂寞凭谁诉。算前言,总轻负。
50 李白 长相思二首其一 天长路远魂飞苦,梦魂不到关山难,长相思,摧心肝。
51 席慕蓉 印记 不要因为也许会改变,就不肯说那句美丽的誓言,不要因为也许会分离,就不敢求一次倾心的相遇。
52 范成大 车遥遥篇 愿我如星君如月,夜夜流光相皎洁。
53 戴叔伦 相思曲 鱼沈雁杳天涯路,始信人间别离苦。
54 柳永 雨霖铃 执手相看泪眼,竟无语凝噎。
55 元稹 遣悲怀三首其二 诚知此恨人人有,贫贱夫妻百事哀。
56 顾敻 诉衷情 换我心,为你心,始知相忆深。
57 鱼玄机 江陵愁望有寄 忆君心似西江水,日夜东流无歇时。
58 李商隐 无题六首其六 春心莫共花争发,一寸相思一寸灰。
59 乐婉 卜算子 相思似海深,旧事如天远。
60 白居易 浪淘沙 相恨不如潮有信,相思始觉海非深。
61 温庭筠 新添声杨柳枝 玲珑骰子安红豆,入骨相思知不知?
62 邵瑞彭 蝶恋花 忍把千金酬一笑?毕竟相思,不似相逢好。
63 晏殊 玉楼春 天涯地角有穷时,只有相思无尽处。
64 曹雪芹 终身误 都道是金玉良缘,俺只念木石前盟。空对著,山中高士晶莹雪;终不忘,世外仙姝寂寞林。
65 周邦彦 玉楼春 人如风後入江云,情似雨馀黏地絮。
66 曹雪芹 红豆词 滴不尽相思血泪抛红豆,开不完春柳春花满画楼。
67 欧阳修 蝶恋花二首其一 泪眼问花花不语,乱红飞过秋千去。
68 冯小青 怨 瘦影自怜秋水照,卿须怜我我怜卿。
69 朱彝尊 高阳台 锺情怕到相思路。盼长堤,草尽红心。动愁吟,碧落黄泉,两处难寻。
70 贺铸 横塘路 若问闲情都几许?一川烟草,满城风絮,梅子黄时雨。
71 张泌 寄人 多情只有春庭月,犹为离人照落花。
72 刘禹锡 竹枝词四首其二 花红易衰似郎意,水流无限似侬愁。
73 晏殊 山亭柳:赠歌者 若有知音见采,不辞遍唱阳春。
74 范仲淹 苏幕遮 明月楼高休独倚,酒入愁肠,化作相思泪。
75 陈叔达 自君之出矣 思君如明烛,煎心且衔泪。
76 苏武 结发为夫妻 生当复来归,死当长相思。
77 陈蓬姐 寄外二首其二 休言半纸无多重,万斛离愁尽耐担。
78 朱彝尊 鸳鸯湖棹歌 妾似胥山长在眼,郎如石佛本无心。
79 韦庄 女冠子二首其一 不知魂已断,空有梦相随。除却天边月,没人知。
80 佚名 涉江采芙蓉《古诗十九首》 同心而离居,忧伤以终老。
81 秦观 八六子 夜月一帘幽梦,春风十里柔情。
82 晏几道 鹧鸪天三首其一 从别後,忆相逢,几回魂梦与君同。
83 柳永 雨霖铃 多情自古伤离别。更那堪,冷落清秋节。
84 晏殊 玉楼春 无情不似多情苦,一寸还成千万缕。
85 元稹 遣悲怀三首其三 唯将终夜长开眼,报答平生未展眉。
86 韦庄 应天长 别来半岁音书绝,一寸离肠千万结。
87 卢仝 有所思 相思一夜梅花发,忽到窗前疑是君。
88 卢仝 楼上女儿曲 直缘感君恩爱一回顾,使我双泪长珊珊。
89 晏几道 鹧鸪天三首其二 相思本是无凭语,莫向花牋费泪行。
90 欧阳修 踏莎行 离愁渐远渐无穷,迢迢不断如春水。
91 辛弃疾 鹧鸪天 若教眼底无离恨,不信人间有白头。
92 曹雪芹 红楼梦引子 开辟鸿蒙,谁为情种?都只为风月情浓。
93 晏殊 鹊踏枝 明月不谙离恨苦,斜光到晓穿朱户。
94 白居易 长恨歌 临别殷勤重寄词,词中有誓两心知。
95 陈端生 寄外 泪纵能乾终有迹,语多难寄反无词。
96 苏曼殊 本事诗 还卿一钵无情泪,恨不相逢未剃时。
97 温庭筠 南歌子四首其二 终日两相思,为君憔悴尽,百花时。
98 晏殊 鹊踏枝 欲寄彩笺兼尺素,山长水阔知何处。
99 李煜 清平乐 离恨却如春草,更行更远还生。
100 晏殊 清平乐二首其二 鸿雁在云鱼在水,惆怅此情难寄。
马云:阿里巴巴为什么能够赚大钱?
*孙正义跟我有同一个观点,一个方案是一流的Idea加三流的实施;另外一个方案,一流的实施,三流的Idea,哪个好?我们俩同时选择一流的实施,三流的Idea。
*如何把每一个人的才华真正地发挥作用,我们这就像拉车,如果有的人往这儿拉,有的人往那儿拉,互相之间自己给自己先乱掉了。当你有一个傻瓜时,很傻的,你很会很痛苦;你有50个傻瓜是最幸福的,吃饭、睡觉、上厕所排着队去的;你有一个聪明人时很带劲,你有50个聪明人实际上是最痛苦的,谁都不服谁。我在公司里的作用就象水泥,把许多优秀的人才粘合起来,使他们力气往一个地方使。
*网络公司将来要判断两个:第一它的team;第二,它有technology;第三它的concept,拥有这些东西,才是存在的必要。
*Judge一个人,一个公司是不是优秀,不要看他是不是Harvard,是不是Stanford.不要judge里面有多少名牌大学毕业生,而要judge这帮人干活是不是发疯一样干,看他每天下班是不是笑眯眯回家。
*30%的人永远不可能相信你。不要让你的同事为你干活,要让我们的同事为我们的目标干活,共同努力,团结在一个共同的目标下面,就要比团结在你一个企业家底下容易的多。所以首先要说服大家认同共同的理想,而不是让大家来为你干活。
*我认为,员工第一,客户第二。没有他们,就没有这个网站。也只有他们开心了,我们的客户才会开心。而客户们那些鼓励的言语,鼓励的话,又会让他们像发疯一样去工作,这也使得我们的网站不断地发展。
*看见10只兔子,你到底抓哪一只?有些人一会儿抓这个兔子,一会儿抓那个兔子,最后可能一只也抓不住。CEO的主要任务不是寻找机会而是对机会说NO。机会太多,只能抓一个。我只能抓一只兔子,抓多了,什么都会丢掉。
*我们公司是每半年一次评估,评下来,虽然你的工作很努力,也很出色,但你就是最后一个,非常对不起,你就得离开。在两个人和两百人之间,我只能选择对两个人残酷。
*您能用一句话概括您认为员工应该具备的基本素质吗?今天阿里巴巴的员工我们要求诚信,学习能力,乐观精神,和拥抱变化的态度!
*互联网是四乘一百米接力赛,你再厉害,只能跑一棒,应该把机会给年轻人。
*在前一百米的冲刺中,谁都不是对手,是因为跑的三千米的长跑。你跑着跑着,跑了四五百米后才能拉开距离的。
*我们花了两年的时间打地基,我们要盖什么样的楼,图纸没有公布过,但有些人已经在评论我们的房子怎么不好。有些公司的房子很好看,但地基不稳,一有大风就倒了。
*我们与竞争对手最大的区别就是我们知道他们要做什么,而他们不知道我们想做什么。我们想做什么,没有必要让所有人知道。
*网络上面就一句话,光脚的永远不怕穿鞋的。
*今天要在网上发财,概率并不是很大,但今天的网络,可以为大家省下很多成本。这个世界没有人能替你发财,只有你自己才能替你发财,你需要的是投资和投入,spend time,invest time,on the internet,把自己的时间投资在网络上面,网络一定会给大家省钱,但不一定今天就能赚多少钱,赚钱是明天的事,省钱,你今天就看得到。
*电子商务最大的受益者应该是商人,我们该赚钱因为我们提供工具,但让我们做工具的人发了大财,而使用工具的人还糊里糊涂,这是不正常的。所谓新经济,就是传统企业利用好网络这个工具,去创造出更大的经济效益,使其成几十倍地增长,这才是真的新经济的到来。今天新旧经济是两张皮。
*互联网上失败一定是自己造成的,要不就是脑子发热,要不就是脑子不热,太冷了。
*我觉得网络公司一定会犯错误,而且必须犯错误,网络公司最大的错误就是停在原地不动,最大的错误就是不犯错误。关键在于总结我们反思各种各样的错误,为明天跑的更好,错误还得犯,关键是不要犯同样的错误。
*我们是教人钓鱼,而不是给人鱼。
*企业家是在现在的环境,改善这个环境,光投诉,光抱怨有什么用呢?国家现在要处理的事情太多了,失败只能怪你自己,要么大家都失败,现在有人成功了,而你失败了,就只能怪自己。就是一句话,哪怕你运气不好,也是你不对。
*中国电子商务的人必须要站起来走路,而不是老是手拉手,老是手拉着手要完蛋。
*我们知道当时可以敲几个锣,就可以围那么多人的时候,锣都敲得好,把戏还能不好?敲锣都敲出花来了。
*我是说阿里巴巴发现了金矿,那我们绝对不自己去挖,我们希望别人去挖,他挖了金矿给我一块就可以了。
*我深信不疑我们的模式会赚钱的,亚马逊是世界上最长的河,8848是世界上最高的山,阿里巴巴是世界上最富有的宝藏。一个好的企业靠输血是活不久的,关键是自己造血。
*我们说上市就像我们的加油站,不要到了加油站,就停下来不走,还得走,继续走。
*互联网是影响人类未来生活30年的3000米长跑,你必须跑得像兔子一样快,又要像乌龟一样耐跑。
*我为什么能活下来?第一是由于我没有钱,第二是我对INTERNET一点不懂,第三是我想得像傻瓜一样。
*发令枪一响,你是没时间看你的对手是怎么跑的。只有明天是我们的竞争对手。
*如果早起的那只鸟没有吃到虫子,那就会被别的鸟吃掉。
*If not now,when?If not me,who?
*互联网像一杯啤酒,有沫的时候最好喝。
*听说过捕龙虾富的,没听说过捕鲸富的。
*我们不能企求于灵感。灵感说来就来,就像段誉的六脉神剑一样。
*阿里巴巴的六脉神剑就是阿里巴巴的价值观:诚信、敬业、激情、拥抱变化、团队合作、客户第一。
*我永远相信只要永不放弃,我们还是有机会的。最后,我们还是坚信一点,这世界上只要有梦想,只要不断努力,只要不断学习,不管你长得如何,不管是这样,还是那样,男人的长相往往和他的的才华成反比。今天很残酷,明天更残酷,后天很美好,但绝对大部分是死在明天晚上,所以每个人不要放弃今天。
*男人的长相往往和他的的才华成反比。
*在我看来有三种人,生意人:创造钱;商人:有所为,有所不为。企业家:为社会承担责任。企业家应该为社会创造环境。企业家必须要有创新的精神。
*三年以前我送一个同事去读MBA,我跟他说,如果毕业以后你忘了所学的东西,那你已经毕业了。如果你天天还想着所学的东西,那你就还没有毕业。学习MBA的知识,但要跳出MBA的局限。
*对所有创业者来说,永远告诉自己一句话:从创业得第一天起,你每天要面对的是困难和失败,而不是成功。我最困难的时候还没有到,但有一天一定会到。困难不是不能躲避,不能让别人替你去抗。九年创业的经验告诉我,任何困难都必须你自己去面对。创业者就是面对困难。
*ebay是大海里的鲨鱼,淘宝则是长江里的鳄鱼,鳄鱼在大海里与鲨鱼搏斗,结果可想而知,我们要把鲨鱼引到长江里来。
*一个公司在两种情况下最容易犯错误,第一是有太多的钱的时候,第二是面对太多的机会,一个CEO看到的不应该是机会,因为机会无处不在,一个CEO更应该看到灾难,并把灾难扼杀在摇篮里。
*淘宝网的主业决不该放在与对手的竞争上,而是把眼睛盯在提升客户体验上。
*上世纪80年代挣钱靠勇气,90年代靠关系,现在必须靠知识能力!(我好像很早也这么说过)
*三年前的马云谈到B2C和C2C的时候丝毫不心动,在论坛上还试图说服8848创始人王峻涛、谭智相信B2C和C2C没有前途。互联网似乎和马云开了一个玩笑,让他去做自己原先最不看好的事情。不是我不明白,这世界变化快,马云发出了这样的感叹,主要是形势的变化太快了,我只能与时俱进。既然B2B在中国能够成功,我想在大环境改变的形势下再试试C2C,对于新进入的C2C领域,马云这样解释。在全球范围内,基于个人网上交易服务的模式已经成为互联网产业最为重要的领域,美国的亚马逊、Ebay,日本雅虎均在行业内具有举足轻重的地位,以中国上网人口的庞大基数,中国也应该有可能造就一个巨大的个人网上交易市场,马云进入角色似乎很快,经过半年多的考察,他对C2C的前景很是看好。
*马云丝毫不避讳拿淘宝网和易趣对比,一口价、拍卖、买卖街这些模式我们都会采用,当然也会采用易趣开始运行的免费策略,时机合适的时候我们会收费,很可能是三年之后。
*如果我马云能够创业成功,那么我相信中国80%的年轻人都能创业成功。
*一个企业为什么而生存?使命!这一点我很自信。
*互联网是影响人类未来生活30年的3000米长跑,你必须跑得像兔子一样快,又要像乌龟一样耐跑。
*我告诉新员工,如果认为我们是疯子请离开,如果你专等上市请你离开,我们要用80年做企业。
*我们必须在别人改变之前先改变自己。
*电子商务和电视机的区别还是很大,因为电子商务是一个手段,怎么把它用好是一个技能,不是说用遥控器就可以了。
*我自己也喜欢免费的东西,但免费的东西往往是最贵的。如果一个女孩跟你好,她又不想嫁给你,麻烦就大了。与其花这点时间去浪费,不如花一点时间去真正成长。
*我当年学英语,我没有想到后来英文帮了我的大忙。所以,做任何事情只要你喜欢,只要你认为对的,就可以去做。如果你思考问题功利性很强的话,肯定会遇到麻烦的。
*我们一起创建的是团队的文化,而不是抱怨的文化。
*我们必须学会尊重和理解别人。很多时候发现我们缺的不是钙,而是爱!!!
*每个人都应学会认真做事,大度做人。
*中国企业都有一个从少林小子到太极宗师的过程。少林小子都会打几下,太极宗师有章有法,有阴有阳,中国企业要从第一天就有练太极的想法才行。
*我们新来的员工业绩不好,没关系,如果违背我们的价值观去欺骗客户,好,你就一句话都不要讲了。不要你说,我也要死了。
*我们全国各地的公司墙上没有一个贴着价值观的。东西贴在墙上就完了,做不好了。
*这个世界不是因为你能做什么,而是你该做什么.
*创意是企业运营中一个很重要的一环,但它只是一环,不是所有,所以要把每项工作落实到实处.
*建立自我,追求忘我。
*做一份工作,做一份喜欢的工作就是很好的创业。
*不是你的公司在哪里,有时候你的心在哪里,你的眼光在哪里更为重要。
*不想当将军的士兵不是好士兵,但是一个当不好士兵的将军一定不是好将军。
*一个创业者最重要的,也是你最大的财富,就是你的诚信。
*小公司的战略就是两个词:活下来,挣钱
*五年以后还想创业,你再创业
*生存下来的第一个想法是做好,而不是做大。
*创业者书读得不多没关系,就怕不在社会上读书。
*在今天的商场上已经没有秘密了,秘密不是你的核心竞争力
*很多人失败的原因不是钱太少,而是钱太多。
*概念到今天这个时代已经不能卖钱了。
*创业者光有激情和创新是不够的,它需要很好的体系,制度,团队以及良好的盈利模式。
*你的项目感觉是一个生意,不是一个独特的企业。
*赚钱模式越来越多说明你没有模式
*最优秀的模式往往是最简单的东西。
*建一个公司的时候要考虑有好的价值才卖。如果一开始想到卖,你的路可能就走偏掉。
*人要有专注的东西,人一辈子走下去挑战会更多,你天天换,我就怕了你。
*一个领导者首先是做正确的事,其次才是正确地做事,这个顺序不能颠倒。一个人要想办法让自己快乐,让团队快乐。每个组织成员都要有清晰的角色定位,所有人都认为你有问题,你就一定有问题。
*愚蠢的人用嘴讲话,聪明的人用脑子讲话,智慧的人用心讲话或者说用行动讲话。能反映一个人本质的是那些小动作,小动作太多就会让人不信任。
*在一个商业组织里,有业绩而无价值观的是野狗,要杀掉;没有业绩有价值观的是小白兔,也一样要杀掉。
*只为失败的结果而遗憾,不为失败的原因去遗憾,那将是遗憾中的遗憾。
*成功就是将平凡的事情做到不平凡。要为成功找方法,不要为失败找理由。
*战略中最重要的部分是组织目标,没有清晰明确目标的团队就是一群无头苍蝇。战略是什么,战略就是重点突破!
*暴露自己的弱点并不可怕,弱点是藏不住的。
*其实最聪明的人永远相信别人比自己聪明,聪明的人是智慧的天敌,你自认为很聪明的人,很难成为智者。
*战略没有细节就等于一堆废纸
*领导力在顺境的时候,每个人都能出来;只有在逆境的时候,才是真正的领导力。
*永远要把对手想得非常强大,哪怕他非常弱小,你也要把他想得非常强大。
*对待你的商业对手犯错误经常会出现是:看不见,看不起,看不懂,跟不上。
*商业社会其实是个很复杂的社会,能够让自己把握起来就是诚信。因为诚信所以简单。越复杂的东西,越要讲究诚信。
* 企业家、商人和生意人有什么样的区别?生意人唯利是图、有钱就赚;商人有所为、有所不为;而企业家必须承担社会的责任、创造价值、完善社会。
*诚信是个基石,最基础的东西往往是最难做的。但是谁做好了这个,谁就路可以走得很长、很远。
*商业过程是一门艺术。只有向竞争者学习的人才会进步。
*人要成功一定要有永不放弃的精神,但你学会放弃的时候,你才开始进步。
*短暂的激情是不值钱的;持久的激情才是赚钱的
*对于创业者来说,今天很残酷,明天更残酷,后天很美好,大部分人死在明天晚上,看不到后天的太阳
*创业要找最合适的人,不一定要找最成功的人
* 一种信仰决定一种生活;一种使命承担一份责任
*我们需要雷峰,但不能让雷峰穿补丁的衣服上街去
*男人的智商和长相是成反比的
*免费是世界上最昂贵的东西
*这世界最不可靠的东西就是关系
不过,盖茨成功最重要的品质是专家们所谓的自觉.不管是编写BASIC语言还是管理一家慈善基金会,盖茨都会毫不犹豫地为了自己的激情付出行动.他不断鼓励创新,拒绝停下脚步和满足于过去的成就.他通过全身心投入工作,不断激励自己前进.职业顾问亚历山德拉·莱维特说:“人们应当把盖茨的成功看作是一个人的成功,而不仅仅是一个商人的成功.无可否认,这是给成功下的一个新定义,但如今随着个人与职业之间的界限越来越模糊,这一定义已经变得越来越重要.”以下是专家们找出的决定盖茨成功的七个要素:
1.起步早
盖茨很小的时候就对计算机产生了浓厚的兴趣,并在中学时免修了一些课程,把这些时间用在编程的研究上.职业心理学家汉密尔顿·菲利普斯在写给《福布斯》网站的一封电子邮件中说:“即使在还是个孩子的时候,盖茨就下定决心做一件轰轰烈烈的事,并从中找到乐趣,因此在成年之后,他拥有足够稳定的情绪支撑他的工作,并让他走向成功.”
2.目标明确 坚持到底
盖茨17岁时创办了他的第一家软件公司,而且从一开始,就梦想把它做成行业巨头.职业顾问安德丽娅·凯说:“青年时期,盖茨花了大量的时间实践他的技能并搜寻更多有关他感兴趣的事物的信息:分析问题,验证自己的想法.他是个天才,有着令人难以置信的专注.”
3.理性而不默守陈规
学校并不适合盖茨,他自己也清楚这一点.20岁时,他毅然从哈佛大学辍学,创办了微软.但在你作出有风险的职业选择前,确信你已经考虑过后果.旧金山职业指导马蒂·纳姆克说:“如果从盖茨辍学后取得成功的经历推断有抱负的企业家都应当效仿他,那就大错特错了.一个人需要的是盖茨几个方面的结合,包括哈佛级智商、干劲、掩饰在孩子气魅力之下的无情,以及最重要的运气.”
4.一个好汉三个帮
盖茨的微软团队从一开始就一直跟着他,盖茨对团队的充分信任也给他带来了丰厚的回报.13岁那年,他与微软联合创始人保罗·艾伦相识,而微软 CEO史蒂夫·鲍尔默和他在哈佛大学时就成了好朋友.牢固的私人关系提供了一种超越工作范畴的信任度,而这种信任度保证你的员工将为你最卖力地做事.
5.形象就是一切
盖茨已经成功地完成了从一个叛逆的暴发户到企业领导人再到慈善家的变身,在这一过程中,盖茨也充分认识到公众对自己的评价.职业指导、《New Rules @ Work》一书作者芭芭拉·帕切特说:“随着年龄的增长,他已经能够展现出自己更成熟、更稳重的一面:他的眼镜越来越小,头发越来越顺.现在,他正将自己的形象从企业领导人转变成前辈,所以他肯定能够根据他希望人们怎么看他完成这一转变.”
6.决不自满
尽管38岁时就成了亿万富翁,但盖茨没有停下创新的脚步.那是因为他的目标不仅仅是赚钱.他痴迷于自己的行业,而且热衷于尝试新事物.在选择职业时,确信你对自己要从事的行业真正感兴趣.专家表示,你的成绩永远有待于提高,而钱也会滚滚而来.
7.知自知彼
在整个职业生涯中,从基础的编程到慈善事业,盖茨已通过追求自己的理想取得了成功.他从来不做自己不相信的事.莱维特说:“人们应当把盖茨的成功看作是一个人的成功,而不仅仅是一个商人的成功.无可否认,这是给成功下的一个新定义,但如今随着个人与职业之间的界限越来越模糊,这一定义已经变得越来越重要.”
Z: 100本名著浓缩成了100句话
1.神要是公然去跟人作对,那是任何人都难以对付的。 (《荷马史诗》)
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.现在我说的您要特别注意听:在别人心中存在的人,就是这个人的灵魂。这才是您本身,才是您的意识在一生当中赖以呼吸、营养以至陶醉的东西,这也就是您的灵魂、您的不朽和存在于别人身上的您的生命。(《日瓦戈医生》)
32.美德犹如名香,经燃烧或压榨而其香愈烈,盖幸运最能显露恶德而厄运最能显露美德。(《培根论说文集》)
33.亲爱的艾妮斯,我出国,为了爱你,我留在国外,为了爱你,我回国,也是为了爱你!(《大卫.科波菲尔》)
34.强迫经常使热恋的人更加铁心,而从来不能叫他们回心转意。(《阴谋与爱情》)
35.在各种事物的常理中,爱情是无法改变和阻挡的,因为就本性而言,爱只会自行消亡,任何计谋都难以使它逆转。(《十日谈》)
36.只要你是天鹅蛋,就是生在养鸡场里也没有什么关系。(《安徒生童话》)
37.就投机钻营来说,世故的价值永远是无可比拟的。(《死魂灵》)
38. 谁都可能出个错儿,你在一件事情上越琢磨得多就越容易出错。(《好兵帅克历险记》)
39.我们经历着生活中突然降临的一切,毫无防备,就像演员进入初排。如果生活中的第一次彩排便是生活本身,那生活有什么价值呢?(《生命中不能承受之轻》)
40.他发现了人类行为的一大法则,自己还不知道——那就是,为了要使一个大人或小孩极想干某样事情,只需要设法把那件事情弄得不易到手就行了。(《汤姆.索亚历险记》)
41.对有信仰的人,死是永生之门。(《失乐园》)
42.有一个传说,说的是有那么一只鸟儿,它一生只唱一次,那歌声比世上所有一切生灵的歌声都更加优美动听。(《荆棘鸟》)
43.离开一辈子后,他又回到了自己出生的那片土地上。从小到大,他一直是那个地方的目击者。(《尤利西斯》)
44.同上帝保持联系是一码事,他们都赞同这一点,但让上帝一天二十四小时都待在身边就是另一码事了。(《第二十二条军规》)
45.在甜蜜的梦乡里,人人都是平等的,但是当太阳升起,生存的斗争重新开始时,人与人之间又是多么的不平等。(《总统先生》)
46.开发人类智力的矿藏是少不了要由患难来促成的。(《基度山伯爵》)
47.离你越近的地方,路途越远;最简单的音调,需要最艰苦的练习。(《泰戈尔诗选》)
48.悲伤使人格外敏锐。(《约翰.克里斯朵夫》
49.我在女人跟前经常失败,就是由于我太爱她们了。(《忏悔录》)
50.她睁大一双绝望的眼睛,观看她生活的寂寞。她像沉了船的水手一样,在雾蒙蒙的天边,遥遥寻找白帆的踪影。(《包法利夫人》)
51.我听见美洲在歌唱,我听见各种不同的颂歌。(《草叶集》)
52.倘若你能使你的心时常赞叹日常生活的神妙,你的苦痛的神妙必不减少于你的欢乐,你要承受你心天的季候,如同你常常承受从田野上度过的四时。(《先知》)
53.现在我住在波勒兹别墅,这里找不到一点儿灰尘,也没有一件东西摆得不是地方,除了我们,这里再没有别人,我们死了。(《北回归线》)
54.艳阳高升,原野上的朝露很快便了无痕迹。源氏痛感人生如梦,像朝露一般,愈加万念俱灰。(《源氏物语》)
55.那些普普通通而毫无特色的罪行才真正令人迷惑,就像—个相貌平凡的人最难以让人辨认—样。(《福尔摩斯探案集》)
56.你有一处建在房子里面的小池塘吗?在那个小池塘里,你可以随时观察水中生物生活的每一个片断。(《昆虫记》)
57.不要向井里吐痰,也许你还会来喝井里的水。(《静静的顿河》)
58.我看到了各个民族彼此敌视,而且默默地,无知地、愚蠢地、甘心地、无辜地在互相残杀。我看到了世界上最聪明的头脑还在发明武器和撰写文章,使这种种敌视和残杀更为巧妙,更为经久。(《西线无战事》)
59.这张脸同早晨雪天映在镜子中的那张脸一样,红扑扑的。在岛村看来,这又是介于梦幻同现实之间的另一种颜色。(《雪国》)
60.一个人只要有意志力,就能超越他的环境。(《马丁.伊登》)
61.站在痛苦之外规劝受苦的人,是件很容易的事。(《被缚的普罗米修斯》)
62.感情有理智根本无法理解的理由。(《月亮和六便士》)
63.世界上一切好东西对于我们,除了加以使用外,实在没有别的好处。 (《鲁滨逊漂流记》)
64.每当太阳西沉,我坐在河边破旧的码头上,遥望新泽西上方辽阔的天空,我感到似乎有未经开垦的土地,所有的道路,所有的人都在不可思议地走向西部海岸。直到现在我才知道,在衣阿华,小伙子们总是不停地骚动喧闹,因为是那片土地使他们如此无法平静。(《在路上》)
65。在有法律之前,合乎“自然的”只有狮子的力量,或者动物饥寒时的需要,更简单地用一个字表示,便是“欲”。(《红与黑》)
66。上天让我们习惯各种事物,就是用它来代替幸福。(《叶甫盖尼.奥涅金》)
67.一个人哪怕只生活过一天,也可以毫无困难地在监狱里过上一百年。(《局外人》)
68.往上爬吧,多捞钱吧,进入上层社会,那里准备好了一切。(《美国的悲剧》)
69.念书不能增添智慧。(《痛症楼》)
70.不管我活着,还是我死去,我都是一只牛虻,快乐地飞来飞去。 (《牛虻》)
71.一个人把他整个的一生都押在“女人的爱”那一张牌上头赌博,那张牌输了,他就那样地灰心丧气,弄得自己什么事都不能做,这种人不算一个男人,不过是一个雄性生物。(《父与于》)
72.这个家庭的历史是一架周而复始无法停息的机器,是一个转动着的轮子,这只齿轮,要不是轴会逐渐不可避免地磨损的话,会永远旋转下去。(《百年孤独》)
73.现在我只信,首先我是一个人,跟你一样的一个——至少我要学做一个人。(《玩偶之家》)
74.天才和我们相距仅仅一步。同时代者往往不理解这一步就是千里,后代又盲目相信这千里就是一步。同时代为此而杀了天才,后代又为此而在天才面前焚香。(《侏儒的话》)
75.遭受苦难的人在承受痛楚时并不能觉察到其剧烈的程度,反倒是过后延绵的折磨最能使其撕心裂肺。 (《红字》)
76.人最宝贵的是生命,生命属于人只有一次。人的一生应当这样度过:当他回首往事时,不会因虚度年华而悔恨,也不会因碌碌无为而羞耻。这样,临终前他就可以自豪地说:“我已经把自己整个生命和全部精力都献给了世界上最壮丽的事业——为人类的解放而奋斗。”(《钢铁是怎样炼成的》)
77.凡是有甜美的鸟歌唱的地方,也都有毒蛇嘶嘶地叫。(《德伯家的苔丝》)
78.凡是想依正路达到这深密境界的人应从幼年起,就倾心向往美的形体。(《文艺对话录》)
79.友谊就是一切。友谊比才能更重要,比政府更重要,它和家庭几乎是可划等号的。千万别忘记这一点。({教父》)
80.已经活了七十二岁,依然像是昨天的事:居民点的林阴小路,在歇晌的时间,白人居住区,道旁开满金风花的大街,阗无行人。(《物质生活》)
81.我明天回塔拉再去想吧。巳那时我就经受得住一切了。明天,我会想出一个办法把他弄回来。毕竟,明天又是另外的一天呢。(《飘》)
82.盲目可以增加你的勇气,因为你无法看到危险.(《格列佛游记》)
83.本人系疗养与护理院的居住者。我的护理员在观察我,他几乎每时每刻都监视着我:因为门上有个窥视孔,我的护理员的眼睛是那种棕色的,它不可能看透蓝眼睛的我。(《铁皮鼓》)
84.每当我追溯自己的青春年华时,那些日子就像是暴风雪之晨的白色雪花一样,被疾风吹得离我而去。(《洛莉塔》)
85.宽宏大量,是惟一能够照亮伟大灵魂的光芒。(《巴黎圣母院》)
86.很多年以前,那时我的钱包瘪瘪的,陆地上看来没什么好混的了,干脆下海吧,去在我们这个世界上占绝对面积的大海里逛逛吧! (《白鲸》)
87.我一贯追求的是:在人的肉体与幻想允许的范围内,获得最大限度的真诚和信任,以及对所有的一切尽可能长久的保证。(《镜中微瑕》)
88.这里有一种无处投诉的罪行。这里有一种眼泪不足以象征的悲哀。这里有一种绝大的失败,足以使我们的一切成功都垮台。(《愤怒的葡萄》)
89.起来,饥寒交迫的奴隶!起来,全世界受苦的人! (《国际歌》)
90.我是说孩子们都在狂奔,也不知道自己是在往哪儿跑,我得从什么地方出来,把他们捉住。我整天就干这样的事。我只想当个麦田的守望者。我知道这有点异想天开,可我真正喜欢干的就是这个。(《麦田的守望者》)
91.获取一颗没有被人进攻的经验的心,也就像夺取一座没有守卫的城池一样。(《茶花女》)
92.他不知道那个梦已经丢在他背后了,丢在这个城市那边那一片无垠的混沌之中不知什么地方了,那里合众国的黑黝黝的田野在夜色中向前伸展。(《了不起的盖茨比》)
93.四月最残忍,从死了的土地滋生丁香,混杂着回忆和欲望,让春雨挑动着呆钝的根。(《荒原》)
94.世间的一切虚伪,正像过眼云烟,只有真理才是处世接物的根据。虚伪的黑暗,必为真理的光辉所消灭。(《一千零一夜》)
95.下面玩什么花样呢?(《发条橙》)
96.昨晚,我梦见自己又回到了曼陀丽庄园。(《蝴蝶梦》)
97.我不能想像这样一个人,他认为开棋的时候先走马而不是先走卒对他来说是英勇的壮举,而在象棋指南的某个犄角里占上一席可怜的位置就意味着声名不朽,我不能想像,一个聪明人竟然能够在10年、20年、30年、40年之中一而再、再而三地把他全部的思维能力都献给一种荒诞的事情——想尽一切办法把木头棋子王赶到木板棋盘的角落里,而自己却没有发狂成为疯子。(《象棋的故事》)
98.咱家是猫。名字嘛……还没有。(《我是猫》)
99.挺起英勇的胸脯前进!
看,无数的旗帜满天飞舞!
谁在那里向右转?
向左!
向左!
向左!(《马雅可夫斯基诗选》)
100.水里照出的是自己的脸,内心反映的是自己的为人。(《圣经.旧约》)
SVM相关理论
2007-11-30 12:35
基于数据的机器学习是现代智能技术中的重要方面,研究从观测数据(样本)出发寻找规律,利用这些规律对未来数据或无法观测的数据进行预测。迄今为止,关于机器学习还没有一种被共同接受的理论框架,关于其实现方法大致可以分为三种[3]:
第一种是经典的(参数)统计估计方法。包括模式识别、神经网络等在内,现有机器学习方法共同的重要理论基础之一是统计学。参数方法正是基于传统统计学的,在这种方法中,参数的相关形式是已知的,训练样本用来估计参数的值。这种方法有很大的局限性.
首先,它需要已知样本分布形式,这需要花费很大代价,还有,传统统计学研究的是样本数目趋于无穷大时的渐近理论,现有学习方法也多是基于此假设。但在实际问题中,样本数往往是有限的,因此一些理论上很优秀的学习方法实际中表现却可能不尽人意。
第二种方法是经验非线性方法,如人工神经网络(ANN)。这种方法利用已知样本建立非线性模型,克服了传统参数估计方法的困难。但是,这种方法缺乏一种统一的数学理论。与传统统计学相比,统计学习理论(Statistical Learning Theory或SLT)是一种专门研究小样本情况下机器学习规律的理论。该理论针对小样本统计问题建立了一套新的理论体系,在这种体系下的统计推理规则不仅考虑了对渐近性能的要求,而且追求在现有有限信息的条件下得到最优结果。V. Vapnik等人从六、七十年代开始致力于此方面研究,到九十年代中期,随着其理论的不断发展和成熟,也由于神经网络等学习方法在理论上缺乏实质性进展,统计学习理论开始受到越来越广泛的重视。
统计学习理论的一个核心概念就是VC维(VC Dimension)概念,它是描述函数集或学习机器的复杂性或者说是学习能力(Capacity of the machine)的一个重要指标,在此概念基础上发展出了一系列关于统计学习的一致性(Consistency)、收敛速度、推广性能(Generalization Performance)等的重要结论。
统计学习理论是建立在一套较坚实的理论基础之上的,为解决有限样本学习问题提供了一个统一的框架。它能将很多现有方法纳入其中,有望帮助解决许多原来难以解决的问题(比如神经网络结构选择问题、局部极小点问题等);
同时,这一理论基础上发展了一种新的通用学习方法──支持向量机(Support Vector Machine或SVM),已初步表现出很多优于已有方法的性能。一些学者认为,SLT和SVM正在成为继神经网络研究之后新的研究热点,并将推动机器学习理论和技术有重大的发展。
支持向量机方法是建立在统计学习理论的VC维理论和结构风险最小原理基础上的,根据有限的样本信息在模型的复杂性(即对特定训练样本的学习精度,Accuracy)和学习能力(即无错误地识别任意样本的能力)之间寻求最佳折衷,以期获得最好的推广能力(Generalizatin Ability)。支持向量机方法的几个主要优点有:
1. 它是专门针对有限样本情况的,其目标是得到现有信息下的最优解而不仅仅是样本数趋于无穷大时的最优值;
2. 算法最终将转化成为一个二次型寻优问题,从理论上说,得到的将是全局最优点,解决了在神经网络方法中无法避免的局部极值问题;
3. 算法将实际问题通过非线性变换转换到高维的特征空间(Feature Space),在高维空间中构造线性判别函数来实现原空间中的非线性判别函数,特殊性质能保证机器有较好的推广能力,同时它巧妙地解决了维数问题,其算法复杂度与样本维数无关;
在SVM方法中,只要定义不同的内积函数,就可以实现多项式逼近、贝叶斯分类器、径向基函数(Radial Basic Function或RBF)方法、多层感知器网络等许多现有学习算法。
统计学习理论从七十年代末诞生,到九十年代之前都处在初级研究和理论准备阶段,近几年才逐渐得到重视,其本身也趋向完善,并产生了支持向量机这一将这种理论付诸实现的有效的机器学习方法。
目前,SVM算法在模式识别、回归估计、概率密度函数估计等方面都有应用。
例如,在模式识别方面,对于手写数字识别、语音识别、人脸图像识别、文章分类等问题,SVM算法在精度上已经超过传统的学习算法或与之不相上下。
目前,国际上对这一理论的讨论和进一步研究逐渐广泛,而我国国内尚未在此领域开展研究,因此我们需要及时学习掌握有关理论,开展有效的研究工作,使我们在这一有着重要意义的领域中能够尽快赶上国际先进水平。由于SLT理论和SVM方法尚处在发展阶段,很多方面尚不完善,比如:许多理论目前还只有理论上的意义,尚不能在实际算法中实现;而有关SVM算法某些理论解释也并非完美(J.C.Burges在[2]中就曾提到结构风险最小原理并不能严格证明SVM为什么有好的推广能力);此外,对于一个实际的学习机器的VC维的分析尚没有通用的方法;SVM方法中如何根据具体问题选择适当的内积函数也没有理论依据。因此,在这方面我们可做的事情是很多的。
上文引自 水母bbs AI版
相关资源
SVM的英文主站,
http://www.kernel-machines.org/
Support Vector Machine 作者的站点
http://www.support-vector.net
piaip 的 (lib)SVM 簡易入門
http://ntu.csie.org/~piaip/svm/svm_tutorial.html
林智仁(cjlin)老師的 libsvm for matlab
LIBSVM — A Library for Support Vector Machines
Chih-Chung Chang and Chih-Jen Lin
http://www.csie.ntu.edu.tw/~cjlin/libsvm/
|
SVM学习之四——从机器学习到支持向量机
上一篇 / 下一篇 2007-09-27 10:41:06 / 个人分类:svm
机器学习(Machine Learning, ML)的目的是根据给定的训练样本求对某系统输入输出之间依赖关系的估计,使它(这种关系)能够对未知输出做出尽可能准确地预测。机器学习至今没有一个精确的公认的定义。作为人工智能(Artificial Intelligence, AI)的一个重要研究领域,ML的研究工作主要围绕学习机理、学习方法和面向任务这三个基本方面进行研究。模式识别、函数逼近和概率密度估计是三类基本的ML问题。
从数学的角度来考虑,机器学习问题就是已知n个独立同分布的观测样本,在同一组预测函数中求一个最优的函数对依赖关系进行估计,使期望风险R[f]最小。损失函数是评价预测准确程度的一种度量,它与预测函数f(x)密切相关。而f(x)的期望风险依赖于概率分布和损失函数,前者是客观存在的,后者是根据具体问题选定的,带有(主观的)人为的或偏好色彩。期望风险的大小直观上可以理解为,当我们用f(x)进行预测时,“平均”的损失程度,或“平均”犯错误的程度。
但是,只有样本却无法计算期望风险,因此,传统的学习方法用样本定义经验风险Remp[f]作为对期望风险的估计,并设计学习算法使之最小化。即所谓的经验风险最小化(Empirical Risk Minimization, ERM)归纳原则。经验风险是用损失函数来计算的。对于模式识别问题的损失函数来说,经验风险就是训练样本错误率;对于函数逼近问题的损失函数来说,就是平方训练误差;而对于概率密度估计问题的损失函数来说,ERM准则就等价于最大似然法。事实上,用ERM准则代替期望风险最小化并没有经过充分的理论论证,只是直观上合理的想当然做法。也就是说,经验风险最小不一定意味着期望风险最小。其实,只有样本数目趋近于无穷大时,经验风险才有可能趋近于期望风险。但是很多问题中样本数目离无穷大很远,那么在有限样本下ERM准则就不一定能使真实风险较小啦。ERM准则不成功的一个例子就是神经网络的过学习问题(某些情况下,训练误差过小反而导致推广能力下降,或者说是训练误差过小导致了预测错误率的增加,即真实风险的增加)。
统计学习理论(Statistical Learning Theory, SLT)和支持向量机(Support Vector Machine, SVM)建立了一套较好的有限训练样本下机器学习的理论框架和通用方法,既有严格的理论基础,又能较好地解决小样本、非线性、高维数和局部极小点等实际问题,其核心思想就是学习机器(又叫预测函数,或学习函数,或学习模型)F要与有限的训练样本相适应。在学习算法中需要选择恰当的F,这里的关键因素是F的大小,或者F的丰富程度,或者说F的“表达能力”,VC维(Vapnik-Chervonenkis Dimension)就是对这种“表达能力”的一种描述。
VC维的定义如下:对于一个指示函数集,如果存在h个样本能够被函数集中的函数按所有可能的2的h次幂种形式分开,则称函数集能够把h个样本都打散,h的最大值就是函数集的VC维。VC维是SLT中的一个重要概念,它是函数集学习性能的重要指标。目前尚没有通用的关于任意函数集VC维计算的理论,只知道一些特殊的函数集的VC维。比如,在n维空间中线性分类器和线性实函数的VC维是 n+1,而 f(x,a) = sin(ax) 的VC维则为无穷大。对于给定的学习函数集,如何(用理论或实验的方法)计算其VC维是当前统计学习理论中有待研究的一个问题。
由上文可知,在有限样本情况下,仅仅用ERM来近似期望风险是行不通的。统计学习理论给出了期望风险 R[f] 与经验风险 Remp[f] 之间关系:R[f] <= ( Remp[f] + e )。其中 e = g(h/n) 为置信区间,e 是VC维 h 的增函数,也是样本数n的减函数。右端称为结构风险,它是期望风险 R[f] 的一个上界。经验风险的最小依赖较大的 F (样本数较多的函数集)中某个 f 的选择,但是 F 较大,则VC维较大,就导致置信区间 e 变大,所以要想使期望风险 R[f] 最小,必须选择合适的 h 和 n 来使不等式右边的结构风险最小,这就是结构风险最小化(Structural Risk Minimization, SRM)归纳原则。实现SRM的思路之一就是设计函数集的某种结构使每个子集中都能取得最小的经验风险(如使训练误差为0),然后只需选择适当的子集使置信范围最小,则这个子集中使经验风险最小的函数就是最优函数。SVM方法实际上就是这种思想的具体实现。
SVM是一种基于统计的学习方法,它是对SRM的近似。概括地说,SVM就是首先通过用内积函数定义的非线性变换将输入空间变换到一个高维空间,然后再在这个空间中求(广义)最优分类面的分类方法。
2008-06-17 21:22
忙于项目,看了一些理论书籍,总感觉雾里看花,为了能有点动力,我准备写一些总结。
1 机器学习问题表示
变量y与输入x之间存在一定的关系,即存在二维联合概率密度F(x,y)
机器学习根据m个独立,同分布观测样本求出一个最优函数y=f(x,a),使预测的期望风险最小
R(a)= |Q(y,f(x,a))dF(x,y),其中Q(y,f(x,a))是f(x,a)与y之间的损失函数
2 经验风险最小化
由于并不知道F(x,y),所以无法利用期望风险来求f(x,a),但根据大数定理的思想,可以用算术平均代替数学期望 Remp(a)= 1/m(Q(yi,f(xi,a))+......),使样本均值最小求出f(x,a)中参数a
3 最小均值方法
求经验风险最小可以看做是最佳拟合问题,E = (yi-f(xi,a))**2+ ..........
在调整权值时需要这样一个算法:在有了新的训练样本时可以在原来的基础上进一步精化权值。对于每一个训练样例,它把权值向减少误差的方向略为调整。这个算法可以看做对可能的假设权值空间进行随机的梯度下降搜索。权值w更新方式为:w<--w+l(yi - f(xi,a))xi
4函数集的vc维
函数集Q(z,a)vc维等于能够用该函数集以所有可能的2**k种方式分成不同两类的向量z1,z2....最大数目。越复杂的函数vc维越高。
期望风险R(a )== 经验风险Remp(a)+sqr(h/m),可见vc维增加会导致期望风险增加。
5结构风险最小化
min(经验风险Remp(a)+sqr(h/m))
6支持向量机
svm的基本思想是通过事先选择的线性或非线性的映射将输入向量映射到高维特征空间中,在这个空间中利用了最优化理论和泛化性理论,同时引入了超平面的概念(减少vc维),来构造最优决策函数,并巧妙地利用核函数来代替高维特征空间的点积运算,从而避免了复杂的计算。
7贝叶斯决策
设要识别的对象有d中特征测量值x1,x2.....xd,每种特征都是一个随机变量。
设gi(x)为对应i类的风险函数,利用先验概率,相应的分类规则为:
如果gi(x)>gj(x),i,j = 1,2,...c, j!= i,则x属于第i类,决策面方程为 gi(x)= gj(x)
8分类与聚类
分类:样本已知所属类别,求出分类函数,对新的样本进行识别
聚类:样本无类别,根据其分布距离进行分类
9线性分类器
定义一个准则函数J(w,x),w是分类器参数,它的最小值对应着最优解。得到梯度法迭代公式:
w(k+1)= w(k)-p(△J)
因为判别函数g(x)满足:
g(x)>0 x∈w
g(x)<0 x!∈w
准则函数有最小平方误差,最小错分类等。
10聚类
相似性测度:欧式距离,马氏距离,明氏距离,夹角余弦
散布准则:类内散布,类间散布,总散布
求解过程是聚类中心点迭代
11特征抽取和选择
选择:选取要使用的特征
抽取:利用选择出来的特征进行降维变换
抽取方法有线性变换,主成分分析的最佳矩阵变换,
|
感觉数学似乎总是不够的。这些日子为了解决research中的一些问题,又在图书馆捧起了数学的教科书。
从 大学到现在,课堂上学的和自学的数学其实不算少了,可是在研究的过程中总是发现需要补充新的数学知识。Learning和Vision都是很多种数学的交 汇场。看着不同的理论体系的交汇,对于一个researcher来说,往往是非常exciting的enjoyable的事情。不过,这也代表着要充分了 解这个领域并且取得有意义的进展是很艰苦的。
记得在两年前的一次blog里面,提到过和learning有关的数学。今天看来,我对于数学在这个领域的作用有了新的思考。
对于Learning的研究,
Linear Algebra (线性代数) 和 Statistics (统计学) 是最重要和不可缺少的。这代表了Machine Learning中最主流的两大类方法的基础。一种是以研究函数和变换为重点的代数方法,比如Dimension reduction,feature extraction,Kernel等,一种是以研究统计模型和样本分布为重点的统计方法,比如Graphical model, Information theoretical models等。它们侧重虽有不同,但是常常是共同使用的,对于代数方法,往往需要统计上的解释,对于统计模型,其具体计算则需要代数的帮助。
以代数和统计为出发点,继续往深处走,我们会发现需要更多的数学。
Calculus (微积分),只是数学分析体系的基础。其基础性作用不言而喻。Learning研究的大部分问题是在连续的度量空间进行的,无论代数还是统计,在研究优化 问题的时候,对一个映射的微分或者梯度的分析总是不可避免。而在统计学中,Marginalization和积分更是密不可分——不过,以解析形式把积分 导出来的情况则不多见。
Partial Differential Equation (偏微分方程),这主要用于描述动态过程,或者仿动态过程。这个学科在Vision中用得比Learning多,主要用于描述连续场的运动或者扩散过程。 比如Level set, Optical flow都是这方面的典型例子。
Functional Analysis (泛函分析), 通俗地,可以理解为微积分从有限维空间到无限维空间的拓展——当然了,它实际上远不止于此。在这个地方,函数以及其所作用的对象之间存在的对偶关系扮演了 非常重要的角色。Learning发展至今,也在向无限维延伸——从研究有限维向量的问题到以无限维的函数为研究对象。Kernel Learning 和 Gaussian Process 是其中典型的例子——其中的核心概念都是Kernel。很多做Learning的人把Kernel简单理解为Kernel trick的运用,这就把kernel的意义严重弱化了。在泛函里面,Kernel (Inner Product) 是建立整个博大的代数体系的根本,从metric, transform到spectrum都根源于此。
Measure Theory (测度理论),这是和实分析关系非常密切的学科。但是测度理论并不限于此。从某种意义上说,Real Analysis可以从Lebesgue Measure(勒贝格测度)推演,不过其实还有很多别的测度体系——概率本身就是一种测度。测度理论对于Learning的意义是根本的,现代统计学整 个就是建立在测度理论的基础之上——虽然初级的概率论教科书一般不这样引入。在看一些统计方面的文章的时候,你可能会发现,它们会把统计的公式改用测度来 表达,这样做有两个好处:所有的推导和结论不用分别给连续分布和离散分布各自写一遍了,这两种东西都可以用同一的测度形式表达:连续分布的积分基于 Lebesgue测度,离散分布的求和基于计数测度,而且还能推广到那种既不连续又不离散的分布中去(这种东西不是数学家的游戏,而是已经在实用的东西, 在Dirchlet Process或者Pitman-Yor Process里面会经常看到)。而且,即使是连续积分,如果不是在欧氏空间进行,而是在更一般的拓扑空间(比如微分流形或者变换群),那么传统的黎曼积 分(就是大学一年级在微积分课学的那种)就不work了,你可能需要它们的一些推广,比如Haar Measure或者Lebesgue-Stieltjes积分。
Topology(拓扑学),这是学术中很基础的学科。它一般不直接提 供方法,但是它的很多概念和定理是其它数学分支的基石。看很多别的数学的时候,你会经常接触这样一些概念:Open set / Closed set,set basis,Hausdauf, continuous function,metric space, Cauchy sequence, neighborhood, compactness, connectivity。很多这些也许在大学一年级就学习过一些,当时是基于极限的概念获得的。如果,看过拓扑学之后,对这些概念的认识会有根本性的拓 展。比如,连续函数,当时是由epison法定义的,就是无论取多小的正数epsilon,都存在xxx,使得xxx。这是需要一种metric去度量距 离的,在general topology里面,对于连续函数的定义连坐标和距离都不需要——如果一个映射使得开集的原像是开集,它就是连续的——至于开集是基于集合论定义的,不 是通常的开区间的意思。这只是最简单的例子。当然,我们研究learning也许不需要深究这些数学概念背后的公理体系,但是,打破原来定义的概念的局限 在很多问题上是必须的——尤其是当你研究的东西它不是在欧氏空间里面的时候——正交矩阵,变换群,流形,概率分布的空间,都属于此。
Differential Manifold (微分流形), 通俗地说它研究的是平滑的曲面。一个直接的印象是它是不是可以用来fitting一个surface什么的——当然这算是一种应用,但是这是非常初步的。 本质上说,微分流形研究的是平滑的拓扑结构。一个空间构成微分流形的基本要素是局部平滑:从拓扑学来理解,就是它的任意局部都同胚于欧氏空间,从解析的角 度来看,就是相容的局部坐标系统。当然,在全局上,它不要求和欧氏空间同胚。它除了可以用于刻画集合上的平滑曲面外,更重要的意义在于,它可以用于研究很 多重要的集合。一个n-维线性空间的全部k-维子空间(k < n)就构成了一个微分流形——著名的Grassman Manifold。所有的标准正交阵也构成一个流形。一个变换群作用于一个空间形成的轨迹(Orbit) 也是通常会形成流形。在流形上,各种的分析方法,比如映射,微分,积分都被移植过来了。前一两年在Learning里面火了好长时间的Manifold Learning其实只是研究了这个分支的其中一个概念的应用: embedding。其实,它还有很多可以发掘的空间。
Lie Group Theory (李群论),一般意义的群论在Learning中被运用的不是很多,群论在Learning中用得较多的是它的一个重要方向Lie group。定义在平滑流行上的群,并且其群运算是平滑的话,那么这就叫李群。因为Learning和编码不同,更多关注的是连续空间,因为Lie group在各种群中对于Learning特别重要。各种子空间,线性变换,非奇异矩阵都基于通常意义的矩阵乘法构成李群。在李群中的映射,变换,度量, 划分等等都对于Learning中代数方法的研究有重要指导意义。
Graph Theory(图论),图,由于它在表述各种关系的强大能力以及优雅的理论,高效的算法,越来越受到Learning领域的欢迎。经典图论,在 Learning中的一个最重要应用就是graphical models了,它被成功运用于分析统计网络的结构和规划统计推断的流程。Graphical model所取得的成功,图论可谓功不可没。在Vision里面,maxflow (graphcut)算法在图像分割,Stereo还有各种能量优化中也广受应用。另外一个重要的图论分支就是Algebraic graph theory (代数图论),主要运用于图的谱分析,著名的应用包括Normalized Cut和Spectral Clustering。近年来在semi-supervised learning中受到特别关注。
生活中的概率
概率论渗透到现代生活的方方面面。正如19世纪法国著名数学家拉普拉斯所说:“对于生活中的大部分,最重要的问题实际上只是概率问题。你可以说几乎我们所掌握的所有知识都是不确定的,只有一小部分我们能确定地了解。甚至数学科学本身,归纳法、类推法和发现真理的首要手段都是建立在概率论的基础之上。因此,整个人类知识系统是与这一理论相联系的……”
婴儿出生时的男女比例
一般人或许认为:生男生女的可能性是相等的,因而推测出男婴和女婴的出生数的比应当是1:1,可事实并非如此.
公元1814年,法国数学家拉普拉斯(Laplace 1794-1827)在他的新作《概率的哲学探讨》一书中,记载了一下有趣的统计.他根据伦敦,彼得堡,柏林和全法国的统计资料,得出了几乎完全一致的男婴和女婴出生数的比值是22:21,即在全体出生婴儿中,男婴占51.2%,女婴占48.8%.可奇怪的是,当他统计1745-1784整整四十年间巴黎男婴出生率时,却得到了另一个比是25:24,男婴占51.02%,与前者相差0.14%.对于这千分之一点四的微小差异,拉普拉斯感到困惑不解,他深信自然规律,他觉得这千分之一点四的后面,一定有深刻的因素.于是,他深入进行调查研究,终于发现:当时巴黎人“重女轻男”,有抛弃男婴的陋俗,以至于歪曲了出生率的真相,经过修正,巴黎的男女婴的出生比率依然是22:21.
一名优秀数学家=10个师
在第二次世界大战中,美国曾经宣布:一名优秀数学家的作用超过10个师的兵力.这句话有一个非同寻常的来历.
1943年以前,在大西洋上英美运输船队常常受到德国潜艇的袭击,当时,英美两国限于实力,无力增派更多的护航舰,一时间,德军的“潜艇战”搞得盟军焦头烂额.
为此,有位美国海军将领专门去请教了几位数学家,数学家们运用概率论分析后分析,舰队与敌潜艇相遇是一个随机事件,从数学角度来看这一问题,它具有一定的规律性.一定数量的船(为100艘)编队规模越小,编次就越多(为每次20艘,就要有5个编次),编次越多,与敌人相遇的概率就越大.
美国海军接受了数学家的建议,命令舰队在指定海域集合,再集体通过危险海域,然后各自驶向预定港口.结果奇迹出现了:盟军舰队遭袭被击沉的概率由原来的25%降为1%,大大减少了损失,保证了物资的及时供应.
什么是概率天气预报
概率天气预报是用概率值表示预报量出现可能性的大小,它所提供的不是某种天气现象的\"有\"或\"无\",某种气象要素值的\"大\"或\"小\",而是天气现象出现的可能性有多大。如对降水的预报,传统的天气预报一般预报有雨或无雨,而概率预报则给出可能出现降水的百分数,百分数越大,出现降水的可能性越大。一般来讲,概率值小于或等于30%,可认为基本不会降水;概率值在30%-60%,降水可能发生,但可能性较小;概率在60%-70%,降水可能性很大;概率值大于70%,有降水发生。概率天气预报既反映了天气变化确定性的一面,又反映了天气变化的不确定性和不确定程度。在许多情况下,这种预报形式更能适应经济活动和军事活动中决策的需要。
生命中的危险概率
生活就是一场冒险。日常生活中出现一些危险是难免的,问题是遭遇某种危险的概率有多大。一般说来,如果遭遇某种危险的概率低于十万分之一,我们还能坦然视之;但如果危险概率提高到万分之一,我们就得小心了。每年都可能遇到的危险机会有:
受伤:危险概率是1/3
难产(行将生育的妇女):危险概率是1/6
车祸:危险概率是1/12
心脏病突然发作(如果您已超过35岁):危险概率是1/77
在家中受伤:危险概率是1/80
受到致命武器的攻击:危险概率是1/260
死于心脏病:危险慨率是1/340
家中成员死于突发事件:危险概率是1/700
死于突发事件:危险概率是1/2900
死于车祸:危险概率是1/5000
染上爱滋病:危险概率是1/5700
被谋杀:危险概率是1/1110
死于怀孕或生产(女性):危险概率是1/4000
自杀:危险概率分别是1/20000(女性)和1/5000
因坠落摔死:危险率是1/20000
死于工伤:危险概率是1/26000
走路时被汽车撞死:危险概率是1/40000
死于火灾:危险概率是1/50000
溺水而死:危险概率是1/50000
如果您自己不吸烟,而您的配偶吸烟,那么您可能受二手烟污染而死于肺癌: 危险概率是1/60000
被刺伤致死:危险概率是1/60000
死于手术并发证:危险概率是1/80000
因中毒而死(不包括自杀):危险概率是1/86000
骑自行车时死于车祸:危险概率是1/130000
吃东西时噎死:危险概率是1/160000
被空中坠落的物体砸死:危险概率是1/290000
触电而死:危险概率是1/350000
死于浴缸中:危险概率是1/1000000
坠落床下而死:危险概率是1/2000000
被龙卷风刮走摔死:危险极率是l/2000000
被冻死:危险概率是1/3000000
一生中可能道遇到的危险有:
死于心脏病:危险概率是1/3
死于癌症:危险概率是1/5
遭到强奸(女性):危险概率是1/11
死于中风:危险概率是1/14
死于车祸:危险概率是1/45
自杀:危险概率是1/39
死于爱滋病:危险概率是1/97
死于飞机失事:危险概率是1/4000
死于狂犬病:危险概率是1/700000
艾滋病的传染概率有多大
艾滋病传染概率有多大?据地坛医院性传播疾病防治中心徐克沂主任介绍,艾滋病是通过3种传播途径传染给他人的,即:血液传播、性传播、母婴传播。如果一个正常人输进了HIV(艾滋病病毒)阳性感染者或艾滋病病人的血液其感染的概率是95%,而一个HIV阳性感染者或已经发病的病人与一个正常人发生性关系的感染概率和性别有一定关系,男传给女的概率是0.2%,女传给男的概率是0.l%,男传男的概率要比以上两种方式大得多。如果母亲是一个HIV阳性或艾滋病的病人,其感染给胎儿的概率是25%,但是如果母亲经过AZT的抗病毒治疗,其胎儿的感染概率下降到8%;经过联合疗法(鸡尾酒疗法)治疗胎儿的感染概率可能下降为2%
艾滋病病毒是一种十分脆弱的病毒,它对热和干燥十分敏感。在干燥的环境中,艾滋病毒10分钟死亡,在60摄氏度的环境中30分钟灭活。如果一支刚接触病人身体带有血液的注射器,马上刺入正常人体内,其感染的概率小于0.3%。蚊虫叮咬不会传染艾滋病就是因为这个原因。
在医学史上人类经历了霍乱、鼠疫、黄热病和天花等多种流行病的侵害,而人类最终还是战胜了它们。如今面对艾滋病,有关遏制艾滋的医学研究也正在紧锣密鼓开展,例如用传统医学方法研制的艾滋疫苗;用中医药技术研发的艾滋抗体及从计划生育角度转而提倡运用的“避孕套”,这些都让我们看到人类克服艾滋病的曙光。
彩票中奖概率话你知
“36选7”“26选5”概率
据有关专家介绍,广东省目前发行的体彩“36选7”、南粤风采“36选7”、南粤风采“26选5”均属于数字组合型玩法,其中奖概率的计算方式也是相同的,其中“36选7”玩法的头奖命中概率为1/8347680,“26选5”玩法的头奖命中概率为1/65780;目前体彩“36选7”二次开奖的中奖概率仍为1/8347680,南粤风采“36选7”全省特别奖(中8个号码)的中奖概率为1/32060340,南粤风采“36选7”南粤福星奖(中9个号码)的中奖概率为1/94143280,南粤风采“26选5”幸运奖(中7个号码)的中奖概率为1/657800。
excel函数可计算中奖概率
针对类似“36选7”的数字组合型玩法,数学专家还向记者推荐了一种利用excel表格软件函数计算的简单方法,打开电脑中的excel软件,在“粘贴函数”栏内选择“数学与三角函数”中的“combin”函数,填入相关数据就可以计算出相应的中奖概率,如“36选7”的概率计算公式为:combin (36,7),南粤风采“36选7”全省特别奖和南粤福星奖的计算公式分别为:com-bin(36,8)、combin (36,9),彩民朋友可以根据公式自行计算“×选×”型彩票玩法的头奖中奖概率。
幸运七星及足彩中奖概率
体彩“幸运七星”则属于数字型玩法,即从0000000~9999999共1000万个号码中任选一个七位数号码组成,每个号码均从0~9共10个数字中开出,“幸运七星”头奖的理论中奖概率为1/10000000。
目前最受彩民欢迎的足彩实际上也是一种数字组合型玩法,不过计算方法相对比较简单,13场比赛均选“3、1、0”可组合出3的13次方1594323注单式号码,一等奖的中奖概率为1/1594323,换句话说,每销售320万元的足彩,平均就可能诞生一个一等奖。而如果将足彩竞猜的场次增加到14场,足彩的头奖中奖概率则降低为1/4782969,难度增加了3倍。
吸烟危及生命概率:50%戒烟等于自救
1987年11月,世界卫生组织(WHO)在日本东京举行的第6届吸烟与健康国际会议上,建议把1988年4月7日,也就是世界卫生组织成立40周年纪念日,作为“世界无烟日”,提出“要吸烟还是要健康”的口号。1989年,世界卫生组织又把这一天改定在每年的5月31日。
今年5月31日,我们将迎来第17个世界无烟日,但目前我国吸烟现状却不容乐观:烟民人数不断增加,达3.2亿人,烟民平均年龄在降低,女烟民及青少年吸烟的数量在不断增加。
我国烟草生产和消费还居八个“世界第一”:烤烟种植面积世界第一;烤烟产量世界第一:烤烟增长速度世界第一;卷烟产销量世界第一;卷烟增长速度世界第一;吸烟人数世界第一;吸烟人数增加数量世界第一;烟税增长速度世界第一。
吸烟有害健康,这句话人人会讲,但是,你可知道,吸烟危及生命的概率究竟达到了何种程度吗?
探究吸烟与戒烟
一,吸烟为什么会上瘾?
烟民往往都有烟瘾,这主要是尼古丁长期作用的结果。尼古丁就像其他麻醉剂一样,刚开始吸食时并不适应,会引起胸闷、恶心、头晕等不适,但如果吸烟时间久了,血液中的尼古丁达到一定浓度,反复刺激大脑并使各器官产生对尼古丁的依赖性,此时烟瘾就缠身了。若停止吸烟,会暂时出现烦躁、失眠、厌食等所谓的“戒断症状”,加上很多吸烟者对烟草产生一种心理上的依赖,认为吸烟可以提神、解闷、消除疲劳等,所以烟瘾越来越大,欲罢不能。
其实烟草与吸食海洛因引起的成瘾性不同,前者是完全可以戒掉的,关键要戒除心理上对烟草的依赖。这种心理依赖导致吸烟者的一种行为依赖,使得吸烟者感到戒烟困难甚大,无形中增加了戒烟的难度。
二,二手烟危害他人健康?
一个人吸烟似乎“无关他人”,其实不然,其家人正受到被动吸烟的危害。根据世界卫生组织的定义,被动吸烟是指不吸烟者一周中有一天以上每天吸入吸烟者呼出的烟雾长于十五分钟。中国71%的家庭、32.5%的公共场所和25%的工作场所,因有人“吞云吐雾”而成为被动吸烟场所。
被动吸烟也即是吸“二手烟”,目前我国有六亿人受到被动吸烟的危害。被动吸烟者所吸入的有害物质浓度并不比吸烟者低,吸烟者吐出的冷烟雾中,烟焦油含量比吸烟者吸入的热烟雾中的多1倍,苯并芘多2倍,一氧化碳多4倍,如此多的有害物质对周围的人特别是儿童、孕妇和老年人造成很大的危害:
据估计,美国每年有四百万儿童因吸入“二手烟”而患病。父母吸烟使儿童下呼吸道疾病如哮喘、肺炎的发生率增加50%,儿童易出现各种慢性呼吸道刺激症状,如咳嗽、咳痰、喘息等,甚至出现持续的肺功能损害;
被动吸烟易引起中耳积液,使儿童中耳炎的发生率增加;
被动吸烟可以使哮喘患儿的哮喘发作次数与严重程度明显增加,对有过敏体质的患儿更易诱发哮喘发作;
被动吸烟与婴儿突然猝死综合征(SIDS)的发生密切相关;
父母吸烟使儿童更易成为吸烟者;孕妇吸入“二手烟”易引起流产、早产、出生低体重儿以及婴儿先天性畸形如唇裂、颚裂等;
老年人长期吸入“二手烟”易引起肺炎、急性心脑血管疾病的发生……
三,戒烟为何戒不了?
有研究表明,吸烟者中有11.7%的人是复吸者,而且复吸者的肺部损伤程度较一直吸烟者为重,原因有多方面:复吸者较其他吸烟者更易成瘾,复吸后其吸入香烟的数量更多,且每口烟的吸入程度更深,对身体的影响不言而喻。对于每一个吸烟者来说,在一些特定的“危险”情形下(当周围人吸烟、感到压力大、心情烦躁、饮酒后)会更有吸烟的冲动,那么请尽量避免这些情况的发生,当有吸烟冲动时做几次缓慢的深呼吸或从事其他活动转移注意力是个好方法。
四,戒烟后生活会变化吗?
如果您选择戒烟,您将选择告别咳嗽气喘、烟灰异味、污浊空气、皮肤衰老、疾病困扰……让我们看看您戒烟后生活发生了哪些变化:8小时后血液的氧合作用恢复正常,患心肌梗塞的风险开始降低;24小时后口气清新,肺开始排泄粘液和焦油,患呼吸道感染、支气管炎和肺炎的风险开始降低;48小时后血液中不再检测出尼古丁;1周后味觉、嗅觉得以改善;3—9月后呼吸得以改善(咳嗽、气喘减少),肺功能提高5%—10%;1年后患心脏病(如心肌梗塞)的风险减半;5年后患脑中风、口腔癌、食道癌、膀胱癌的风险减半;10年后患肺癌的风险减半,患脑血管突发事件(脑“中风”)的风险与未吸烟者持平……所以选择了戒烟,你就选择了一个健康清新的生活。
“吸烟危及生命的概率是50%,戒烟等于自救”。这是法国国家戒烟委员会和烟草预防办公室在巴黎举行的第30届法国医学沙龙上对所有吸烟者发出的警示和呼吁。
复旦大学附属中山医院呼吸内科瞿介明宋琳
消息来源:上海疾控中心
10%的酗酒概率
我们经常见到,当全家人围坐在节日餐桌旁的时候,父母让年幼的孩子喝上一点酒,这是否对孩子有害?专家们的看法是:90%的情况下不会有任何危害。但是,仍有10%的孩子,因为基因的特殊性而导致日后酗酒。谁来给这10%的孩子上保险,不致使他们进入这10%的行列?美国总统夫人弗尔德描述了自己酗酒的情况。她回忆说,当她感冒的时候,她妈妈将一勺威斯忌倒进了她的茶里。这足以使她成年后成了酗酒者。
中数字出现的稳定性(法格逊猜想)
在的数值式中,各个数码出现的概率应当均为.随着计算机的发展,人们对的前一百万位小数中各数码出现的频率进行了统计,得到的结果与法格逊猜想非常吻合.
我们是不是该相信小概率事件?
文/葛民勤
一、什么是小概率事件?
小概率事件,字面意义就是发生的可能性极小的事件。比如,北京地区出现日全食;山西洪洞发生里氏5级地震,新疆吐鲁番地区下了一场暴雨,小行星撞地球等等。以上这些是发生在自然界的小概率事件,发生在人类社会的小概率事件诸如上证指数突破2000点,某特定国家通过允许同性恋的法律,某两个国家统一等等。至于发生在日常生活中的小概率事件,也是不胜枚举,如某个特定的人中了彩票头奖,某日某地有人跳楼自杀,等等。
小概率事件是要和不可能事件,也即无概率事件区别开的。所谓不可能事件,就是指完全不可能发生、概率为零的事件。不可能事件可以分为三类。第一类,如某人某时刻既在甲地又在乙地,世界上既有能刺穿一切盾的矛又有能抵挡一切矛的盾等等,属于自相矛盾的事件,违反了逻辑,也就绝对不可能发生。这类不可能事件显然没有研究意义。
第二类,如日本没有进行南京大屠杀、诸葛亮的隐居地在河南南阳而不是湖北襄阳等等,是对于历史上确凿发生过的事件的否定,也即对必然事件的否定,其概率自然为零。但是这种不可能事件在统计学上也没有研究意义,因为统计学更多地是关注在一定条件下可以重现的事件以及一般性的事件,而不是永远无法重现的个别事件。
不可能事件的第三类,如永动机、常温常压下纯冰在零摄氏度以下自发融化、地球接收到三秒钟前太阳发射的光线等等,违反了最基本的自然规律,也是对必然事件的否定,因而发生的概率也为零。永动机违反了热力学定律;常温常压下纯冰在零摄氏度以下融化违反了冰的相图,实质也是违反了热力学第二定律;地球接收到三秒钟前太阳发射的光线则违反了相对论“真空光速不变”的原理。不过,某些这一类的不可能事件的判定不是很简单的,后文还要提及。
二、基本的概率计算方法
小概率事件彼此也可以相差很大的。例如,同样是发生里氏5级以上地震,在日本和在山西洪洞的概率就明显不同。日本几乎每年都会发生至少一次里氏5级以上地震,而山西洪洞发生里氏5级以上地震的概率大约是200年~300年一遇(同一地震序列中的几次5级以上地震按一次计算)。又如同样是干旱地区,吐鲁番和南美洲智利阿塔卡马沙漠的暴雨概率也大为不同。1958年8月14日,吐鲁番突降36.0毫米的暴雨,引发山洪泛滥;这种暴雨在有记录以来的阿塔卡马沙漠地区还从未出现——相反,阿塔卡马沙漠曾创造了1845-1936年间整整91年没有降水的纪录。
要对小概率事件发生的可能性有正确的认识,就必须估计出小概率事件的概率。概率计算的最基本方法,是先估计出与该事件互不相容(即永远不可能同时发生)的所有事件的数目,则该事件包括的所有情况的数目与所有这些互不相容事件的数目之比,就是该事件的概率。最直观的例子是掷骰子。骰子共有六面,掷一次骰子得到某一点值就有六种可能,而且是互不相容的。因此,全部互不相容事件的数目是6。假如我们要算掷一次得到1点的概率,这个事件只有一种可能,所以其概率为1/6。假如我们要算掷一次得到点数为3的倍数的概率,因为这个事件包含两种情况(3点和6点),所以其概率为2/6=1/3.
这种基本方法有两个局限:第一,它所计算的事件如果要发生,只能发生一次;第二,它所计算的事件是瞬间决定的,而不是一个连续的过程。但是这两个局限并不难突破。对于多次发生的事件,可以应用独立事件的积的办法计算某一事件的概率。所谓独立事件,是指两件或两件以上事件彼此之间互不干扰,一件事发生与否对另一件事的概率没有影响。如两次彩票的头奖号码,因为抽奖过程是完全独立的,因此第二次彩票的头奖号码有可能和第一次相同,而不会有意避开。显然,在考虑几次事件联合发生的概率时,总的互不相容事件的数目是每一独立事件的互不相容事件数目的乘积。如掷两个骰子,第一个骰子有6种可能,第二个骰子也有6种可能,总可能性就是6×6=36种。因此,总概率也就是每一独立事件发生的概率之积。例如掷两个骰子出现两个6点,每个骰子出现6点的概率是1/6,总概率就是(1/6)×(1/6)=1/36。
如果事件发生的次数再多,应用简单的四则计算就会感到计算量庞大而难以算出结果。而对于连续性发生的事件,也不能用硬性分割的办法把它简化为瞬间发生的多次独立事件。幸而高等数学已经解决了这个问题。极限概念的引进为解决复杂的概率计算提供了理论基础,微积分就是极限概念的应用。应用微积分来计算概率,也就成为统计学的基础。
三、小概率事件的估计方法
不同的小概率事件,有不同的各具特色的概率估计方法,概率值的表达形式也不相同,但都体现了上述基本的计算方法。例如,对地震、旱灾、洪水之类自然灾害的概率,我们常常用“××年一遇”这种表达形式。仍以洪洞地区地震为例。自有史料记载以来,1303年9月25日在城关镇-赵城镇(当时为洪洞县和赵城县)发生了大地震,据史籍文献里的烈度推算,震级为里氏8级;1695年5月18日,在洪洞南部的临汾发生八级大地震,强烈波及洪洞地区。如果再算上一些震级较小的破坏性地震,洪洞地区5级以上破坏性地震的概率大约是两三百年一遇。
需要说明的是,这种通过史籍的记载来进行自然灾害的统计和概率估计的方法是中国特色的,因为只有中国保留下来了如此众多而完备的各种史籍。对于缺乏史籍的国家和地区,对自然灾害的统计和概率估计,只能通过自然调查的方法。
又如对外星人来访的概率估计。首先是分析事件发生的原因。外星人来访有两个前提条件,一是生命能够存在,二是生命能够进化到智慧生命并且发展到宇航时代。影响这两个前提条件的必备因素是很多的,首先必须要求恒星是稳定的主序星,温度不能过热,而且是单一存在,不是双星或多星系统;其次,行星大小适中,有足够的水和大气,与恒星的距离适中,轨道偏心率不能太大;再次,有足够的时间供生命演变,也即宇宙环境要稳定,在行星系统30光年内的所有恒星都必须保证在这一时间段内不发生灾变。如果对每一个原因都利用现有的天文观测资料进行慎重的估计,文明世界在银河系内发生的可能性只有不到10^(-6),换句话说,银河系的四千亿颗恒星里,可能存在宇航时代文明世界的恒星不到四十万个,即文明世界的平均半径达70光年。这一计算方法首先由SETI工程的先驱者、美国天文学家弗兰克·德雷克(Frank Drake)提出,德雷克因此建立了一个计算概率的公式,称为德雷克公式。德雷克公式清晰地告诉我们,即使按最保守的估计,外星人来访的可能性也不会比你猜中一个随机生成的六位数更大。
同样,对于社会和日常生活中的小概率事件的统计和概率估计,也有自己独特的方法。但总不外乎原因分析、建模和调查这几种基本方法。统计学发展到今天,已经是一门严谨精密的科学,在自然科学和社会科学的研究中得到了越来越多的应用。例如统计热力学,就是统计学方法和物理学的完美结合。社会科学的研究更离不开统计学,因为社会发展的规律本身就是以统计性为其特征的。因此,掌握统计学的基本原理,已是对从事各种研究的学者的最起码要求。
四、有意义和无意义的小概率事件
以上对小概率事件及其概率估算方法做了简单的分析。分析结果是需要应用于实践的。对小概率事件估算出来的概率值,可以科学地决定我们的决策。这时我们就需要判定,哪些小概率事件是有意义的,哪些小概率事件是无意义的。因此,判断小概率事件是否有意义,就是判断它对于我们的实践是否有影响。这体现了对小概率事件的意义判断的“实用性”。
首先,概率本身的大小是一个重要的判定依据。如果一个小概率事件的概率太小,比如,低于10^(-5)量级,那么在绝大多数情况下,它对于实践的影响可以忽略,也就因此是没有意义的。比如月亮从天上掉下来,严格地说,这也是小概率事件,因为既然地球对月亮有吸引力,它从天上掉下来是理论成立的。那么这种事件发生的概率是多少呢?同样先要找原因。月球掉下来的最可能原因不外乎三种:一,有小行星撞过来,改变了它的运行轨道;二,外星人所为;三,地球人自己所为。前两种的概率都不到10^(-7),而第三种,在最近几十年内,概率趋近于零。三种原因合起来考虑,这一事件发生的概率至多是2×10^(-7),尽管不是零,但却足以被认定是无意义的。因此,不会有任何一个国家准备足够的核弹头,以备万一月球下坠时发射、以改变其运行轨迹、使之飞离地球或回到原轨道之用。
其次,实践的精度也是一个重要的判定依据。如果做一件事不需要太多的考虑,也就是说,不需要太高的精度,那么凡是低于这个精度的不确定性都可以不在考虑之列,也就因此是无意义的。比如计算月球轨道,如果只是为了定农历的初一,那么至多考虑地球引力、太阳引力、岁差等三四项就可以了;如果要精确计算的话,大行星的摄动之类也必须考虑进去。二十世纪初,英国天文学家E.W.布朗(E.W. Brown)在精密的观测和天体力学理论的基础上,建立了新的月球运动理论,并以毕生精力投入到月球轨道计算中去。他所考虑的影响月球轨道的因素,就有几百项之多。这对于尖端的天文学应用(例如后来的人造卫星发射和控制)当然是十分有意义的,但对于编制农历,考虑这么多的因素就无意义了。
再次,考虑小概率事件的发生时,需要注意到它的发生频率不均性。小概率事件的发生概率只能是在一定范围内平均而言,但分布可以是不均的。例如我们常常说我国是多地震国家,但地震在时间和空间上都分布不均。比如,我们不能要求地震很少的江西省盲目加大抗震基础设施建设,那样是对资金的浪费,自然是无意义的。国家颁布的中国地震烈度区划图就是根据不同地区不同的地震发生频率制订的,有效地避免了抗震措施的盲目采取和资金的浪费。又如,1976年7月28日唐山地震后,围绕如何重建唐山展开了争论。如果按唐山地震的最大烈度XI度设防,则需要的建设资金过高,新唐山难以重建。因此,在地震学者的详细勘察之后,认定五十至一百年内,唐山地区不会再发生5.0级以上地震。于是把唐山地区的烈度区划定为VIII度区。这时候,1976年的唐山地震最大烈度高达XI度这一小概率事件对于今年五十至一百年这个时间区段内的城市抗震建设就是无意义的了。
划分小概率事件的有意义和无意义,可以使我们科学地对各种可能影响实践的因素进行取舍,从而使我们的决策具有最大的合理性。这也是运筹学的基本思想。
五、小概率事件和不可能事件的分辨
小概率事件以其概率小,有时是容易和不可能事件混淆的。如何区分小概率事件和不可能事件,不是一件简单的事情。首先,确实得承认某些情况下的区别是一个历史范畴,也就是说,随着科学技术的进步,某些被判定是不可能的事件可能成为小概率事件,而某些被判定是小概率的事件可能成为不可能事件。但是,这种分辨标准的变化只是个别标准的变化,而不是全部标准的变化。科学技术的发展是对宇宙客观规律的不断深入认识,是一个趋近绝对真实的过程,这就好比岩石在海中沉积,不断会有新的岩层生成,而老的岩层并未消失,而是成为新岩层的基础和支撑。承认个别判定标准的变化,决不是为了推而广之,认为整个科学体系的判定标准都有问题。
比如,惰性气体在发现之后的半个多世纪内,一直认为绝对不能与其他元素化合。但1962年,加拿大化学家巴特列(N. Bartlett)率先合成了第一种惰性气体的化合物——六氟络铂酸氙,开创了惰性气体化学这一崭新的无机化学分支,也使人们不得不把惰性气体改称为“稀有气体”,以图名正言顺。但是,在常温常压的大部分情况下稀有气体是无法和其他物质反应的,氦、氖、氩三种稀有气体至今没有拿到化合物,说明稀有气体的化学反应只是小概率事件。这是不可能事件转变为小概率事件之一例。 又如,1898年,英国物理学家凯尔文(W.T. Kelvin)曾忧心忡忡地认为,随着工业文明的不断发展和人类数目的不断增多,地球上的氧气在500年之内就会耗光,人类就会灭亡。事实上,早在1772年,英国化学家普利斯特里(J. Priestley)就发现了光合作用,以后的科学家陆续发现,光合作用消耗二氧化碳,制造氧气,恰恰和呼吸作用相反。生态学的发展使人们确立了碳循环、氧循环的概念,知道在尊重自然规律的前提下,人类的活动不会造成地球上的碳循环和氧循环失衡,生态环境会一直保持下去,因而,凯尔文的担心只是杞人忧天。这又是小概率事件转变为不可能事件的例子了。
但是需要指出的是,这种小概率事件和不可能事件的区别,仅仅是哲学层面上的意义。在实践层面上,一旦认定某小概率事件是“无意义”的,那么它和不可能事件也就没有任何区别。这就像是用计算器计算,如果你不停地用2除1,在一直不断地按等号之后,最后肯定会得到一个零。尽管从理论上讲,“一尺之棰,日取其半,万世不竭”,但计算器把若干次操作之后的结果,和真正的零等同起来,也就说明小概率事件和不可能事件的哲学层次区别,不能简单地套用在实践中。
六、小概率事件的另一个层面性
前面讲到了小概率事件有意义和无意义的一个层面性,即哲学层面和实践层面的区别。小概率事件的另一个层面性,是个体层面和一般层面的区别。事实上这也只不过是事物的种种矛盾中的一般矛盾和特殊矛盾的区别,但因为在我们讨论中的重要性,姑且把它提升到“层面”的高度来讨论。
我们举一个通俗的例子。日本漫画《机器猫》中曾经有一个故事,野比看到电视上保护朱鹮的新闻报道,忽然意识到自己也是世界上独一无二的一个,于是要机器猫“保护”自己以逃避繁杂的功课享受童年的快乐,结果适得其反。这里面就存在个别和一般层面的区别。野比作为人类,只是一个个体,而人类则是一个一般层面上的概念。个体的野比的“灭绝”和一般的人类的灭绝,显然是不同的。
同理,小概率事件作为偶然性的一种体现,只能起到补充和完善必然性的作用。如果承认历史唯物主义是正确的,人类社会的发展是客观的,那么社会规律必然是客观的,而作用在整体社会上的小概率事件,如果是起源于社会内部,而不是外部世界强加的不可抗力,就不会扭转人类社会本身发展的大势。但是在个体层面,这种小概率事件却可以扭转个人以至局部社会的命运。
不错,有时候社会领域里的小概率事件确实给人一种“身不由己”的感觉。但是这种“身不由己”感只在个人层面上有意义,从整个社会的发展来看,它只不过是滚滚洪流中的一瞬间的浪花。在承认历史唯物主义的前提下,过分渲染这种“身不由己”感,如果不是文学式的感喟,就是历史相对主义对人的意识的夸大;而抹煞这种“身不由己”感,又落入了机械历史唯物主义的窠臼。
所以,能够辩证地看待小概率事件,也是我们认识自然世界和人类社会,并更好地应用统计学和运筹学来解决问题的一个前提。
七、我们是不是该相信小概率事件? 经过上述的分析,下面我们来回答本文题目中的这个问题。
所谓“相信”某事,最简单的解释是认为某事是真的,不怀疑。如果我们不去考虑现代心理学对相信这一意识行为发起的原因的探析,而仅分析它的表现形式的话,那么“相信”至少有两个层次:其一,仅仅停留在哲学层面上的相信,而不用它指导实践;其二,既是哲学层面上的相信,也是实践层面上的相信,即用这一所相信的理念来指导实践。
显然,第一种相信对于指导实践是没有意义的,它所满足的,仅是一种内心的需求,一种纯思辩的愉悦。第二种相信则不仅仅达到这一点,而且将所相信的事物,用作自己行动的指南,并将这种指导实践的作用,作为发挥“相信”的能动性的重点。
对于自然科学研究来说,因为实践是其重点,一切自然科学研究的理论都要符合实践,所以从科学实践的角度来讲,第二种相信才是真正的相信,第一种相信对此而言只能是“伪相信”。比如,有一些科学家信教,但是在科学研究里面,他们并不把那些独属于宗教的教义拿来实施,宗教只是他们科学实践以外的感性生活里的重要成分。因此,对于他们作科学研究这件事来说,宗教的信仰只能是一种伪相信。不过需要特别强调一点,本文中所有“伪相信”中的“伪”,对应英文的pseudo-,只是一个中性的前缀,不具贬义,因此不能说,伪相信就是不合理的。
同理,上文已经论述,无意义的小概率事件对于实践不具指导作用。相信这种小概率事件只能起到对意识本身的能动作用,而对于实践,只能是一种伪相信。
反过来,在人文艺术领域,因为不涉及以物质为客体的实践,上述伪相信和真相信的区别,也就没有必要。尽管在科学实践的立场上,人文艺术领域的相信都是“伪相信”,但这样讲显然是对人文艺术不公平的——因为人文艺术并不要求能指导实践。因此我们另换一种说法,称其为“人文式相信”更合适一些。可以说,人文艺术所孜孜追求的也就是人文式相信。但是把这种人文式相信上升到科学实践角度的真相信的层次,也即人文艺术越俎代庖地指导科学实践,就是一种错误的作法了。
八、违反上述作法导致的错误作法举例
在本文的末尾,我们举两个今年发生的有名事件,以阐明违反上述作法会导致怎样的错误。
“非典”期间,著名科幻作家王晋康先生写了一组文章,阐述自己的“平衡医学观”,并认为“非典”的爆发正是现代医学违反“平衡医学观”而引发的咎由自取现象。王文见网之后,立刻引发了留美生物学博士方舟子及清华大学教授赵南元、网人桔梗等人的抨击。方舟子以自己掌握的专业知识,论证了王晋康“平衡医学观”的荒谬之处;赵南元则重点批评了王晋康越俎代庖的行为。客观地说,王晋康的“平衡医学观”经过他自己的补充和发挥,是一套很有趣味的思想体系。最初,王晋康只是把这种思想体系应用到科幻小说创作中来,只局限在人文艺术的框架里,自然收到了很好的效果。因为那些不以科普为目的的科幻小说的本质是纯文学或通俗文学,科普以外的审美为第一要求,不用来指导实践,所以王晋康在小说中写这样的观点无可厚非,反而使他的小说因具备思想性而锦上添花。但现在王晋康把他的观点应用到实践层面上,意欲指导科学,从科学实践的角度来说,不管王是不是意识到这一点,都是犯了以伪相信为真相信的错误。
又如中国科技大学校长朱清时在接受别人访谈时,称自己相信西藏喇嘛可以用内功融化披在身上的冰毯上的冰。这种相信对科学实践来说也只是一种伪相信。因为他所相信的事物,在没有外界不可抗力的作用下,足以被证明是一个不可能事件;即使在有外界不可抗力(如外星人之类)的作用下,也只能是一个小概率事件。如果真是外星人所致,前面已经分析,外星人和地球人打交道的概率不超过10^(-6),而外星人帮助喇嘛融化冰毯,概率只可能更低。这种小概率事件对于指导科学实践已经没有意义。但是朱院士在访谈中侈谈科学和哲学,并且以确凿的语气认为,喇嘛的拙火“就是科学”,这种认识显然也犯了以伪相信为真相信的错误,是伪相信性质的人文式相信在越俎代庖指导科学,所以是应当受批判的言论。公开发表这种言论,更是与朱清时的院士和科技大学校长身份不相匹配的。
我想那些赞同王晋康或朱清时的人们,也应该慎重地考虑自己对这个
问题的认识是不是太简单。
生命起源进化的高概率事件:统计(生物)化学
摘要:生命的起源和自然进化有他自己的生命动力学--非线性动力学,他是有较高概率或较高条件概率的易发生事件,是信息进化,统计生物化学的结果,它有别于传统进化论的低概事件.
从生物和非生物事件发生概率的角度看,传统的生物起源和进化观点都认为,生命的出现或创生是与无生命的物理事件雷同的等概率或低概率事件[1],P→0,或P=0,即生命的起源或进化是自然界中无数可能发生的事件(或组合)中极少或根本不可能发生的极低概率事件(或组合),P≈0?但从物理、化学(无机化学、有机化学)生物化学、生物等系统的发生、发展、演化的过程(进程)看,其各系统中特有事件发生的概率是逐渐增高的,并且有极高的专一性、特异性.从最初的经典物理--热力学、分子物理学的等概(均匀、均衡、一种几率、能量均分原理)事件,到量子物理的量子化(间断,分立)的概率分布----高低概率事件的混合;从统计物理学的"全同粒子的不可分辨性原理",到化学、生化、生物系统中实际存在的"非全同粒子的可分辨性(原理)"----"统计化学、统计生物化学、统计生物学",与非线性动力学--混沌学、分形学的间断、不连续、不等概率事件才是生物从无序、无生命的"东西(死物)"进化为有序、有生命的生物,及丰富的自然生物种群的机制!它是达尔文进化论的拓展,也是"信息进化"的新途径和轨迹.
化学、生化、生物系统及统计(生物)化学是大大有别于物理系统或统计物理的,常有特殊高概率事件(化学反应,化学变化,Pch—×→0,即Pch≠0,Pch→a)发生的非物理、非等概事件的系统.(平庸的)物理变化、物理性反应中的质点或粒子常是(假设)无差别的.各粒子间的相互作用也是等同、无优先次序、无选择性的等概、同级、遍历或各态历经、"无智能"的均匀系统:无特殊事件--各事件都是均等的无差异共性事件(非线性有序物理过程除外).而化学、生化、生物界确到处充满了特殊事件(有差异事件)--个性事件"化学反应".生化、生物系统中的"质点、粒子"是有差别、不等同、有优先次序、有选择、有识别、非等概、多级、多层次、间断、跳跃、"有智能"、"不均匀"的系统或事件元、组的集合.
1.物理事件的概率说
物理系统中,系统处于第i种状态的概率(几率)Pi和物理量M取值Mi的几率是一致的.如果N是测量M的总次数--微观状态总数或粒子总数,ni是测量中发现M取Mi的次数或第i种状态下的微观状态数或粒子数,则
Pi = lim (ni/N)
N→∞
对于状态是连续变化的系统,量M从M到M+dM范围中的值的概率是
dP(M)=ρ(M)dM
式中ρ(M)是概率密度或概率分布函数。有平均概率Pi和平均状态或平均粒子数ni,及信息(状态)守恒或不灭律.
在经典统计物理中遵从"能量均分原理",Pi基本与平均概率Pi一致,即Pi=Pi.对量子统计有"准经典的近似"方法,相空间中粒子数的分布函数,及最可几分布问题(函数,概率).多用平均粒子数ni表示.
2.化学事件的概率:"统计化学"的起源
对于可逆的化学反应系统:
A+B←→C+D
两两"粒子"间的碰撞(反应)总数共有N=42=16种.其中,粒子A与A、B与B、C与C、D与D、A与C、B与D间的碰撞(反应)与物理系统类似,不发生化学反应,算无差别、无差异的同一或等同状态,即每一对碰撞的物理状态数Nph=1=NAA=NBB=NAC=...,产生物理碰撞的概率Pph=Nph/N=1/16=0.0625,及Pp=12/16=3/4=0.75,但是,它们发生化学反应的概率是Ppc=Npc/N=0/16=0;而A与B、C与D不同于物理碰撞,可发生化学反应,并且比A-A、B-B、C-C、D-D等间的作用更优先、更强烈,且具有选择性、高亲合力和针对性(特异性).其A+B或C+D的化学碰撞--反应的状态数各为2=NAB=NCD,合并的化学状态数Nch=4,故此系统发生化学反应(碰撞)的概率为
Pch=Nch/N=4/16=1/4=0.25, PAB=PCD=2/16=1/8=0.125
显然,化学反应的机会较不发生化学反应的机会(物理碰撞-无化学-特殊反应或有差异的变化)大许多,Pch>Pph、PAB=2Pph、Pch>>Ppc=0.显示了化学(信息)是比物理学的进化程度更高的系统(机会、概率增加);化学合成、分解反应是较物理过程为高的概率事件---有偏概率,或有较高的条件概率。
3.生物化学事件的概率:"统计生物化学"
在生物化学系统中,生化反应可有:
∑Ai=∑Bj, (i=1,2,...,m;j=1,2,...,n.m=n或m≠n)
若生化、化学反应与物理状态的总微观状态数是N=Nph+Nbio(信息守恒律[2]),生化、化学反应的微观状态数Nbio=∑NAi+∑NBj;显然,物理碰撞发生化学或生化反应或向生命(人工机器人除外)进化的概率为Pphch=0,则发生化学、生化反应状态的概率
Pbio=Nbio/N=∑Pbioi=∑Nbioi/N
Pbioi=Nbioi/N, Pbio+Pph=1
Pbio>>Pphch=0,生化反应过程的概率高于普通物理过程的概率,就象DNA中互补的碱基对腺嘌呤A-胸腺嘧啶T、鸟嘌呤G-胞嘧啶C优先(高概率、概率权重高)结合拷贝复制,碱基对又与相对应的蛋白质-氨基酸优先(高概率、非等概)结合组装蛋白;及其它的生化反应和生化循环等.生物、生化反应的"较高概率事件"或条件概率--信息进化(Pch、Pbio↑;Pbio≠0、Pbio-/→0)、信息统计,才是生命起源和生物进化的关键机制和动因.
4.生物、生命事件的概率--分形分维
生物化学是生命,生物学存在的基础.生化反应的历程、轨迹、路程,不是遍历无缝隙、连续的,就象公路、河流、血管(高概率的通道路径,与不完全充满或占有二维平面的部分面积的低概率的通道周边田野的混合。“……走的人多了,就形成了路”);也有她自己最可几的起源、进化,生成、生长的固定路线、程序或概率分布(规律),和她自己固定的自然演化的轨迹、路线和方式,如非线性动力学(方程):DNA的复制:N=2N(N=1,2,3,...m),细胞分裂;生物的繁衍,生物种群分类(分类树,类别:种、属,、门、纲),人口,种群的消长:Xn+1=μXn(1-Xn)--非线性、混沌、分叉、分形、分维等.其(化学、生化、生命起源、进化机制的)非线性动力学的概率分布函数或统计分布函数有
P(Xi)=F(xi)
对离散随机生命变量
P(X1
对连续随机的生物(生化,信息)变量
X1
P(X1<ξ
X2
ρ(x)是分布密度.总∑P(xi)=1,∑ni=N,信息(状态)守恒不灭定律[2].生命起源进化的非线性动力学轨迹,其填充度是非全满的--不会填满全部的可能性空间,机会(概率Pi)不均等,有高概率事件(有利进化事件)和低概率事件之分.她的分形维数:信息(概率)维数等常有非整数,分数维数,及非等概特征Pi≠Pj.他们趋向演化进化(有序,轨迹线上)的概率高于非演化(无序,平衡态,线外--田野)的概率.生物起源与进化正是在这较高概率(线)条件下的非线性"信息进化"才有可能"自然"形成有序生命,并"战胜,克服"无序熵增倾向,建立了有序,丰富的生物种群和多彩世界.
生命起源和进化遵从它自己的内在规律性或生命的动力学(非线性),就象物理,化学等自然现象一样有同源性,即"非线性动力学--混沌,分形论"的机制.其生命起源进化的非线性非一维的决定论确定性动力学公式中蕴含着(不均衡)随机性--不确定性,而复杂"不确定""随机性"的生命活动中又潜含着决定论的确定性:奇怪吸引子(吸引点,线,面,体),"无形的手";排斥子.生命有它自己的非线性(非一维,非二维,非三维性)的发展进化路径,轨迹.在这轨迹(线)上的事件发生或保留的概率就高,线外的事件发生或存活的概率就低.
无生命的物理,化学世界中广泛存在着类似生命进化的有序分形的形态发生,有规律的分形生长、随机行走、全息自相似的复制、凝聚、结晶等.无生命、无智能的煤灰、粉尘也能有"规则"漂亮的分形凝聚,即有一个凝聚中心(种子、元胞、分形元、分形子)点的"粒子-粒子凝聚(PPA,PARTICLE-PARTICLE AGGREGATION)模型",又叫"扩散-限制凝聚(DLA)模型";和多中心点(起点、起源)的"集团-集团凝聚模型(CCA,CLUSTER-CLUSTER AGGREGATION)",又称"动力学集团凝聚模型(KCA)".生命的起源和进化也与上述无生命单组份尘粒的有序单层次的物理凝聚类似,但他们是复杂性更高,组份和层次更多的化学-物理混合,复合型的"点(粒子)-集凝聚(PCA)和分形生长(模型)".从无生命的尘埃粒子可以粘附聚集("吸纳吃饭")、解聚(排泄)、"复制、代谢"成有序(无生命)形态的功能结构和分界--壁、膜的前身;无生命的"生命分子"--点也能PPA1凝聚合成-分解,复制,代谢生成有序有功用的分形"生命前组元(组合,集合)";许多"生命前组元"--集团又非线性的CCA1聚合-分解、复制、代谢长成"生命初体",进而PCA1或CCA2成"生命基本单位(细胞)"和壁或膜(生命分界),直到生命细胞再多层次的PCAn或CCAn生长自造出更高的有序全息的"生命单元",如人.无生命的质点的简单的初始功能单元,如结合-分解,和细胞中功能分化的各种细胞器,如吸收-消化、信息、产能等单元,与人的更高度分工的组织、器官、系统,有着从小到大,从低级到高级的自相似、准全息的对应--分形关系:高概率的对应关系.生命的发生、发展,起源、进化走着一条"上帝(自然原动力的非线性动力学的法则.看不见的妖)"制定的较高概率的发生.发展、生长变化的优化、优势的优选途径--生命起源进化的新假说:(高概率的非一维--非线性的生命动力学起源进化模型)
出乎意料的人生三问
上课钟响了,班主任来了,但他并没有带书。站在台上半天没有出声,同学们一边笑一边诧异地望着他。
老师扫视着同学:“这节课我们来讨论三个问题。”他问道:“世界上第一高峰是哪座山?”大家哄堂大笑地回答:“珠穆朗玛峰!”老师接着追问:“第二高峰呢?”这下同学们面面相觑,无人应声,老师转过身,在黑板上写下一句话:屈居第二与默默无闻毫无区别。
老师顿了顿,说:“好了,下面我们来看第二问题。有个人烧壶开水,可是等他生好火才发现柴火可能不够,他该怎么办?”同学们议论纷纷,但意见都趋同于赶快去找柴火,或说去借,或说去买。可老师都不置可否,他说:“为什么不把茶壶里的水倒掉一些呢?”同学们一听,一片佩服声。
接下来,老师又说出了第三个问题:“我国古代有一个人,想学好一门立身的本领。他曾经反复的比较,决心去学屠龙之技。于是,他拜名师,日夜苦练,终于有所成。大家说他会怎么样呢?”同学们兴致勃勃,说他肯定能成为英雄、明星,受世人崇拜。有的还旁征博引。老师越听越摇头,他说:“这个人一定会穷苦潦倒一生,因为世上根本就没有龙。”
经过老师一节课的循循善诱,大家终于明白,原来这节课老师要告诉我们的是做人、做事、做学问的道理。那就是做人要力求出色,勇争第一,这样别人才能发现你、记住你;做事要敢于创新,方法灵活,千万不可墨守成规;做学问要学以致用,能将知识转化效益,闭门造车是没有出路的。
的确,这节课,让我们所有的人受益终生。
大学上概率论课,我就很纳闷:这1%的概率和99%的概率有区别吗?
打一个比方:有四张彩票供三个人抽取,其中只有一张彩票有奖。第一个人去抽,他的中奖概率是25%,结果没抽到。第二个人看了,心里有些踏实了,他中奖的概率是33%,可结果他也没抽到。第三个人心里此时乐开了花,一来其他的人都失败了,觉得自己很幸运。二来自己中奖的机率高达50%。可结果他同样没中奖。由此看来,概率的大小只是在效果上有所不同,很大的概率给人的安慰感更为强烈。但在实质上却没有区别,每个人中奖的概率都是50%,即中奖与不中奖。
同样的道理,对于个人而言,在生活中要成功做好一件事的概率是没有大小之分的,只有成功或失败之分。但这概率的大小却很能影响人做事的心态。
人们常说:“希望越大,失望越大”,此话并不无道理。希望越大,成功的概率就越大,由此而麻痹了人的心态——以为如此大的概率也是自己能够成功的筹码,这样在思想和行为上就会有所懈怠。自以为十拿九稳的事,到头来却把事情弄砸了。这并不奇怪,因为所谓的“概率大”已逐渐由“希望”转移到“失望”上面了。一说到把这件事做好的概率微乎其微,做事的人难免心灰意冷,因为觉得机会渺茫。因此而丧失了克服困难的意志,觉得事情做不好那是理所当然。
如果说概率有大小之分,那应该不是针对个体而言,而是从一个群体出发,因为不同的人有不同的信念,有不同的做事方法。把地球给撬起来,这在大多数人眼里是绝对不可能的。但在牛人亚里士多德眼里,他觉得成功做这事的概率那是100%——绝对没问题,只要你给他一个支点和足够长的杠杆。就像前面提到的抽奖一样,25%、33%和50%这些概率只不过是外界针对这个群体给出的。25%的机率同样能中奖,50%的机率也会不中奖,对于抽奖者个人而言,没有概率大小之分,只有中与不中之分。别人说做这件事相当容易,切莫掉以轻心,也许你做这件事会相当困难。大家都说做这件事相当困难,切莫心灰意冷,也许你做这件事能如鱼得水。成功与否,不在概率大小,而在于自己能否清楚地认识自己:容易的事自己是否具有做这件事必备的素质,困难的事自己是否有克服这个困难的潜质。
总之,在自己没做一件事之前,不要在外界评价的“容易”和“困难”之间对号入座。要对自己有个清楚的认识,不要膨胀了“自信”,更不要埋没了自己的“潜质”。不要被“绝对有希望”所蒙蔽,也不要被“希望渺茫”所打垮。记住:生活中的概率有且仅有一个数值,那就是50%。
世界不是天才创造的zz
2008-06-03 13:15
有趣的游戏
前几天晚饭间,老华组织在座的12个人玩一个猜数字的游戏。。游戏规则是这样的。
每人给出一个从0到100之间的数字。把所有人的数字求算术平均值。谁选的数字最接近这个算术平均值的2/3,谁就赢得整场游戏。
这是个很有趣的游戏,建议大家每个人都再仔细读一下题,想一想,试一下?
选一个数,写一个理由,然后再往后看。
分析一下过程
我们来分析一下这个游戏里的每个人。如果每个人都是真的随机的选择的话,大家平均值应该在50左右。50的2/3应该是33.3,对吗?很多人都写了33.3。(当然还有很多人没有想到这一步)
不过多想一步,如果你写了33.3,难道其他的人不会想得和你一样,也写33.3吗?如果这样,你应该写22.2。如果继续想下去,大家的平均值应该越来越小,就是这样。。。
50
33.33333333
22.22222222
14.81481481
9.87654321
6.58436214
4.38957476
2.926383173
1.950922116
….
最后,把问题想得非常地复杂的人的答案是0。
这是我们那天的结果
30
98.16
32
50
12
33.3
22
8
8.2
18
28.68
37
所有的平均数:31.445,它的三分之二是20.96333333。选22的人获胜。
世界不是由天才创造的
老华的很多次游戏表明,无论是什么样的群体,最终的获胜的数字,都在22左右徘徊。群体决策的结果和天才的想法总是有些格格不入。这个游戏告诉我们,这个世界不是由天才决定的。在众人决策的过程中,赢得游戏的人,都是比别人多想一步的人,而不是多想两步或更多步的人。
游戏中的人
这个游戏里面,选择不同的数,或许就代表了不同的人。
先说选超过66.67 的人。在开始游戏的时候,我悄悄对Wendy说,“肯定不会有人选超过66.67的数字的,要是谁要是写了,一定是没动脑子的”。就算是所有人都写 100,获胜的数字也才66.67。结果出来,第二个报出的数字就是98.16。我窃笑。他解释写这个数字的原因是因为没听清楚题。慢着,先别就这样放过这个现象。在现实社会里面,没听清楚规则的人不是比比皆是吗?比方说,做产品的人认为质优价廉用户就会买,而实际上,花高价买差产品的人大有人在,我们不能指望所有的用户都和和业内人士有一样的判别力,一样的了解规则,对吗?
再说选0的。或许这个结果很多人想都想不到,但老华组织的游戏里面,几乎每次都有选零的,而且越理性的群体,选零的比例越高。比如微软研究院30个人里面高达3个人选零。选零的人,沉浸于自己对世界了解的快感中,却知之者甚少。很可惜,在每次游戏里面,比一般人想一步的人就不多,想两步的人更少,经过重重地归迭代到达0的最终境界的人少之又少,我们只好轻叹一声,说,你是天才,但是你赢得不了游戏。或许原本他们在写0的时候,本来也就清楚的知道自己不可能赢得游戏,而他们就是用这种近似自杀的方式向世界宣称,“我放弃获奖,因为我是天才。我可以接受没有奖励,但我不能接受大家不认为我聪明”。我们假想一下,如果天才的理论有机会向每一个参与者传播,让他们理解,跟随天才的选择,说不定他还有一线获胜的机会,不过让每个人了解,从古到今就不曾在天才在世的时候实现过。天才不是疯了,就是穷困潦倒。
然后我们来说选33.3的。他们是正常的,平凡的人。就像数以百万计的洗发水的使用者或者报纸的阅读者一样,再正常和普通不过。在明白无误的规则面前,按照规则办事,用思考指导行动,却不多想更多。33.3的人是社会的大多数,在他们前面,有引领世界的0和推动世界的22;在他的后面,有大量的选择随机数的更平凡的人。是33们,奠定了这个社会的基调。
再说赢得游戏的22。他们也遵循规则,但是比规则前进了一步,不多不少,刚刚好一步。他们提出的方案让大多数人(33)感觉的有道理,却不像天才(0)提出的解决方案那么晦涩难懂。我们假设,如果布鲁诺要是发现一个新的号称是绕地球旋转的星星或许能为他赢得终生的荣誉和财富,但如果走得像推翻地心说,宣扬日心说那般的接近真理,得来的就是8年的监禁和熊熊的烈火了。
社会上除了这些种类,还有很多,在游戏里也在出现。比如说选50 的。他在公布答案之前就解释说,“我知道这个数字肯定会非常小,趋近于0,而我就是想说一个大一点的数字,把平均值拉大,看看是会不会左右游戏的结果”。这叫做“搅局的”或者说“损人不利己”的。现实社会里面有吗?大有人在呀。
天才的悲哀就在于,他搞懂了规则,却没有搞懂人。他自己想明白了,就想当然的以为别人也会想明白。他不但错误的忽略了只想到33的人的存在,更忽略了没有思考的,或者存心不按规则玩的人的存在。毕竟,这个世界不是一个只有天才的世界。
最后说一说8.2,就是我了。我对8.2的分析是,这个人有一点点天才的倾向,却又不能像选0的天才一样潇洒的放弃冠军的奖励;他希望赢得游戏,却又过高的估计了大众思考的步伐; 8.2被天才斥责有太多功利心,却被22嘲笑过于“自作聪明”,算是一个摇摆在理想和现实之间的人。自嘲一下罢了。?
天才的选择
对于这个社会,必然有看得比别人稍微透彻些的,离真理更近些的,我们姑且称之为天才吧。这些已经窥探到天机的天才,在现实世界里面,选零还是选22,这是个问题。
选零,就注定了要放弃大多数人的认可。这认可可能是名声,可能是钱。选零的人,适合当教授,适合当评论者,不合适自己来做商业。
如果你本来想选0,却又为了迎合大众选了22,就注定了你要伪装的傻一些,要被业内人士批判,会被选0或者8的人认为不紧跟潮流。大家看一看现在大凡成功的公司,从美国的软件业网络业巨头们,到中国的门户和成功网站,哪个躲得过选0的人的指指点点?或者说,选22的人是易中天,会用通俗(甚至有些错误)的方式讲史,而选0的人就是严肃的历史学家。通俗文学,流行音乐和热门网站,在大众和同行两个世界里面有完全不同的声名,大多是因为这样。
没有选0的人,这个世界何以进步?选零的天才们艰难的拖着这个世界前行。我对他们表示敬佩。只可惜,他们获得的只有一小部分人的敬佩。对于选22个人,帮助了无数选33的人改善了生活,他们也获得了巨大的商业成功。没有22,世界怎么可能从33过渡到更小的数字去呢?我对他们也表示尊敬。
世界毕竟不是由天才创造的。
好了,下面是包括你在内的三十个人的结果。看看平均值是多少?在现实中,你又会选几呢?
|
【zz】经典 [转]
2006-11-21 00:35
2004-9-3 星期五(Friday) 晴
1,记住该记住的,忘记该忘记的。改变能改变的,接受不能接受的。
2,能冲刷一切的除了眼泪,就是时间,以时间来推移感情,时间越长,冲突越淡,仿佛不断稀释的茶。
3,怨言是上天得至人类最大的供物,也是人类祷告中最真诚的部分。
4,智慧的代价是矛盾。这是人生对人生观开的玩笑。
5,世上的姑娘总以为自己是骄傲的公主(除了少数极丑和少数极聪明的姑娘例外)。
6,如果敌人让你生气,那说明你还没有胜他的把握。
7,如果朋友让你生气,那说明你仍然在意他的友情。
8,令狐冲说“有些事情本身我们无法控制,只好控制自己。”
9,我不知道我现在做的哪些是对的,那些是错的,而当我终于老死的时候我才知道这些。所以我现在所能做的就是尽力做好待着老死。
10,也许有些人很可恶,有些人很卑鄙。而当我设身为他想象的时候,我才知道:他比我还可怜。所以请原谅所有你见过的人,好人或者坏人。
11,鱼对水说你看不到我的眼泪,因为我在水里.水说我能感觉到你的眼泪,因为你在我心里。
12,快乐要有悲伤作陪,雨过应该就有天晴。如果雨后还是雨,如果忧伤之后还是忧伤.请让我们从容面对这离别之后的离别。微笑地去寻找一个不可能出现的你!
13,死亡教会人一切,如同考试之后公布的结果——虽然恍然大悟,但为时晚矣~!
14,你出生的时候,你哭着,周围的人笑着;你逝去的时候,你笑着,而周围的人在哭!一切都是轮回!!!! 我们都在轮回中!!!!
15,男人在结婚前觉得适合自己的女人很少,结婚后觉得适合自己的女人很多。
16,于千万人之中,遇见你所遇见的人;于千万年之中,时间的无涯荒野里,没有早
一步,也没有晚一步,刚巧赶上了 。
17,每个人都有潜在的能量,只是很容易:被习惯所掩盖,被时间所迷离,被惰性所消
磨。
18,人生短短几十年,不要给自己留下了什么遗憾,想笑就笑,想哭就哭,该爱的时
候就去爱,无谓压抑自己。
19,《和平年代》里的话:当幻想和现实面对时,总是很痛苦的。要么你被痛苦击倒,要么你把痛苦踩在脚下。
20,真正的爱情是不讲究热闹不讲究排场不讲究繁华更不讲究嚎头的。
21,生命中,不断地有人离开或进入。于是,看见的,看不见的;记住的,遗忘了。生命中,不断地有得到和失落。于是,看不见的,看见了;遗忘的,记住了。然而,看不见的,是不是就等于不存在?记住的,是不是永远不会消失?
22,我们确实活得艰难,一要承受种种外部的压力,更要面对自己内心的困惑。在苦苦挣扎中,如果有人向你投以理解的目光,你会感到一种生命的暖意,或许仅有短暂的一瞥,就足以使我感奋不已。
23,我不去想是否能够成功,既然选择了远方,便只顾风雨兼程;我不去想,身后会不会袭来寒风冷雨,既然目标是地平线,留给世界的只能是背影。
24,后悔是一种耗费精神的情绪.后悔是比损失更大的损失,比错误更大的错误.所以不要后悔 。
25,日出东海落西山,愁也一天,喜也一天;遇事不钻牛角尖,人也舒坦,心也舒坦。
|
Dan in Real Life
2008-03-03 20:54
Dan in Real Life,小修又在看电影了。。。
喜欢一边看电影,一边写下有感触的东西,害怕看完之后就会忘记,想留下每一份记忆。。。现在开始吧~
dan,一个不愿意接受3个女儿已经长大的事实,总是时时事事管着女儿们。。看着他就想起可爱的赵爸爸,赵爸爸也是一个不知道女儿已经长大的爸爸,u r a good father,but sometimes a bad dad...喜欢小女儿的这句台词,而dan却始终认为是姐姐们教她说的,不知道小女儿已经足够大且能够有自己的想法了。。想到赵爸爸,好像也是这样,那个可爱的爸爸似乎不愿意承认小修已经长大的事实,总是还是喜欢用爸爸的身份和小修说话,好幼稚的爸爸哦,赵爸爸喜欢和小修聊天,喜欢和小修一起喝茶,看着小修一点点长大,爸爸心里是不是很复杂呢?!赵爸爸会不会担心小修有一天会离开家呢。。他会舍不得吧。。
oops~!dan's dream girl is his brother's girlfriend。。。天,电影总是这样,喜欢安排这种情节,dan在书店碰到了Marie,当他神经恍惚的回到家,默默的告诉家人:i met sb,she's reli sth...的时候,弟弟把女朋友带进客厅。。这是什么样的感觉。。可怜的孩子。。这让我想起曾经问朋友,有没有爱上过兄弟的女人,或是女友的好友。。。那个时候,心会痛吧,who knows~看到自己喜欢的人和自己的兄弟谈情说爱,一向稳健的dan开始语无伦次,开始“乱说话”了,家人们都“怒”了。。。love drives ppl crazy...and,life is full of disappointment...看到dan的样子,觉得他好可怜啊。。。and love is not a feeling,love is an ability...how could u tell u love sb in three days?....and....Plan to be surprised....did i just died because an angel just walked into the room?!....I'll forgive ur ur past if u just forgive me mine...这些都是个人觉得还不错的Lines。。。剧终时,皆大欢喜,有情人终成眷属。。。
没有什么特别的,只是随便写写~
wtever...
ending for today~
|
活在当下,be myself——《沉思录》读后感
2008-03-22 17:08
“希望是本无所谓有,无所谓无的。这正如地上的路;其实地上本没有路,走的人多了,也便成了路。”鲁迅先生在《故乡》中出奇地定义“路”的形成,也许这就是我们所谓的从众心理。然而,意大利诗人但丁在《神曲》中挥毫泼墨“走自己的路让别人说去吧!”处于两难境地的我们,站在十字路口,左转意味着赶上潮流,同时也注定碌碌无为;右转张扬了个性,但也要承受来自外界的奇异的眼光。如何抉择?这并不像投硬币一样轻松,旋转、抛起、落地,正反两面只是一秒钟的定格。我们也要做一回罗丹手下的思想者。
灵魂碰撞出火花,思想用醒悟收场,我就是我,一个独特的生命个体,我不是天使,没有飞翔的翅膀,我不是精灵,也有犯错的时候。我就是我。我是80后,天生充满了激情和活力,天生追求刺激,追求不一样的感觉。当我站在十字路口时,我要向右转,去体会不一样的人生境遇,be myself 。
其实我们并不是孤独的,我们有“前车之鉴”,新定义下的前车之鉴。
全球个人电脑软件领导品牌——微软公司的董事长兼CEO 比尔·盖茨就是一个与世俗眼光抗衡的杰出代表。他的经历是我们的典范,走出社会一概的精神桎梏,他收获的岂止是一点点。从小,盖茨就和别人不一样。升初中时,因为他的兴趣与6年级的同龄孩子迥然不同,父母决定送他到一所有名的私立中学就读来满足他的智力发展。
1993年,盖茨进入哈佛大学。正当人们认为盖茨处于正常的生活状态时,他又做出了一个惊人的决定。大三那年,盖茨离开哈佛,专心致力于微软的工作。哈佛,对亿万学者而言意味着什么?更何况,那时的微软是处于怎样的发展阶段啊?正是盖茨坚持心中的追求,明白自己要的到底是什么,并且迈出了自己坚实的步伐不管别人怎么说,才有了今天盖茨。
同样,篮球明星科比布莱恩特懂得什么才是自己的人生。他有优秀的高中成绩以及良好的SAT考试成绩,一般人都会选择读大学,但科比是“二般人”。他还是决定不读大学而直接进入NBA。在这里,他将作为NBA顶尖球员在四年内赚到几百万美元,并且是奖项大满贯。科比做自己,超脱寻常的自己,于是他得到非比寻常的价值。
我们也可以。生活在世界上,容易的是生活下去,不容易的是活出特色,活出精彩。做一回自己,不要顾及他人的思想,他人的意见,只要认为是对的,是自己想要的,无论多么卑微,多么渺小,坚持它,实践他,你就可以成就它,同时也成就了你自己。Just be yourself.我也会一如既往,be myself .
有感文段:
判断每一个符合你本性的言行,不要受来自任何人的谴责或话语的影响,而如果做或说一件事是好的,不要把他想做对你是无价值的。因为那些人有他们特殊的指导原则,遵循着他们特殊的活动,你不要重视那些事情,而直接前进,遵从你自己的本性和共同的本性,遵循二者合而唯一的道路。
我按照本性经历所发生的事情,直到我倒下安息,直到我呼出的气息化为我每日吸入的那种元素,直到我倒在这块大地上——我的父亲从它收集种子,我的母亲从它获得血液,我的奶妈从它吸取奶汁,在许多年里我从它得到食物和饮料的供应;当我践踏它,为许多的目的滥用它是,它默默地承受着我。
《沉思录》选摘
一日之始就对自己说:我将遇见好管闲事的人、忘恩负义的人、傲慢的人、欺诈的人、嫉妒的人和孤僻的人。
不要老想着你没有的和已有的东西,而要想着你认为最好的东西,然后思考如果你还未拥有它们,要多么热切地追求它们。同时无论如何要注意,你还没有如此喜爱它们以致使自己习惯于十分尊重它们,这样使你在没有得到它们时就感到烦恼不安。
——这只黄瓜是苦的。——那就扔掉它。——道路上有荆棘。——那就避开它。这就够了。不要再增加什么,问为什么这世界上有这种东西啊?
哲学家皇帝的沉思
文:王佩
你想获得帝王一样尊贵的享受吗?不必奢望独中亿元大奖,或者住进花园洋房,只要花费20元或更少的钱买一本《沉思录》就够了。
《沉思录》的作者是古罗马的皇帝马可·奥勒留(公元121年~180年)。跟古今中外荒淫的暴君不同,他没有三宫六院,酒池肉林,他一生中大部分时间在马背和篝火边度过。在戎马倥偬的间隙里,他写了一本给自己看的书,一共十二卷,就是这本《沉思录》,也翻译成《马上沉思录》。
这是很多国家的领袖们的案头书,据说克林顿就喜欢读它,不知道是不是因为里面说过——“那么,尽情快乐地生活吧。”且不去管它。对于我们这些凡夫俗子们来说,这本书的价值在于给我们兜头浇了一盆冷水,又像喝下了一杯苦咖啡。原来,两千年前的烦恼跟今天没什么区别,强大帝国的皇帝跟今天的上班族都有着同样的困惑。奥勒留好像伸手拍着我们的肩膀,目光灼灼,对我们说:好自为之吧,你并不能改变世界。生活像一锅烂白菜汤,谁不得一仰脖一闭眼喝下去。付出你最好的努力,但要始终认清你的局限所在。
从哲学传承上讲,奥勒留是斯多葛学派的传人,在这里我不准备“Google”一堆古希腊哲学的教条来冒充知识分子。在《沉思录》中,我读到了佛陀、孔子、老子、圣经的思想。可见,智慧是跨越时代、地域、宗教和种族的。正应了那句话:东方圣人出,西方圣人出,其心同,其理同。
简单归纳一下,《沉思录》说了下面这些道理:把你自己当成自然的一部分;接受命运,不要抱怨;不要为身边有讨厌的人而大惊小怪;接受变化,死亡也是变化的一部分;万事都是重复的,人活四十跟千岁也没区别;趁活着的时候,追求简朴、美德与快乐;压力是正常的,是宇宙的一部分,忍耐也是正义的一种;我们生来不是为了追求自己的伟大,我们为他人而生;既然平静与快乐在我们内心,为什么要向身外去求呢?
当然,如果奥勒留像我这样的行文的话,那就不是“马上沉思录”,而是“的士咏叹调”了,也许还要加上“无病呻吟”几个字。像无数先哲一样,奥勒留的文笔优美舒扬,擅用比喻,充满了诗意。比如他说——
“假设人们杀死你,把你切为碎片,诅咒你。那么这些事情怎么能阻止你的心灵保持纯净、明智、清醒和公正呢?例如,如果一个人站在一泓清澈纯净的泉边诅咒它,这清泉决不会停止冒出可饮用的泉水,如果这个人竟然把泥土或垃圾投入其中,清泉也将迅速地冲散它们,洗涤它们,而不会遭到污染。那么作为拥有一种永恒的泉水而不仅仅是一口井的你将怎样呢?要每时每刻地塑造你自己,达到与满足、朴素和谦虚结为一体的自由。”
不过,这本《沉思录》的中文译本可能并不适合朗读,它是根据乔治·朗的英文译本转译的。而朗译存在一个问题:风雅有余,信达不足。中文译本喜欢用绵长的句子直译,偶尔有叠床架屋、不知所云的地方。这不能不说是一个遗憾。诚如译者何怀宏所说:期待将来有直接从希腊文翻译的本子问世,让现有的这个译本完成其历史使命。
马可·奥勒留:乱世帝王哲学家
马可·奥勒留:(Marcus Aurelius,公元121年~180年),原名马可·阿尼厄斯·维勒斯,生于罗马,其父亲一族曾是西班牙人,从维斯佩申皇帝(69年~79年在位)那里获得了贵族身份。马可·奥勒留在位近二十年,这是一个战乱不断、灾难频繁的时期,洪水、地震、瘟疫,加上与东方的安息人的战争,使罗马人口锐减,贫困加深、经济日益衰落,即使马可·奥勒留以其坚定精神和智慧,夙兴夜寐地工作,也不能阻挡古罗马帝国的颓势。在他统治的大部分时间里,尤其是后十年,他很少呆在罗马,而是在帝国的边疆或行省的军营里度过。《沉思录》这本自己与自己的12卷对话,大部分就是在这种鞍马劳顿中写成的。
马可·奥勒留在希腊文学和拉丁文学、修辞、哲学、法律、绘画方面受过很好的教育,晚期斯多葛学派代表人物之一。奥勒留也许是西方历史上唯一的一位哲学家皇帝。
帖子82090 积分118036 注册时间2005-10-18 查看详细资料
读《沉思录》
3# 2008-5-3 12:05 x2 只看该作者 文:张治 出处:文汇读书周报 2008年4月
马可·安东尼努斯·奥勒留是罗马帝国安敦王朝(公元97-192年)的一位君主。他本名马可·安尼乌斯·喀提琉斯·塞尔维儒斯,其父死后,哈德良帝为之更名为安尼乌斯·维理息穆斯,并指定他作为继嗣王位之人。奥古斯都大帝死后,罗马文化进入所谓的“白银时期”,克劳狄乌斯朝和弗拉维乌斯朝的多数君主崇尚奢华、性格乖张,俱为罗马帝国由盛转衰埋下种种隐患。而安敦朝诸帝持政多清明闲德,崇文尚俭,为帝国内部的臣民带来一个相对和平宁静、学术昌明的世纪,以致后人称西元二世纪为“罗马和平时期”。这时期帝国疆界也达到历史上最广大的范围,其影响之远,竟直波及到遥远东方的中国。“安敦”之名本就是汉代人的译法,见《后汉书·西域传》:“至桓帝延熹九年,大秦王安敦遣使自日南缴外献象牙、犀角、玳瑁,始以一通焉。”根据张星烺先生的研究,这位安敦王即马可·奥勒留。公元162至165年,他命令东征安息,屡战屡胜,美索不达米亚复归罗马帝国版图,波斯湾头诸地复通,往东方海道无复阻障,所以他的使者才能于公元166年得至中国。
从书中内容来看,《沉思录》与写作时的外部世界似乎毫不相干。全书共十二卷(“篇”),第一卷是以个人身份作的致辞,对自己平生思想有所沾溉和陶铸的亲友师长乃至神明一一表达感恩之心;而此后的十一卷则全属私密的日记体,第二卷第一节的开端:“一日之始就对自己说:我将遇见好管闲事的人、忘恩负义的人、傲慢的人、欺诈的人、嫉妒的人和孤僻的人。他们染有这些品性是因为他们不知道什么是善,什么是恶。”这可以说是奥勒留对自己皇帝生涯的一个总述,此后他不断描述身边之人种种的恶劣品质,反映出他对所处环境的厌倦:“每一件发生的事情都像春天的玫瑰和夏天的果实一样亲切并且为人熟知,因为疾病、死亡、诽谤、背叛以及任何别的使愚蠢的人喜欢或烦恼的事情就是这样”(第四卷第四十四节)。他以为自己对于善恶有着明确的判断能力,这产生于他对世间一切事物均变化无常的看法(比如他提到前朝先帝时代的那些生命和历史上早已消逝分解的人事一样俱不复存在了),或许可看作是奥勒留的“齐物论”,他由此以为,没有任何事物可以被当作一种善去追求,或是被当作一种恶去畏惧的。故而他有意选择一种平静无欲的人生道路。如他所推重的斯多葛后期哲学家爱比克泰德一样,奥勒留也将存在于人心中的“神明”(不同于希腊罗马传统中的人格化的神祗,带有柏拉图主义的色彩,更接近于基督文明中的上帝)视为崇拜之对象,人应该顺应神明所赋予之的人生角色,不可违反本性和他自己应担负的责任。
据西人研究,马可·奥勒留写作《沉思录》的时间应在公元170年以后,如此一位精力充沛、军机繁忙的马上皇帝,何以在征伐劳顿间写了这么一部“独语”的著作,即如何怀宏先生在前言中所说的“自己在同自己对话”?其实这与社会思想风气和政治传统有关。从表面上看,尼禄、韦斯帕芗、图密善这几个皇帝都曾驱逐各派哲学家出境,而像哈德良、马可·奥勒留又广泛地支持希腊学术,尤其奥勒留本人曾在雅典创办了允许学园派、逍遥学派、伊壁鸠鲁派和斯多葛派哲人共同讲学的哲学学校,颇有点儿“兼容并包”的意思。但实际上,自奥古斯都到奥勒留,罗马君主一直将所谓“公众福利”视为自己政治功绩的最高准则,就连暴君尼禄,起初在位五年里,他老师塞涅卡对之还具影响力时,也不例外。据西塞罗《论共和国》,这种追求实源自斯多葛哲学在罗马帝国的传播。换言之,斯多葛哲学虽是外来思想,却与罗马帝国的立国理想能够不断发生契合。国人多喜谈论古罗马人之骄奢放纵,这实则属于东方行省文化的侵蚀,而其本身具有严恪板正之更为传统的一面,却为俗见所认识不足。
奥古斯都之后,罗马帝国出现过三位斯多葛派的哲学家:一个是尼禄时的重臣小塞涅卡,一个是自由民爱比克泰德,一个就是马可·奥勒留。人们常常以斯多葛派与犬儒派的渊源为理由,认为塞涅卡口口声声倡禁欲、崇内省、尚独处,生活中却独揽大权,兼具狡狯之巨富与善谋之政客的两重身份,言行不一;而奥勒留位居至尊,更不宜审视其哲学思想的实际价值;惟有奴隶出身的爱比克泰德,才算是达到了体用二端的彻底贯通。塞涅卡固可非议,乃因其著作属于显性的,公之于众的;但奥勒留作《沉思录》,追随的是爱比克泰德无心于著述流传之态度,其写作本是隐性的,私密的,不具有故作标榜的意味。此外,奥勒留书中对于自己身份、命运虽不感快乐、骄傲,然也并不逃避,他认为亚历山大大帝和他的马夫其实都一样属于宇宙中质料的一次短暂的组合,他们死后也会回到同样的地方。做皇帝的意义,就在于完成属于他应该完成的那些工作:以欢迎的眼光看待和接受一切,根据其价值运用每一事物。因此而言,以其社会身份而废其言论价值,至少对于奥勒留来说是不公允的。
具有西班牙祖籍的奥勒留帝,其《沉思录》则是以古希腊语写成,此两者俱反映出当时行省在罗马帝国的政治、文化中的地位和作用。二世纪乃是罗马世界的“希腊文化复兴”时期,著名的作家普鲁塔克、琉善与爱比克泰德、奥勒留一样都是以希腊语著述。何怀宏先生译文转出于英译本,典雅端庄之余,未免以不能校核原作为憾。还望来日有心之人能够再贡献一个更渊重深厚的新译本。
原文链接:http://www.yuedu.org/thread-79590-1-1.html
- 核心提示:2008年的五四,中国青年无可回避地面对新的世界、新的使命。
人民网5月4日报道
曾经以为历史的舞台很高很高,我们今天却站了上来!
感谢奥运,感谢圣火,感谢全世界给我们加油和鼓励的人们。同时,我们也要感谢那些对中国的崛起心存疑惧和敌视的人,感谢所有傲慢与偏见、遏制和打压、误解和谩骂。风,让火燃得更旺;雨,将浊气一扫而空。风雨中,我们登上舞台,宣读这一代中国青年的五四宣言。
在许多人眼里,我们曾经是那样的脆弱、幼稚、孤独、另类甚至卑微。
在许多人眼里,我们“独生子女”“小皇帝”,从小娇生惯养、我行我素,不懂得兄弟姐妹的友爱,不懂得对父辈心怀感恩;我们被“素质教育”折磨得死去活来,沉迷网络游戏,缺乏传统文化修养,更不要说什么远大理想。
在许多人眼里,我们在不该早熟的时候早熟,在需要成熟的时候懵懵懂懂,超女快男是我们的标签,我们“既缺乏50后与祖国共命运的伟大情怀,也缺乏60后追求精神解放的觉悟,同样缺乏70后善于自省的精神”……
我们读小学时,读大学不要钱;
我们读大学时,读小学不要钱。
我们没能工作的时候,工作是分配的;
我们可以工作的时候,撞得头破血流才勉强找份饿不死人的工作。
我们不能挣钱的时候,房子是分配的;
我们能挣钱的时候,却发现房子已经买不起了。
我们没有进入股市的时候,傻瓜都在赚钱;
我们兴冲冲地闯进去的时候,才发现自己成了傻瓜……
然而,就是我们这群人,从一地鸡毛的琐碎生活里抬起头来,在祖国最需要的时候挺身而出,发出震撼世界的呐喊!
卡弗蒂们巴不得我们都是“愤青”,可相当遗憾,我们不是。我们学过历史,我们不是“造反派”;我们痛恨暴力,所以才对拉萨狂暴的“藏独”深恶痛绝;我们珍视和平,我们深信,再给中国一代人和平发展的时间,我们将对人类做出更大的贡献。
卡弗蒂们巴不得我们都是暴民和匪徒,可相当遗憾,他们的诅咒永远只是诅咒。既然有分辨虎照、羚羊照的眼力,我们就不会分不清善恶和是非;既然有捍卫火炬的勇气和信心,我们就有“放过法国人宽恕西方人”的宽容和大度;既然有在巴黎共和国广场慷慨陈词的雄辩口才,我们为什么要学卡弗蒂,令人不齿地攻讦和谩骂?抵制?你是说抵制吗?那些人可以用“抵制奥运”来威胁我们,我们为什么就不能以牙还牙、吓唬他们一下?(如果让家乐福受惊了,我们在此深表歉意——等风波过去,我们会去采购很多很多)哈哈!
总结圣火风波,必须承认,我们对江湖的险恶估计不足。我们曾理所当然地认为,一个13亿人口的国家走向繁荣,在任何人眼里都是世界之福,所有人都会乐见一个古老民族的复兴,分享我们凤凰浴火的喜悦。然而,剧情跳出了我们温情、善意、阳光灿烂的剧本,以一种复杂得多的章节展开。“同一个世界,同一个梦想”,暂时还只是一个梦想。
的确,西方对中国存在误解和偏见。但坦诚地讲,我们对西方文明的理解同样可能失之肤浅。这种肤浅,让我们容易将对方的理念和行为,局部与整体,政府、传媒与民意混为一谈,迷失其间;这种肤浅,让我们往往误把特定的游戏规则视作普世价值,把竞争中的利益权衡视作文明冲突,时而艳羡邻人的富贵高雅,渴望倾盖相交,时而又高筑藩篱,鸣鼓而攻。
从历史的角度,中华文明的宽广深厚,足以令人自豪;从现实的角度,在国际格局的风云变幻中,我们还是名副其实的New Comer。30年改革开放,我们以经济的腾飞换来了跻身VIP俱乐部的门票,但在很多方面,我们远没有完全做好准备……
2008年的五四,中国青年无可回避地面对新的世界、新的使命。
1919年五四的北京街头,陈独秀、李大钊、傅斯年们高举双臂,接受现代文明的洗礼。那一年,他们中的大多数人,正是我们这个年龄。
从那时开始,1935年一二?九运动,1976年四?五运动,1981年大学生喊出“团结起来、振兴中华”的时代最强音,1999年抗议北约轰炸我驻南使馆……青年爱国大潮引领历史的脉动,将积贫积弱的中国推上自强之路。
今天,这一浪由这一代人掀起,我们站在历史的潮头!
向左走还是向右走?全世界都在注视我们。我们的回答是:向前走!
2008年8月的北京,未必一切都尽如人意,但青年志愿者的微笑是真诚的;北京“的哥”英语可能还有些磕巴,但我们沟通的愿望是那样的强烈。
所有友善、理性、有正义感的朋友,我们都欢迎——我们之间的合作,是这个世界和谐运转的基础;所有跟我们红过脸、打过架的,我们也都欢迎——历史正翻开新的一页,未来世界的命运,取决于今天我们彼此的意愿和交流的深度。
“一个大国,绝不可能指望只在掌声中前进”。无论“挡在中国与世界之间的这堵墙”有多厚重,我们都奋力向前,义无反顾。
今天,我们站上历史的舞台,秉承前辈的血脉,承载世界的目光,历史正倾听这一代人的回答! (本文来源:人民网 )
|
两个曾经相爱的人,一方提出分手,另一方痛苦是肯定了。但是,不管有多痛,分手时,你都不要和曾经爱你的人和你爱的说狠话。能伤害到你的人,一定是你爱的人;能让你受伤的人,也一定是爱你的人。不然,他怎么有机会在你心上刻下伤痕?他怎么有资格让你在情海浮沉?
如果命中注定要分手,你还咬牙切齿地说那些可笑的狠话有什么用?既然人家已经放手,你就不要再握着那点微不足道的感情骗自己了。谁都知道,相爱总是简单,相处太难。相处久了,烈焰激情自然会归于平淡。而爱情与平淡,本来就是一胎孪生。
当初和他牵手,是何等幸福。现在提出分手,也许是你做了让他感到非常失望事。上天给每个人,都预备好一张去地狱的单程车票。关键是,不要把自己当成天使,不然,就有时时被折断翅膀的疼痛。
爱,难分对错,如果你智慧地分清楚了,那就应该学会把错忘记。面对转身的爱情,真诚地道一声“希望你幸福”,比硬着心肠说狠话好。
很多人张大嘴巴高喊:我爱就无怨无悔!都是自欺欺人的鬼话。付出了,在心底都希望有回报。就像有的人,心里明明爱,嘴却硬说恨,这时候的恨,就像是抹在爱表面的一层黄油,是为了掩盖真相。不然,爱火熄了,痛就不会燃烧。不要在分手时做愚妇或做蠢男,不要让对方为当时选择离开你而感到万分庆幸。
一段感情走到尽头,你不要向他倾倒无情的口水来证明你被抛弃的痛苦和无辜。如果那样做,能让你的伤口好得快一点;让你的心理平衡一点;让你重新找回自我的时间缩短一点,那么,你就不遗余力地向曾经爱过你的人和你爱过的人猛烈开火吧!你一定要近距离瞄准,出手时,争取弹无虚发,招招致命。早听说“杀人一千,自损八百。”不相信从你口中说出的狠毒的话,在让对方无地自容的同时,你自己的心一点也不疼?
伤口是爱的笔记,痛苦是人生一笔重要的财富,不要轻易践踏;曾经爱过你的人,前世一定和你有缘,不要语言虐待。如果他今生真的负你了,那是因为你前生负他,红尘轮回,无需计较 |
|
|
突然有种情素,不觉中想起了这首歌。也想到了记住过得一些东西。比如令我一见钟情的书有《穆斯林的葬礼》、《我是女博我嫁谁》。于是联想到近日秋官因为肥姐去世受到责难。想到了亦舒的最爱引用的话
”他日若是相见,吾将何以面汝?以沉默,以眼泪“。爱情中的人是不平等的,如同人生而不平等一样。当两个人已然分开时, 对于那个处于弱势的对象而言,或许不见才是对他最好的方式。从这个角度讲,或许秋官的”无情“是恰恰是因为其有情。
一则笑话,又是关于咱程序员的,有意思啊~~~~~#!!
男孩正走在路上, 一只青蛙将他叫住, 对他说:"如果你吻我, 我就能变成美丽的公主."男孩听后, 弯下身, 把青蛙捡来, 放进口袋里.
青蛙又开口了:"如果你吻我, 把我变成美丽的公主, 我就和你共处一个星期."
男孩吧青蛙掏出来, 冲它笑了笑, 又放回口袋里.
于是青蛙叫起来:"如果你吻我, 把我变成美丽的公主, 我就让你为所欲为."
男孩吧青蛙掏出来, 冲它笑了笑, 又放回口袋里.
最后青蛙问道:"为什么?我告诉过你我是一位美丽的公主, 会与你共度一个星期并让你为所欲为. 你为什么还不愿吻我?"
男孩说道:"我是一个程序员. 我没时间交GF, 但拥有一只会说话的青蛙简直太酷了."
今天当我再次偶然的拿到《感动大学生的100篇散文》时,我再次看到了莫小米的三篇散文,分别是《缔结平衡》,《电话两端》和《选择缺点》。我看了一次就很难忘记的他们。
在今天我学习模式识别的同时,从中的数据模型的讨论与计算,最终都将归结到一点tradeoff(折中或是中庸之道)。然则惊奇的是,这三个文章也不约而同的可以用这个理论来给予解释。
《缔结平衡》是一个残了腿的和一个缺了臂的,两个人的结合的平衡的完美比完美的人的结合要更美。
在就他们两个的个体时,他们选择了最小误差的结果。
《电话两端》是两个男女都期待对方打电话给自己,并在没有接到电话时做了向消极方向的想象,最终美好变得不好,这里他们都走了极端,走了两个不好的极端,试想如果有一个往好里想,打了电话的话。与上一个相反,他们走向了选择了最小误差反方向。
《选择缺点》是说了一个女人选择男人的标准,“既然所有的男人都有缺点,那么就选择那个最点对我伤害最小的吧”。这是最佳的选择了最小误差的结果的一个例证了。
其他的女人选择男人的标准:
曾子墨说,选择和我有一辈子说不完话的人。
通常的标准,选择最优秀的男人。这个最普遍,但其合理之处在哪里呢?简单的说就是局部最大值的选择,但是局部最大值在一个相对较长的时间了变得对全局最大值的影响小的可怜的地步了。
羊皮卷》。可能在很多人的眼里,这只不过是一本虚无缥缈,夸大其词的励志书籍。
也曾经将其弃于桌脚而不顾,然而,几次不经意的翻看之下,却改变了我对很多事情的看法。 书的内容很简单,也很谄媚,通篇都是在鼓励读者热爱一切:
热爱你的朋友,热爱你的敌人,热爱每一次成功,热爱每一次失败。
这本被称为犹太经商圣经的书籍,看起来着实乏味的很。不过,几次反复之后,却会发现隐藏在通篇的一个道理:
积极的态度。
2006-03-16 09:13:29 来自: 第七歌 (成都)
Prison Break / 越狱的评论
昨晚把《越狱》已有的13集全部赶完了,现将感想汇报如下:
1、一定要学建筑学,以防不时之需;
2、要注意知识的积累,没准什么时候就能用上;
3、要学会找人当肉盾(MT);
4、手机必须要有照相功能,最好还能够摄像;
5、精神有缺陷的人是天才,智力有缺陷的人是怪才;
6、在美国网上聊天,两句话别人就能查到你的详细地理位置;
7、不要相信任何人,除了你自己;
8、不要相信任何人,包括你自己(与第7条并不矛盾);
9、有些东西可以超越民族和种族的差异,但是是什么?
10、要勤洗衣物,至少要让别人看起来是这样;
11、不要乱扔垃圾;
12、计划永远赶不上变化,但不要因为这个原因就不做计划;
13、资本主义国家果然是黑白颠倒、善恶不分;
14、看别人越狱永远比越狱的人更紧张;
15、黑老大也干不过变态狂
16、照片有多种用途;
17、手表有多种用途;
18、衣服有多种用途;
19、也就是说,什么东西都有多种用途;
20、继续想……
以上,仅供参考。
最后,再次强烈推荐这部剧集!
we are the world
(written by Michael Jackson and Lionel Richie)
there comes a time when we heed a certain call
when the world must come together as one
there are people dying
and it's time to lend a hand to life,
the greatest gift of all
we can go on pretending day by day
that someone, somewhere will soon make a change
we are all a part of god's great big family
and the truth you know love is all we need
we are the world
we are the children
we are the ones who make a brighter day
so let's start giving
there's a choice we're making
we're saving our own lives
it's true we'll make a better day
just you and me
send them your heart so they'll know that someone cares
and their lives will be stronger and free
as god has shown us by turning stones to bread
so we all must lend a helping hand
we are the world
we are the children
we are the ones who make a brighter day
so let's start giving
there's a choice we're making
we're saving our own lives
it's true we'll make a better day
just you and me
michael - when you're down and out
michael - there seems no hope at all
but if you just believe there's no way we can fall
let us realize that a change can only come
when we stand together as one
-we are the world
-we are the children
-we are the ones who make a brighter day
-so let's start giving
-there's a choice we're making
-we're saving our own lives
-it's true we'll make a better day
-just you and me
努力使全体人民学有所教、劳有所得、病有所医、老有所养、住有所居,促进社会和谐
|