尤里的复仇npatch工具包

小站会根据您的关注,为您发现更多,
看到喜欢的小站就马上关注吧!
下一站,你会遇见谁的梦想?
上帝是公平的吗----从一道投行面试题到Arc Sine Law
& & & &人们常说,上帝是公平的,其实这也是我一直以来做人的信仰。然而当我与友人谈论这个问题的时候,却几乎没有人这么想。事实上,我们不难在身边找到一些朋友,他们似乎一路走来鸿运当头顺风顺水;当然也会有一些人,他们的人生似乎总是跌跌撞撞运气欠佳。
& & & 如果你把这个问题交给数学家,他会怎么想呢?他会首先问你,&你怎么定义公平呢?&。下面我来做一个最简单的模型。假设今天你碰到了一件事情,结果比你想象中的要好,我们说遇到了一件&好事&;反之,如果碰到了一件结果比预期要坏的事情,就说遇到了一件&坏事&。根据我们的常识,如果每个人一生中,&好事&和&坏事&的数量一样多,那么上帝就是公平的。可是你也许会问,我每天遇到那么多事情,&好事&和&坏事&的数量真的会一样多吗?
& & & 我现在用随机过程的简单随机游走(simple random walk)的观点来描述这件事情。假定现在有一个随机过程S,它在零时刻的值是0。并且在某一个大于零的时刻n,它会以二分之一的概率等于前一时刻的值加1,且以二分之一的概率等于前一时刻的值减1。就相当于一个人,他很想知道自己是不是一个幸运儿,于是某一天突发奇想给自己设定了一个计数器,如果他碰到了一件好事,他就加上1;如果他碰到了一件坏事,他就减去1。易知如果这个计数器回到了零点,那么他碰到的好事和坏事就一样多,也就是&运气守恒&。
& & &这使我想起几个月前,我在某投行电面的时候,遇到的一道面试题:一个起始点是0的简单随机游走,它在某个固定时刻n(n&0)之前回到零点的概率是多少?
& & & 这个问题其实不是特别困难,我们需要对终点时刻的过程点Sn进行讨论。因为奇数时刻n,Sn不可能等于0,所以我们不妨假定n是一个偶数。另外不妨假定S1=1,Sn=X。如果X是一个非正数,由过程每一步只能移动1,我们知道该过程肯定经过了零点。如果X是一个正数,那就不一定了。这时候我们可以用对称原理(reflection principle)解出来,即如果该过程经过了零点,每一条样本轨道(sample path)都可以等概率地把零点之前的线段翻转成从S1=-1出发,到Sn=X的轨道。可以验证他们是一一对应的,于是我们能简单地把所有从S1=1到Sn=X并经过零点的路径数算出来,将之除以所有的路径数,我们就能得到经过零点的概率。
& & & 最后我们算出所有Sn=X的概率,并用全概率公式算一下再化简,就能得到原问题的***。巧的是,假定n是偶数,起始点是0的简单随机游走不回到0的概率,居然跟它在n时刻等于0的概率是一样的!该结果可以在Durrett的《Probability: Theory and Examples》第四版第四章里找到,这里就不在赘述了。
& & & 我们用一下著名的Stirling公式近似一下那个结果就可以发现,简单随机游走不回到0的概率,是跟根号n分之一同阶的。也就是说,如果一个年轻人,人生一开始不怎么走运,那么他在某一个时刻n,还是有正比于根号n分之一的概率,从来没有恢复到&运气守恒&状态的。这个数收敛到0的速度不算特别快,所以我们还是经常能看到有些年轻朋友,好像一路走来整体来说都不算特别顺利。
& & & 当然如果你觉得我们强大的概率学家们只能做出这些结果,那真是太小看他们的数学才华了。事实上,我们不仅能算出一个人会回到&运气守恒&状态的概率,我们还能算出一个人在时间点n之前,处于&运气好&(也就是S&0)的时间,占所有时间的比值的分布。而这个&运气好时间比值&,居然是跟最后一次回到零的时间点除以n的比值是同分布的;最强大的是,当n很大的时候,他们收敛到Arc Sine分布!这就是传说中牛叉闪闪的Arc Sine Law了。
& & & 下面我们来看一下这个Arc Sine分布长什么样。
& & & 我们可以看到,它是对称的,而且在0和1附近达到峰值。也是说,即使上帝真的是公平的,人每次遇到好事和坏事的几率都是一样的二分之一,人生最有可能的情况,居然是大部分的时间都处于&总体运气偏好&或&总体运气偏差&的状态。或者用一个交易员作比喻,即使他的策略完全不赚不赔,他也很有可能发现自己在交易的时候,要么大部分时间是赚钱的,要么大部分时间是赔钱的。所以当我们看到有些人好像一辈子走好运的时候,也会释然了,这只不过是Arc Sine Law在作怪。
& & & 好在概率论已经告诉我们,虽然有些人在人生大部分时间都在&总体运气偏好&状态,他总会(以几乎是概率1)回到&运气守恒&状态的。所以上帝其实还是公平的,我们只是需要耐性,去等待那&运气守恒&的一天。
有趣&&转自&
从零开始学游戏编程----可视化编程游戏开发工具学习指南
开发游戏可能是学习编程的理由中最吸引人的一条了。但如何从零开始入门,达到能够开发游戏的编程水平,是困扰无数勇敢少年们的传统难题。作为一名游戏设计师,我没有系统地学习过编程。从5年前开始,我有了自己从头完整开发游戏的念头,于是断断续续地看了很多书,试过了很多入门方法和开发环境,但直到近半年才找到正确的门路。现在我在Unity开发环境下独立制作游戏原型和利用成型的框架完善游戏功能已不成问题。&本文会介绍如何从零开始学习游戏开发编程的方法,希望能为和我一样挣扎在编程大门之外的游戏开发爱好者们提供帮助。不过事先要说明的是,这种学习思路是为了帮助你在做游戏的过程中逐渐学习编写程序,不适用于其他领域,但作为一种入门方法,它能让你在半年到一年的学习之后,做到独立制做小游戏(或原型)。&门外汉学编程的难点&介绍学习方法之前,我们先看看门外汉学编程最常遇到的问题。&第一,程序员们经常说程序语言只是编程工具,但市面上常见的教程都喜欢从语法、算法和程序语言的使用思想开始教学,而不是把编程语言当做解决实际问题的工具来入手。因此,初学者经常耗费很大精力才能理解书上写的算法和思想,却完全不知道理解之后能用来做什么。&第二,很多编程教程虽然配有实例,但一方面例子的学习难度曲线增加得很快,刚看完一个&Hello World&实例,下一个例子可能就变成教你如何分配内存(真实的故事,我的一本学习Objective-C的教程就是这样的)。另一方面初学者在对开发流程不熟悉的情况下,很难做到举一反三,从一个实例里总结出做另外三个游戏的方法,我经常遇见看了三个不同类型的游戏实例,放下书后却连一个游戏都做不出来的情况。第三,很多编程教程为了提高普适性,在使用现成架构方面都很保守,导致了很多重复造轮子的教程出现。例如在前几年Cocos2D(一个用于iOS平台游戏开发的游戏引擎)还没有现在这么火时,几乎所有的iOS游戏开发教程讲的都是如何使用OpenGLES来制作游戏图像,而这些底层架构的实现对初学者来说是根本不可能完成的任务。&因此,适合初学者的学习方针是:从实际需求出发;&怎么做&优于&为什么&(为什么可以在入门之后再慢慢理解);使用允许你偷懒的工具或架构(需要做的越少越好)。这些要求其实很容易满足,***恰恰在看起来和编程关系不大的领域&&可视化编程工具里(Visual Programming Tools)。&可视化编程游戏引擎让你先做再想&可视化编程泛指一切使用可视化元素的操作代替文本输入的程序设计方式,大体上就是像画流程图一样通过连接若干&盒子&和&箭头&来实现程序逻辑。这个概念在游戏开发工具上的应用越来越流行,近年来还有井喷趋势,从老牌的GameMaker、RPGMaker、TorqueGameBuilder、到新兴的GameSalad、Construct 2和Unity都是其中的代表。尽管这些工具和引擎各有不同的开发方式,但它们都能让初学者在完全不懂编程语法和复杂算法的情况下快速实现自己的游戏设计。我之前的态度是宁可抱着&看也看不懂,看懂了也不会做&的书苦学XNA(一个微软发布的使用C#的游戏开发架构)和Cocoa(苹果发布的使用Objective-C的应用开发架构),也不屑于使用GameMaker、GameSalad之类的图形界面开发工具。认为这些工具属于&业余型&,就算能做出游戏来也是旁门左道,不能修炼内功。&直到有一次参加了柏林独立游戏BIG Jam的活动,接触了很多非常优秀的游戏开发者。他们大部分人都把GameMaker和Flash这些简单的工具当做制作独立游戏的最佳选择。原因是他们多年以前开始学习游戏开发时使用的就是这些工具,常年的使用经验让他们能在最短的时间里用这些工具实现想法。而使用这些工具从头到尾制作了大量游戏的经历,也在他们以后学习用编程语言开发游戏时打下了很好的基础。&从那之后,为了快速开发原型,我开始物色入门级的可视化编程游戏引擎。HTML5游戏引擎Construct 2偶然进入了我的视线。花十几分钟学习教程实例之后,我很快用几个小时做出了一个一直在构思的游戏想法(当然想法本身就很简单,而且制作过程中碰到实现困难的设计都进行了进一步简化)。说来惭愧,尽管在主机游戏业从业多年,这次使用Construct 2的开发过程中我第一次感觉到对游戏开发的整个过程和架构有了初步认识。&首先,可视化编程工具里一般都有一个现成的游戏场景(任何游戏开发过程中都需要一个画布或一个摄像机来描述玩家可以看到的图像范围),然后你需要把游戏中需要的各个元素(一般称为Actor,例如主角、敌人、子弹等,这就是编程语言里对象的概念)放进场景里,然后通过关联逻辑模块来让它们快速互动起来。Construct 2的逻辑模块使用了非常贴近编程语言的按行号从上到下的执行顺序。而且你将从教程中学习到,原来游戏开始运行后每一帧都会按顺序执行一遍所有的逻辑,这就是游戏开发的基本框架中最常说的主游戏循环(Main Game Loop)。&除此之外,用户使用逻辑模块时不用担心语法错误和算法的设计,一般这类引擎里都会提供大量现成的算法模块可供挑选。只要专注于设计游戏逻辑,其他事情可以说都是软件自动帮你完成。在观看教程和其他范例项目时也一目了然,学习别人的设计思想更加容易。&通过使用Construct 2独立完成了第一个游戏原型后,我学到了相似的游戏元素可以共享一部分属性(编程语言里使用类和继承的概念);学到了所有活动的游戏元素都需要在每一帧的循环里进行驱动,每帧只运动一小段距离;还学到了应该在主游戏循环的什么位置判断是否Game Over,以及Game Over时进入另一个循环来等待玩家重新开始游戏等内容。&这段经历让我认识到有能力从头到尾制作游戏(或者原型)对于游戏开发的理解有多么重要。但有一个问题出现了&如果可视化工具那么好用,那为什么还要继续学习编程呢?我当时也光顾着高兴了,并没有从可视化编程工具转到真正编写代码的计划,直到&&&由需求出发向编写代码的转型&直到我打算做个稍大一点的战略游戏项目,才开始在各种游戏开发工具中碰壁。接连尝试了Construct 2、GameMaker、Stencyl,可不管哪一个工具都无法很容易地提供我所需要的数据结构。重新审视了需求的增加和工具的局限性之后,我才决定开始学习Unity下的C#编程。在请教了团队里的程序员和有针对性地学习了一部分数据结构知识后,我终于在Unity中搭建出了设计需要的基本游戏结构。并在之后开始正式学习Unity的C#脚本,一步步地掌握了C#里类的继承、列表和字典的使用与委托等难以读懂,学了也不知道怎么用的概念。&刚开始在Unity开发环境里独立制作游戏原型时,我也感觉从零开始独立完成所有的代码非常和困难。但幸运的是,Unity引擎有个特点,就是有一个内容非常丰富的插件市场,其中最流行的插件类型之一就是可视化编程插件。这些插件(PlayMaker、uScript、Antares Universe等)将Unity游戏开发的常用功能打包成函数块,并按需求类别归纳成组,只要花一点时间阅读手册就相当于掌握了Unity里大部分的常用函数功能。之后用户通过连接不同函数块的输入输出接口来实现完整的游戏逻辑。&当时我为了开发一个动画状态很多的动作游戏原型,购买了PlayMaker插件,并且使用这个插件强大的状态和动画控制功能第一次学习了有限状态机的制作和使用。之后又经身边的程序员指点了解到有限状态机在游戏开发中的运用非常广泛,不光是控制动画,还可以用来控制菜单和不同条件下需要不同处理方式的很多游戏逻辑。就像之前的Construct 2一样,我也只在一个项目中使用了PlayMaker的状态机。在了解了有限状态机的基本工作方式后,我在之后的项目中都使用了团队里的程序员开发的纯代码的有限状态机系统(开源的exUnity,还包括其他Unity下的游戏开发实用架构:/jwu/exUnity),完成了从可视化编程到代码编程的转型。&这就是Unity下的可视化编程插件很适合用来学习编程的原因:和其他较为简单的工具的区别在于,Unity使用JavaScript和C#作为脚本语言,这个环境下的可视化编程插件只是把C#函数和脚本打包成了可视化的逻辑块,并没有改变其设计思路。&对于初学者来说,用可视化插件组装起来的游戏逻辑和用C#手动编写的游戏程序几乎是一一对应的,有时甚至能精确到函数段落(例如Antares Universe里的函数块就和Unity的全部函数功能一一对应)。在已熟悉整个设计流程的情况下,只需查阅Unity官方的脚本参考手册,就能完成从可视化编程到文本编程的翻译。我经过可视化工具的启发,很快就发现插件有些臃肿和烦琐,也无法实现一些需求实现。在接下来的两个原型中就越来越多地开始手动编写代码,对工具的依赖越来越小,直到完全抛弃。&现在可以回答前面提出的&为什么有了不用编程就能开发游戏的工具,还要学习编程&的问题了。如果你的所有设计需求都可以被可视化游戏开发工具完成,那么确实不需要进一步学习编程。但如果有的需求无论如何都不能用其他工具完成,那么自己写代码来实现就是唯一的出路,这时你有强烈的需求和目标,就可以通过询问或搜索&怎么做&来学习编程并满足需求。我的程序员好友经常说:&能否学会编程其实只取决于你的需求是否强烈,不得其门而入、或半途而废的都是需求不够明确或不够强烈的人。&&可视化编程工具对于游戏开发者来说就是一个筛选需求的过程:在硬啃编程书籍时,感觉自己有100个需求,但都不知道从哪开始学习、如何去实现;使用可视化工具,可以轻松实现90个需求,剩下10个就被放大并明确化了。接下来依靠上网学习或向他人请教,终究也能自己实现(个别超出能力的需求不要强求,请别人做或者放弃都比钻牛角尖要好)。&可视化编程工具能够培养我们由浅入深的思考习惯。先尽可能地用简单的逻辑去实现设计,如果用&盒子&和&箭头&无法完成,那么你在寻求代码上的解决方案时,就回答了&为什么要用这样的程序设计思想&的问题。经历了这个过程,你对&为什么&的理解会比一开始就去看专门讲解&为什么&的大部头程序书籍深刻许多。而通过实践理解了需求和程序设计之间的关系后,再去系统地阅读程序设计教程效果会好得多。&可视化编程虽然依赖于工具,但也能帮助你时刻把&程序语言即工具&的概念装在脑袋里。之后无论换什么引擎,用哪种语言,首先应该问自己:&这个工具能帮我做什么?我要怎样做才能实现需求?&另外,程序设计和画流程图之间的距离没有想象中那么大,通过反复用可视化编程工具画&流程图&的过程,能够从实践中学习各种游戏设计的实现方法,当你能准确地画出逻辑完美的流程图时,离你写出同样逻辑完美的程序距离已不远了。更重要的是,在这个过程中你实现了自己的想法,创造出了和书上的例程完全不同的东西,对于增强信心和进一步明确自己的学习需求的作用都是巨大的。&想学写程序,就要做程序员的朋友&最后讲下如何从身边的程序员那里获得帮助。初学者想要学写代码,有个程序员朋友能让你获益良多。当你遇到难题时,请把询问的重点集中在需求思路和关键字上,而不是一味求代码。高手提供了思路以后自己实现,或通过关键字自己寻求解决方案,都更有助于水平的提高。&从可视化编程到代码的转化中,也可以尝试使用程序员写的功能库或常用的架构。前文中提到不要重复造轮子,当抛弃可视化编程工具时,就要用现成的功能库来代替。在选用功能库时,自己信任的程序员推荐的东西总会是一个非常不错的选择,他能告诉你一个库的优缺点并且在使用过程中提供技术支持。&我在学写代码的过程中,先是自己用最简单的方式实现功能,然后一边不断阅读和学习同个独立开发团队里程序员的项目结构和代码,再使用程序员设计或惯用的架构来组织自己的代码,这样既能最快地完成工作,又能逐渐养成较好的编程习惯和深入理解程序设计思想。&流行的可视化编程游戏开发工具及简单点评&GameMaker&GameMaker是已有十多年历史的老牌独立游戏开发引擎,也是在世界范围内最受独立游戏开发者欢迎的引擎。巨大的用户基数和独立游戏圈用户们乐于分享的精神使得学习GameMaker非常容易。该引擎有自定义的脚本语言GML,方便用户使用脚本代码实现更高级的功能。最新版本的GameMaker Studio可以发布到iOS、Android和HTML5等各种平台。&Construct 2&比起GameMaker学习起来更容易的HTML5游戏引擎,它的事件编辑界面(Event Editor)非常接近写单一过程的程序代码的模式和习惯,可以帮助初学者学习最基本的游戏循环构架。Construct 2本身的泛用性不如GameMaker,但仍然处在高速发展期,新功能添加的很快。&GameSalad&这是一个很受业余爱好者和游戏开发初学者的图形界面引擎,逻辑功能全部都放在一个Library里,用户只要把需要的功能拖拽出来,填上参数,再和其他功能建立连接就可以实现游戏逻辑。只能在Mac下使用,可以发布到iOS和Android。&Stencyl&使用Flash内核的游戏开发引擎,总的来说和GameSalad比较接近,可视化编程的部分由很多拼图积木组成。逻辑积木的组合方式比较灵活,可以尝试很多解决问题的思路。&Unity&非常流行的民用商用二合一引擎,不过其可视化编程的模块(PlayMaker、uScript、Antares Universe)需要另外购买,对于初学者来说,最大的好处是一开始可以把大部分的功能交给工具完成,然后一点点地添加必要的代码,直到可以完全不借助工具也能写出完整的游戏原型。&作者王楠,毕业于浙江大学,2008年加入德国YAGER工作室至今。2010年联合组建了aBit Games独立游戏开发团队,首个作品《Super SheepTap》获得IGF China 2011最佳音效奖。&本文选自《程序员》杂志2012年08期
我觉得这篇文章说得很有道理。速度就是王道,手游的开发可能拼的就是那么几个月的时间。这个是战场,你在战场上修炼内功无疑是愚蠢的。PS. 我做过一个月的unity的测评,我很喜欢这款引擎。&&转自&
写给即将入行的程序员的一封信
首先,欢迎来到程序员的世界。在这个世界上,不是有很多人想创造软件并解决问题。你是一名hacker,属于那些愿意做一些有挑战性的事情的人。
当你不创造东西时,你只会根据自己的感觉而不是能力去看待问题。
对于下面的文字你不必完全接受,所有这些来自一个其貌不扬的程序员。我喜欢把事情做到最好,而不是对原来的东西修修补补。
仅仅是因为爱好开始做一些创新,这是一个很好的开始!如果你说我要先学习一下再开始做那么你永远不会真正开始。每个人都需要从某个地方开始,所以现在打开你的编辑器开始写代码吧。
下面是一些很重要的建议,虽然有人并不认同,但我保证你看完我的分析以后会站在我这一边。一开始,先不要管算法和数据结构。大多数简单的程序不 需要用到算法和数据结构,所以当你真正需要时再去学习。编程一段时间以后,你就会知道在哪些地方用到他们。这时知道算法的名字并了解它们的功能,然后找一 些相关的论文去理解算法并动手编程实践。如果没有现成的函数库(其他程序员提供的可重用代码),你用自己喜欢的编程语言来实现它。
0. 选择一门好的编程语言,一门你自认为可以用它快速地做出一些有用东西的语言。
不要选择作 为你第一门编程语言。也许选择C语言会给你一种过时的满足感。虽然它比早期的汇编语言提供了更好语法描述,但是今天C(或者 C++)不是能够快速编写软件的语言。毫不偏袒的说,我建议你学习一种动态语言。选择一种你觉得语法(文档)让你使用起来更舒服的编程。为此,你可能需要 花费一些时间来在几种不同的语言之间进行比较。这么做目的不是为了让你感觉更好或者让编程更容易。更快地完成自己的作品并且能够看到成果,才是激励你编程 的源动力。不要选择一门需要某种重量级的IDE(IDE是一种能够帮助你编写并运行代码的工具)才能轻松编程的语言。你所需要的仅仅是一个文本编辑 器。(注:原文并没有标号,是我们加上的,请大家别忘记了哦,我们是从零开始数数的。:) )
1. 选择一个好的编辑器。
编辑器对程序员而言,就是像是弓对弓箭手一样重要。这里有一些推荐的编辑器:
SublimeText 2 如果你刚开始编程,推荐使用SublimeText 2
Emacs 学习曲线陡峭,快捷键复杂。如果你想定制自己的使用习惯,需要学习Emacs Lisp.
Vim 不仅操作简洁而且它默认包含在linux的发行版中,所以深受大家欢迎。我开始使用了2年Emacs。由于Emacs的快捷键操作过于复杂,我的双手开始 经常疼痛,这迫使我转向了Vim阵营。了解Vim的快捷键是非常有必要的。当你在远程的服务器上编辑代码时,你唯一不需要***的编辑器就是Vim。
注意!Emacs和Vim可能已经成为成为古董了。但是,它们都具备一些现代编辑器多不具备的功能。
2. 选择一个你可以从中学到东西的操作系统
Windows不会教会你任何东西。使用Windows你唯一学会的就是打开一个exe(可执行)文件来***软件和使用它。可能刚开始的时候你 会觉得很酷,但是长远来看,如果你立志成为一个人员,可能还是要具备基本的linux知识,尤其是当你要发布程序的时候。Linux也允许你根 据自己的要求来定制程序。Macs也很酷,但是我认为你现在经济上还负担不起。
3. 不要通过复制粘贴来做备份
一个新手程序员通常会把文件复制粘贴到一个临时目录下面来进行备份。这也许也是他们唯一知道的方法。不要那么做!你需要使用版本控制软件。我强 烈推荐使用Git,它是个目前很流行的版本控制工具,而且使用起来非常简单。对一个Git新手,有一个良好的社区和很多参考资源来学习。(除了Git之 外,还有mercurial, darcs, fossil等等。但是我还是建议从Git开始,我有很多的理由来支持Git,这里就不多费口舌了。)
4. 知道去哪里寻求帮助
参加一个和你相关的(你使用编程工具相关的)程序员社区。比如StackOverflow就是程序员的Facebook。那里没有消息状态和回 复,取而代之的是问题和***。除此之外还要学会使用IRC。IRC是一种老式的聊天室,现在还在被大多数开发人员用来分享技术信息和帮助解决问题。
5. 培养你的礼仪
知道什么时候问问题。你遇到的大多数问题都是别人碰到过并且在Internet上能够找到解答的。在IRC或者任何论坛里发问之前,先搜索一下 google(或者blekko)来看看是不是有现成的***。在IRC上问问题需要有耐心。永远记住,人们只是处于好心来免费帮助你。有时你发问以后需要 几个小时才能有回复。所以,耐心等待。除此之外,记得问问题的时候要礼貌。世界很小,你怎么对待别人,别人就会怎么对待你。
6. 结交朋友,技术书籍只能教你解决常见的问题(他们说:书是死的)
当你在捣鼓一些程序或者从程序的作者那里学习,你能学到一些书本上没有的东西。当你散步的时候,请和遇到的朋友打招呼。你肯定不是唯一的程序 员。和其他的程序员一起交朋友一起工作。你会注意到,当一群技术爱好者在一起的时候,不论话题是从什么地方开始,最后总是以技术话题收尾。这是必然的现 象。所以你可以尽情参与。在你的黄金年龄努力编程,我能告诉你的是,我在开始6年前寻找朋友并开始讨论编程,从那时起才学到那些书本和文章不会我的东西。 所以我总是说,我的编程经验有6年,因为只有那个时候开始,我才开始与人交流并开始感觉真正地开始。
7. 参加开源项目
为开源项目编写代码能带来回报。这不仅仅是帮助别人,你留下的代码会被其他人使用或(可能)改进。当别人给你的代码添加功能或者提出修改意见 时,也是在提高你的编程水平。开源不一定要是一个大工程,编写一个下载youtube视频的小程序也是很有用的。更重要的是,你会惊奇地发现你编 写的代码会成为与他人有效沟通的桥梁。其实关于参与开源项目,伯乐在线编译的不少有关程序员的文章都是如此建议。
最后,若干年之后如果本文的内容曾经对你有一点点的帮助,作为回报请写一封类似的信给希望开始编程并不知如何入手的朋友,有可能的话请纠正本文中过时的内容。
智者说过,掌握某个东西需要10年或10000个小时,也就是汉语中的十年磨一剑,所以不用着急。
转自:&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&##4##刘冯振
唉,我入行十年了,但现在很多问题仍然一头雾水。回想起来,无比汗颜。&&转自&
函数式编程初探
作者: 阮一峰 日期: 2012年4月 6日
诞生50多年之后,函数式编程(functional programming)开始获得越来越多的关注。
不仅最古老的函数式语言Lisp重获青春,而且新的函数式语言层出不穷,比如Erlang、clojure、Scala、F#等等。目前最当红的Python、Ruby、Javascript,对函数式编程的支持都很强,就连老牌的面向对象的Java、面向过程的PHP,都忙不迭地加入对匿名函数的支持。越来越多的迹象表明,函数式编程已经不再是学术界的最爱,开始大踏步地在业界投入实用。
也许继"面向对象编程"之后,"函数式编程"会成为下一个编程的主流范式(paradigm)。未来的程序员恐怕或多或少都必须懂一点。
但是,"函数式编程"看上去比较难,缺乏通俗的入门教程,各种介绍文章都充斥着数学符号和专用术语,让人读了如坠云雾。就连最基本的问题"什么是函数式编程",网上都搜不到易懂的回答。
下面是我的"函数式编程"学习笔记,分享出来,与大家一起探讨。内容不涉及数学(我也不懂),也不涉及高级特性(比如和),只求尽量简单通俗地整理和表达,我现在所理解的"函数式编程"以及它的意义。
我主要参考了Slava Akhmechet的。
简单说,"函数式编程"是一种(programming paradigm),也就是如何编写程序的方法论。
它属于的一种,主要思想是把运算过程尽量写成一系列嵌套的函数调用。举例来说,现在有这样一个数学表达式:
 (1 + 2) * 3 - 4
传统的过程式编程,可能这样写:
  var a = 1 + 2;
  var b = a * 3;
  var c = b - 4;
函数式编程要求使用函数,我们可以把运算过程定义为不同的函数,然后写成下面这样:
  var result = subtract(multiply(add(1,2), 3), 4);
这就是函数式编程。
函数式编程具有五个鲜明的特点。
1. 函数是"第一等公民"
所谓(first class),指的是函数与其他数据类型一样,处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。
举例来说,下面代码中的print变量就是一个函数,可以作为另一个函数的参数。
  var print = function(i){ console.log(i);};
  [1,2,3].forEach(print);
&2. 只用"表达式",不用"语句"
"表达式"(expression)是一个单纯的运算过程,总是有返回值;"语句"(statement)是执行某种操作,没有返回值。函数式编程要求,只使用表达式,不使用语句。也就是说,每一步都是单纯的运算,而且都有返回值。
原因是函数式编程的开发动机,一开始就是为了处理运算(computation),不考虑系统的读写(I/O)。"语句"属于对系统的读写操作,所以就被排斥在外。
当然,实际应用中,不做I/O是不可能的。因此,编程过程中,函数式编程只要求把I/O限制到最小,不要有不必要的读写行为,保持计算过程的单纯性。
3. 没有"副作用"
所谓"副作用"(side effect),指的是函数内部与外部互动(最典型的情况,就是修改全局变量的值),产生运算以外的其他结果。
函数式编程强调没有"副作用",意味着函数要保持独立,所有功能就是返回一个新的值,没有其他行为,尤其是不得修改外部变量的值。
4. 不修改状态
上一点已经提到,函数式编程只是返回新的值,不修改系统变量。因此,不修改变量,也是它的一个重要特点。
在其他类型的语言中,变量往往用来保存"状态"(state)。不修改变量,意味着状态不能保存在变量中。函数式编程使用参数保存状态,最好的例子就是递归。下面的代码是一个将字符串逆序排列的函数,它演示了不同的参数如何决定了运算所处的"状态"。
  function reverse(string) {
    if(string.length == 0) {
      
    } else {
      return reverse(string.substring(1, string.length)) + string.substring(0, 1);
由于使用了递归,函数式语言的运行速度比较慢,这是它长期不能在业界推广的主要原因。
5. 引用透明
引用透明(Referential transparency),指的是函数的运行不依赖于外部变量或"状态",只依赖于输入的参数,任何时候只要参数相同,引用函数所得到的返回值总是相同的。
有了前面的第三点和第四点,这点是很显然的。其他类型的语言,函数的返回值往往与系统状态有关,不同的状态之下,返回值是不一样的。这就叫"引用不透明",很不利于观察和理解程序的行为。
函数式编程到底有什么好处,为什么会变得越来越流行?
1. 代码简洁,开发快速
函数式编程大量使用函数,减少了代码的重复,因此程序比较短,开发速度较快。
Paul Graham在一书中:同样功能的程序,极端情况下,Lisp代码的长度可能是C代码的二十分之一。
如果程序员每天所写的代码行数基本相同,这就意味着,"C语言需要一年时间完成开发某个功能,Lisp语言只需要不到三星期。反过来说,如果某个新功能,Lisp语言完成开发需要三个月,C语言需要写五年。"当然,这样的对比故意夸大了差异,但是"在一个高度竞争的市场中,即使开发速度只相差两三倍,也足以使得你永远处在落后的位置。"
2. 接近自然语言,易于理解
函数式编程的自由度很高,可以写出很接近自然语言的代码。
前文曾经将表达式(1 + 2) * 3 - 4,写成函数式语言:
  subtract(multiply(add(1,2), 3), 4)
对它进行变形,不难得到另一种写法:
  add(1,2).multiply(3).subtract(4)
这基本就是自然语言的表达了。再看下面的代码,大家应该一眼就能明白它的意思吧:
  merge([1,2],[3,4]).sort().search("2")
因此,函数式编程的代码更容易理解。
3. 更方便的代码管理
函数式编程不依赖、也不会改变外界的状态,只要给定输入参数,返回的结果必定相同。因此,每一个函数都可以被看做独立单元,很有利于进行单元测试(unit testing)和除错(debugging),以及模块化组合。
4. 易于"并发编程"
函数式编程不需要考虑"死锁"(deadlock),因为它不修改变量,所以根本不存在"锁"线程的问题。不必担心一个线程的数据,被另一个线程修改,所以可以很放心地把工作分摊到多个线程,部署"并发编程"(concurrency)。
请看下面的代码:
  var s1 = Op1();
  var s2 = Op2();
  var s3 = concat(s1, s2);
由于s1和s2互不干扰,不会修改变量,谁先执行是无所谓的,所以可以放心地增加线程,把它们分配在两个线程上完成。其他类型的语言就做不到这一点,因为s1可能会修改系统状态,而s2可能会用到这些状态,所以必须保证s2在s1之后运行,自然也就不能部署到其他线程上了。
多核CPU是将来的潮流,所以函数式编程的这个特性非常重要。
5. 代码的热升级
函数式编程没有副作用,只要保证接口不变,内部实现是外部无关的。所以,可以在运行状态下直接升级代码,不需要重启,也不需要停机。Erlang语言早就证明了这一点,它是瑞典爱立信公司为了管理***系统而开发的,***系统的升级当然是不能停机的。
&转自:/blog/2012/04/functional_programming.html
比较笼统,可以去系统地学一下Erlang,会有收获的。&&转自&
盖茨的数学作业:牛人到了哪里都会牛(着重最后一句话)
比尔&盖茨大二时的数学作业,据说是微软面试题,真是牛人到了哪里都会牛。
比尔&盖茨大二时的数学作业,发表于SCI期刊《Discrete Mathematics》1979年27卷。出作业题的是Christos Papadimitriou(后面简称帕帕),帕帕是一位著名的数学家,希腊裔的美国人,目前也是美国工程院院士,当时他在哈佛大学任教。课程结束后,帕帕老师布置了一道非常难的题目,他对此很&满意&,因为绝大多数学生都交了白卷,唯独一份一卷子让他眼前一亮&&那就是比尔&盖茨的答卷。后来,帕帕老师找到盖茨,劝说他毕业之后跟自己做研究生。盖茨问他什么样的研究是比较Top的领域,他说你做的答卷就算是。再后来,盖茨退学了,他要去干比学术更有挑战性的事业&&创业,并且还拐走了他的一个师兄,去了不毛之地新墨西哥州建立了&微软&。不过,他的老师帕帕仍然把盖茨的作业整理了一下,以盖茨为第一作者发表在了一份专业的数学杂志《Discrete Mathematics》上。
多年之后,帕帕在香港的一个学术会议提到了这个故事,有人问他你后不后悔当初失去了盖茨这么一个优秀的学术苗子?帕帕说是有点后悔,不过我更后悔的是当初没有跟他一起去创业。看来牛人是有基因,有特质的,牛人到了哪里都会牛。
我想,看完这个故事,那些因为沉迷游戏、无所事事而导致成绩不好,大学学业无以为继的人,就不要拿盖茨也没读完大学来安慰自己了,呵呵。
注:好多人对比尔&盖茨的名字有疑问,其实他的名字叫William Henry Gates,威廉&亨利&盖茨,而Bill则是William的昵称。
Python语言编程学习资料(电子书+视频教程)下载汇总
Python语言编程学习资料(电子书+视频教程)下载汇总:
开发工具:
学习资料:
(涵盖Python 2.6和3.x)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&##4##刘冯振&
推荐Dive into&&转自&
火焰病毒样本逆向分析( 转自 www.007sec.org )
病毒名称:Worm.Win32.Flame.a中文名称:&火焰&病毒病毒类型:蠕虫类文件 MD5:BDC9E04388BDAC34667E18文件长度:6,166,528 字节开发工具:Microsoft Visual C++加壳类型:无病毒描述 病毒主模块是一个文件名为mssecmgr.ocx的DLL文件,我们发现该模块的以有多个衍生版本,文件大小为6M,运行后会连接C&C服务器,并试图下载或更新其它模块。其主模块在不同时期被感染的机器上文件名有所不同,但扩展名都为&OCX&。运行后的主模块会将其资源文件中的多个小功能模块解密释放出来,并将多个小功能模块注入到几个进程中,功能模块具有获取进程信息、键盘信息、硬件信息、屏幕信息、麦克风、存储设备、网络、WIFI、蓝牙、USB等多种信息的功能。所记录的信息文件存放在%Windir%\temp\下。该病毒会先对被感染系统进行勘察,如果不是其想要的攻击对象,它将会自动从被感染系统卸载掉。病毒最有可能是通过一个USB接入设备或是其他可移动存储介质引入的。病毒还能够发现有关其周边设备的信息。通过蓝牙装置,它会寻找其它设备,比如手机或笔记本电脑等。此病毒和以往病毒有很大程度上的不同,首先主模块体积很大、多个功能模块,内嵌Lua解释器和大量Lua脚本,进行高层的功能扩展。启动方式比较特殊,具有多种压缩和加密方式。2.1本地行为:1.添加注册表:HKLM_SYSTEM\CurrentControlSet\Control\LsaAuthentication Packages = mssecmgr.ocx注:该键值会达到开机加载mssecmgr.ocx的目的。该文件路径为:%system32%\mssecmgr.ocx2.文件运行后会释放以下文件:通过对&146&资源进行释放并加载运行,以下为资源释放的模块%System32%\advnetcfg.ocx (MD5: BB1FCA600E9C433CB1550)%System32%\boot32drv.sys (MD5: C81D037B723ADC43E3EE17B1EEE9D6CC)%System32%\msglu32.ocx (MD5: D53B39FB5E9CFD8B52C2E)%Syste32m%\nteps32.ocx (MD5: C9E00C9D94D1A790DBD741)%Syste32m%\soapr32.ocx (MD5: 296E04ABB00EA5F18BA021C34E486746)%Syste32m%\ccalc32.sys (MD5: 5AD73D2E4E33BB8FBEFC2B)以下为各模块运行时产生的一些临时记录文件,如:获取进程信息、键盘信息、硬件信息、屏幕信息、麦克风、存储设备、网络、WIFI、蓝牙、USB等多种信息。%Windir%\temp\~DEB93D.tmp%Windir%\temp\~HLV084.tmp%Windir%\temp\~HLV294.tmp%Windir%\temp\~HLV473.tmp%Windir%\temp\~HLV751.tmp%Windir%\temp\~HLV927.tmp%Windir%\temp\~KWI988.tmp%Windir%\temp\~rf288.tmp其它文件:%Windir%\Ef_trace.log在%ProgramFiles%\Common Files\Microsoft Shared\MSAudio目录下为各模块的配置信息和自身副本文件,从网络中更新或下载新模块配置也会在这里,列表如下:Audcacheaudfilter.datdstrlog.datlmcache.datntcache.datwavesup3.drv(自身副本)wpgfilter.dat跟据&146&资源配置还可能会存在以下文件目录:%ProgramFiles%\Common Files\Microsoft Shared\MSSecurityMgr%ProgramFiles%\Common Files\Microsoft Shared\MSAudio%ProgramFiles%\Common Files\Microsoft Shared\MSAuthCtrl%ProgramFiles%\Common Files\Microsoft Shared\MSAPackages%ProgramFiles%\Common Files\Microsoft Shared\MSSndMix2.2网络行为:访问地址1:
访问地址2:
协议:Http端口:80访问地址:91.135.66.118[][ traffic-spot.biz][ smart-access.net][ ]协议:https端口:443病毒运行后,首先访问系统升级服务器地址,然后对IP地址为91.135.66.118的四个域名进行访问,并回传数据。2.3样本文件启动加载顺序
该病毒的启动方式有两种,一种是在注册表中添加键值,另一种是利用批处理文件来执行dos命令运行rundll32.exe加载主模块运行。当病毒运行后会将其自身拷贝为Wavsup3.drv。然后对系统进程进行注入如上图,Nteps32.ocx和Advnetcfh.ocx模块被多次注入Winlogon.exe和Services.exe。Explorer.exe也被注入了恶意代码多次创建Iexplore.exe进程并加载模块Wpgfilter.dat。
写在世界末日的Python的小问题
在世界末日的时候,写这么一小篇东西,真是很难匹配这个大背景啊。但也还是要写的。先看python的官方文档所说的这几句话:
the innermost scope, which is searched first, contains the local names
the scopes of any enclosing functions, which are searched starting with the nearest enclosing scope, contains non-local, but also non-global names
the next-to-last scope contains the current module&s global names
the outermost scope (searched last) is the namespace containing built-in names
概括起来就是,LEGB规则,即local, enclosing, global, built-in这样的顺序去查找变量。
OK,搞明白了这件简单的事情之后,再看这句话:
In Python, variables that are only referenced inside a function are implicitly global. If a variable is assigned a new value anywhere within the function&s body, it&s assumed to be a local. If a variable is ever assigned a new value inside the function, the variable is implicitly local, and you need to explicitly declare it as &global&.
这里解释了什么样的变量是local的,什么样的会当做global。OK,这也很简单。再往下一点,看看Python 不是那么动态的地方。
def foo():
& print x&foo()&上述代码执行的很好,打印出10来了。但是,&
def foo():
foo()&就报错了。这个结果让人很吃惊。第一段代码,没问题,x是global的,第二个,为什么就不对了呢。因为,python是通过 def 的最后一条语句判断了,x 是一个 local 的。因此,就会出现Unbounded Error了。也就是说在 def 执行完了以后,x就已经被决定为一个local的,而不是global的。python没有你想象的那么动态,对不对?&好了,这就解释了,python 的闭包为什么要用list,而不能用一个unmutable的变量了。&def foo():& & count = [0,]& & def bar():& & & & count[0] += 1& & & & return count[0]&& & return bar&用闭包写一个计数器的正确写法只能是上面的那种,只有这种写法(没有赋值),count才会被当做enclosing变量来处理,而不是local的。当然,如果代码中有 count = [count[0] + 1,]这种写法,count又是local的了,也就会报错了。&python有时候很二。尽管二得很有道理。有时候,程序猿们最喜欢的未必是有道理的东西,而是能陪你一起二的东西。比如Javascript
如何学习计算机图形学
&IT人一定要记住,不要指望通过一本教材就学会计算机图形学,它比你想象的要复杂的多。
一、&引言&
&&&&&&& 计算机图形学是用计算机来画东西的学科,数字图象处理是把外界获得的图象用计算机进行处理的学科。在法国,图形图象是一门课程。&
&&&&&&& 如何学习计算机图形学呢?除了计算机图形学的基础知识以外,你还需要有以下的知识,你懂的越多,当然做的越好。&
&&&&&&& 1、英语。你一定要把英语学好,如果你想学习计算机图形学的话,尽量看英文的书籍和资料。国内的资料一者比较少,二者涉及到原理性的东西不多。
&&&&&&&&2、数学。计算机图形学里面的数学用的比较多,我们可以列举一些常用的:高等数学、数值分析、微分几何、拓扑,概率、插值理论、(偏)微分方程等等。&
&&&&&&&&3、物理。如果你要进行基于物理的建模,一些物理理论是要学习的:力学(运动学,动力学,流体力学&),光学,有限元&&
&&&&&&&&4、编程语言。C或C++是计算机图形学最通用的'普通话'。&
&&&&&&& 5、数据结构。你需要数据结构来描述你的图形对象,除了通用的链表、树等数据结构外,图形学还有自己特殊的数据结构。
&&&&&&& 6、其他类别。有的时候你需要其他学科的知识,根据你的需要去学习吧。&
&&&&&&& 上面列举的不是你必须学习的东西,而是计算机图形学可能会用到的东西。一定要记住,不要指望通过一本教材就学会计算机图形学,它比你想象的要复杂的多。&&
二、图形学的问题&
&&&&&&& 每个学科都有自己学科的特定问题,图形学要解决的是如何画出图来,得到需要的效果,当然这是图形学最大的一个问题。在开始学习计算机图形学的时候,找一本简单的书看,对计算机图形学有个大概的认识,你就可以开始图形学之旅了。&
&&&&&&& 《OpenGL&Programming&Guide:&The&Official&Guide&to&Learning&OpenGL》(&Version&1.4,&4th&Edition)&
&&&&&&& 《OpenGL&SuperBible&(3rd&Edition)&》
&&&&&&& 这两本书是比较好的学习计算机图形学的入门教材,在练中去学。
&&&&&&& 不建议一开始就看《Computer&Graphics:&Principles&and&Practice,&Second&Edition&in&C》,会看的一头雾水,一本什么都讲的书的结果往往是什么都没讲清楚。&
&&&&&&&&当你把OpenGL的基本内容掌握之后,你对图形学就有了大概的了解了。那么下面你可以来学习一下计算机图形学的数据结构和算法。Joseph&O'Rourke&的《Computational&Geometry&in&C》非常推荐,书里面有C的源代码,讲述简单、清晰,适合程序员学习。
&&&&&&&& 总的来说,计算机图形学涉及到2大部分:建模和渲染。
&&&&&&& 1、建模
&&&&&&& 你想画一个东西,首先要有它的几何模型,那么这个几何模型从什么地方来呢?下面的书很不错:&&
&&&&&&& (1)Gerald&Farin&的《Curves&and&Surfaces&for&CAGD:&A&Practical&Guide》这本书有一点难度,呵呵,要努力看啊。
&&&&&&&&&&&& 这本书算是CAGD&(计算机辅助几何设计)的经典图书,CAGD方面的全貌。
&&&&&&&&(2)还有2本很好的讲述曲面的书,Bezier和Nurbs的书,Les&A.&Piegl,Wayne&Tiller&的《The&Nurbs&Book&》,里面有NURBS曲线、曲面的程序伪代码,很容易改成C的,书讲的通俗、易懂,但是你要有耐心看。&
&&&&&&& (3)《曲线与曲面数学》&
&&&&&&&&&&&& 这本书是法国人写的中文翻译版,里面还有Bezie本人写的序J,翻译的很不错的,看了你就掌握Bezier曲面技术了。&&
&&&&&&& (4)还有其他的一些造型技术,这些技术可以适当的看看,有时可能会用到。
&&&&&&&&&A、隐式曲面(Implicit&Surface)造型:就是用函数形式为F(&x&,y&,z&)&=&0的曲面进行造型,这样的造型技术适合描述动物***一样的肉乎乎的东西。有2本书推荐大家:&
&&&&&&&&&&&&&&&&Jules&Bloomenthal编辑的《Introduction&to&Implicit&Surfaces》,是一本专著,讲述了Implicit&Surface建模型(Modeling),面片化(Polygonization),渲染(Rendering)的问题。
&&&&&&&&&&&&&&&&Luiz&Velho&的《Implicit&Objects&Computer&Graphics》也是一本专著,讲述了更新的一些进展。
&&&&&&&&&B、细分曲面(Subdivision&Surface)造型:当用NURBS做造型的时候,曲面拼接是复杂的问题,在动画的时候,可能产生撕裂或者褶皱,Subdivision&Surface用来解决这个问题&。
&&&&&&&&&&&&&&&&&Joe&Warren的《Subdivision&Methods&for&Geometric&Design:&A&Constructive&Approach》就是这方面的专著。&&
&&&&&&&&&(5)光有造型是不够的!开始在你的几何模型做好之后,有一些问题需要对这个模型进一步处理,得到适合的模型,当面片很多的时候,或者模型很复杂的时候,需要对几何模型进行简化,才可以满足一些实时绘制的需要,这个技术叫做层次细节(LOD-Level&of&Detail)。下面的书就是讲这个的:&
&&&&&&&&&&&&&&David&Luebke编著的《Level&of&Detail&for&3D&Graphics》&
&&&&&&&&2、渲染&
&&&&&& 有了模型,怎么把这个几何模型画出来呢?这个步骤就是渲染。
&&&&&&&&(1)如果你看了上面的OpenGL的书,那么你就知道一些渲染的知识了,但是别高兴的太早,OpenGL使用的是局部光照模型(Local&Illumination&Model),不要被这个词吓住了。
&&&&&&&& Local&illumination&Model指的是在做渲染的时候只考虑光源和物体之间的相互作用,不考虑物体和物体之间的影响,所以OpenGL不支持阴影,一个(半)透明物体的效果,这些需要考虑物体之间的影响才可以实现。&
&&&&&&& (2)光线追踪(Ray&Tracing)&&&&&&&&& 关于Ray&Tracing的好书有2本:
&&&&&&&&Andrew&Glassner&的《An&Introduction&to&Ray&tracing》。Glasser是图形界的名人,这本书也是Ray&Tracing的经典
&&&&&&&&R.&Keith&Morley,&Peter&Shirley&的《Realistic&Ray&Tracing,&Second&Edition》。这本书第一版是伪代码,第二版是C代码。它的结构不是很清楚,虎头蛇尾的感觉。&
&&&&&&& (3)辐射度(Radiosity)&&&&&&&&&&关于Radiosity的好书有4本:&&
&&&&&&&&Michael&Cohen&的《Radiosity&and&Realistic&Image&Synthesis》。Cohen获得SIGGRAPH&1998计算机图形学成就奖,他把Radiosity变成实际可用。
&&&&&&&&Francois&X.&Sillion的《Radiosity&and&Global&Illumination》。Sillion是法国人,他的主要研究方向是Radiosity,这本书写的很不错的,非常清晰。&
&&&&&&&&Philip&Dutre&的新书《Advanced&Global&Illumination》。看起来还不错,刚拿到手,还没看,呵呵,所以不好评价&
&&&&&&&&&Ian&Ashdown的《Radiosity:&A&Programmer's&Perspective》。有源代码的书啊!!&
&&&&&&&& (4)Photon&mapping&
&&&&&&&& 这个我也不知道怎么翻译,呵呵。这个技术出现的比较晚,一本好书!&
&&&&&&&&&Henrik&Wann&Jensen的《Realistic&Image&Synthesis&Using&Photon&Mapping》。Henrik&Wann&Jensen是Photon&mapping技术的发明者。
&&&&&&&& 3、除了上面讲的'经典'的计算机图形学,还有下面的一些东西,它们也叫计算机图形学吗?是的!!!&
&&&&&&&& 3.3.1非真实性图形学(Non-Photorealistic&Graphics)&
&&&&&&&&真实性不是计算机图形学的唯一要求,比如:你给我画一个卡通效果的图出来,或者我要用计算机画水彩画怎么办?或者:把图象用文字拼出来怎么做?,解决这些问题要用到非真实性图形学,&好书继续推荐!!!&
&&&&&&&&Bruce&Gooch,&Amy&Ashurst&Gooch的《Non-Photorealistic&Rendering》。&
&&&&&&& 3.3.2体图形学(Volume&Graphics)&
&&&&&&& 用CT机做很多切片(比如头骨),那么能通过这些切片得到3D的头骨吗?Volume&Graphics就是解决这样的问题的。&
&&&&&&&&Min&Chen&编著的《Volume&Graphics》。&
&&&&&&& 上面的2个图形学技术就和图象的界限不明显了,实际上他们是图形图象的综合。
&&&&&&& 4、还有其他的书吗?还有一些好书啊,呵呵,好书看不完的,继续放送:&
&&&&&&& 《Graphics&Gems&I&~&V》。一大帮子人写的书,包括研究人员,程序员&。有计算机图形学的各种数据结构,编程技巧。&
&&&&&&&&Tomas&Akenine-Moller&等人编著的《Real-Time&Rendering&(2nd&Edition)&》。讲述了许多最新的计算机图形学进展。&
&&&&&&&&David&Ebert等人的《Texturing&&&Modeling:&A&Procedural&Approach,&Third&Edition》。讲述如何通过程序实现纹理、山、地形等图形学要素。&
&&&&&&&& F.&Kenton&Musgrave号称分形狂(Fractal&Mania)。Ken&Perlin就是Perlin噪声的发明者,用过3d软件的人对Perlin&Noise不会陌生的。
&&&&&&&& 5、关于图形学的特定对象,有特定的专题图书。&
&&&&&&&& 《Evan&Pipho&Focus&On&3D&Models》。对于图形学的常用模型格式,进行了讲解。&
&&&&&&&&&Trent&Polack的《Focus&On&3D&Terrain&Programming》。讲地形&
&&&&&&&&&Donald&H.&House&的《Cloth&Modeling&and&Animation》。讲布料&
&&&&&&&&&Nik&Lever的《Real-time&3D&Character&Animation&with&Visual&C++》。讲角色动画&&
&&&&&&&&&&&
&&&&&&&& 6、还有:
&&&&&&&&&Richard&Parent的《Computer&Animation:&Algorithms&and&Techniques》,当然是讲动画的啦,呵呵。&
&&&&&&&&&David&H.&Eberly的《3D&Game&Engine&Design&:&A&Practical&Approach&to&Real-Time&Computer&Graphics》,有代码的啊!&
&&&&&&&& 7、最后,没事情的时候,看看下面的书吧:&
&&&&&&&&&Alan&H.&Watt的《3D&Computer&Graphics&(3rd&Edition)》。&
&&&&&&&&&James&D.&Foley等人的《Computer&Graphics:&Principles&and&Practice&in&C&(2nd&Edition)》。这本圣经没事的时候再看吧。&
数字图像与裸女人像的故事
但凡学习数字图像处理的人,都用过标准测试图像Lenna。你知道她是谁吗?她的全名是Lena Soderberg。Lenna图在图像压缩算法是最广泛应用的标准测试图----她的脸部与裸露的肩部已经变成了事实上的工业标准。但是很少有人见过这张图像的原图吧~原图是刊于1972年11月号花花公子杂志上的一张?体插图照片。
擦。。。&&转自&
动态补丁技术总结------by cacorot
总结一下学习的PE补丁技术吧~很重要,而且很实用!
什么动态补丁,是指目标PE(DLL,EXE等)处于活动状态时(进程)为其实施的补丁。通俗来讲就是当进程在活跃的时候,另一个进程去操作进程虚拟空间并对部分指令加以修改,从而实现某一功能。
我们知道各进程的地址空间是独立的,相互之间是不影响的。难道有方法可以突破这种限制吗?这时候要用到一个非常强大的接口WriteProcessMemory,该函数可以对其他进程的空间进行写访问。除此还有ReadProcessMemory,顾名思义。但是在进行访问之前要获取读写内存的权限。
VirtualProtect可以更改其他进程空间的保护方式。 
相关函数原型为:
BOOL VirtualProtect(
  &&&&&& LPVOID lpAddress, // 目标地址起始位置
  &&&&&& DWORD dwSize, // 大小
  &&&&&& DWORD flNewProtect, // 请求的保护方式
  &&&&&& PDWORD lpflOldProtect // 保存老的保护方式
BOOL WriteProcessMemory(
  HANDLE hProcess,&&&&&&&&&& //进程句柄
  LPVOID lpBaseAddress,&&&& //& 目标地址起始位置,与VirtualProtect相同位置
  LPVOID lpBuffer,&&&& //& 写入的缓冲区
  DWORD nSize,&& &&&//&& 缓冲区大小
  LPDWORD lpNumberOfBytesWritten //& 可为NULL
上述函数的进程句柄也可以使用OpenProcess来获取。该函数也可以修改访问权限。
小结:一般使用VirtualProtect是指在同一进程下的不同DLL中相互修改。故进程句柄完全可以用GetCurrentProcess()来获得。
OpenProcess是不同进程之间需要修改数据。首先呼叫方需要获取远程进程的句柄,同时修改访问权限。
还要记得修改了保护方式,重新写入了数据之后,还需要恢复保护方式
ULONG oldProtectionW
VirtualProtect(StartAddress, nPatchSize, PAGE_EXECUTE_READWRITE, & oldProtectionWay);
WriteProcessMemory(&);
VirtualProtect(StartAddress, nPatchSize, oldProtectionWay, & oldProtectionWay);
实战:修改指令跳过某一功能函数。
图1 修改前
要想修改该DLL的地址0x64B943DB处的指令。首先必须获取该地址。
获取方式很简单。
1.当我们逆向分析后,知道该函数的具体功能了。就先保存这些指令对应的机器码
&\x85\xC0\x74\x0C\x6A\x03\x56\xFF\x15&。可以存入到一个数组中
byte szCode[] = {0x85, 0xC0, 0x74, 0x0C, 0x6A, 0x03, 0x56, 0xFF, 0x15};
2.将补丁码存入另一个数组。如下图所示,更改的指令为je short&!故机器码改为EB 0C,故数组为 byte szCodePatch[] = {0xEB, 0x0C};
图2 修改后
3.LoadLibray获取模块基地址。然后根据PE文件的SizeOfImage字段获取模块的大小。PIMAGE_DOS_HEADER lpDosH
PIMAGE_NT_HEADERS lpNtH
lpDosHeaders = (PIMAGE_DOS_HEADER)lphM // lphModule模块基址
if (lpDosHeaders-&e_magic == IMAGE_DOS_SIGNATURE) //判断是否MZ
&&&&&&&&&& lpNtHeaders=(PIMAGE_NT_HEADERS)((DWORD)lphModule+ pDosHeaders-&e_lfanew); //0x3C处取得IMAGE_NT_HEADER基地址
&&&&&&&&&& if (lpNtHeaders-&Signature == IMAGE_NT_SIGNATURE) //判断是否PE文件
&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& dwResult = lpNtHeaders-&OptionalHeader.SizeOfI
//在IMAGE_OPTIONAL_HEADER结构中的SizeOfImage字段即为模块镜像的大小
&&&&&&&&&& }
&&&&&&&& } (windows PE权威指南中详细介绍)
4.获取了模块基地址以及模块镜像大小后,从头到尾搜索数组szCode中的机器码所在的位置的偏移量
5.最后计算打补丁的地方的位置:基址+机器码偏移量+补丁内部偏移量。
即0x64B943DB处,如图2所示。可以有很多种方法来修改。大家自己可以琢磨琢磨。
6.VirtualProtect修改保护属性。使用WriteProcessMemory将szCodePatch写入指定地址0x64B943DB处。
WriteProcessMemory(GetCurrentProcess(), lpDLLPatch, szCodePatch, nPatchSize, NULL);
lpDLLPatch是上述地址0x64B943DB
7.VirtualProtect返回原有属性
动态补丁技术可以使用在游戏修改器、病毒生存、动态调试等。(windows PE权威指南)
这里只是原理性的描述。至于应用需要逆向出某一模块中某一函数的功能,然后才能使用补丁技术来进行修改!
写得好啊。撩拨得我终于下定决定重头读Windows核心编程了。&&转自&
DLL劫持技术(原创)
大家是不是有个疑惑。只是单纯的把DLL拷贝到目录里,应用程序如何去调用你这个DLL呢?调用了这个DLL又如何保证应用软件的稳定呢?这些问题可以由&DLL劫持技术&来回来。
什么叫DLL劫持技术?
首先我来介绍一下DLL转发器的概念。
&&&&&&&& 函数转发器是指将一个DLL的函数的调用转到另外一个DLL的另一个函数!举例说明。例如在Kernel32.dll中有个函数为CloseThreadPoolIo,若调用该函数,GetProcAddress会先在kernel32.dll导出表中查找并发现该函数是个函数转发器,于是递归调用GetProcAddress,在NTDLL.dll导出表中查找TpRealeaseIoCompletion。其实CloseThreadPoolIo根本就没有具体代码实现。(windows核心编程第五版)
&&&&&&&& 设定函数转发器的代码如下:
&&&&&&&& #pragma comment(linker, &/EXPORT:CloseThreadPoolIo = ntdll.TpRealeaseIoCompletion&)
如果为该导出函数设置一个编号
#pragma comment(linker, &/EXPORT:CloseThreadPoolIo = ntdll.TpRealeaseIoCompletion,@1&)
专门介绍#pragma comment
&&&&&&&& DLL劫持技术,按我自己理解就是本来一个软件要去调用操作系统的DLL库,而一些黑客在这个软件的当前目录下加入了相同名字的DLL,不仅如此还要有相同的导出函数。这样根据DLL调用规则,应用软件会首先调用当前目录下的非法同名DLL。当需要使用真实DLL的导出函数时,就会利用DLL转发器,转到真正的系统DLL的导出函数地址。
&&&&&&&& DLL调用规则:(1)可执行程序加载的目录(可理解为程序比如 C:\Program Files\uTorrent)(2)系统目录(即 %windir%\system32 )(3)16位系统目录(即 %windir%\system)(4)Windows目录(即 %windir%)(5)运行某文件的所在目录,比如C:\Documents and Settings\Administrator\Desktop\test)(6)PATH环境变量中列出的目录。
实战:针对QQ2012的msimg32.DLL劫持
使用LordPE查看msimg32.dll的导出函数表
只有5个导出函数。非常容易操作
首先设置一个转发器
#pragma comment(linker, "/EXPORT:vSetDdrawflag=_AheadLib_vSetDdrawflag,@1")
#pragma comment(linker, "/EXPORT:AlphaBlend=_AheadLib_AlphaBlend,@2")
#pragma comment(linker, "/EXPORT:DllInitialize=_AheadLib_DllInitialize,@3")
#pragma comment(linker, "/EXPORT:GradientFill=_AheadLib_GradientFill,@4")
#pragma comment(linker, "/EXPORT:TransparentBlt=_AheadLib_TransparentBlt,@5")
当QQ软件需要使用这5个导出函数时。就会先加载该非法DLL。之后根据函数转发器转到
AheadLib_vSetDdrawflag。这个函数是什么?
该函数作用是获取真实DLL的地址的。
EXTERN &C& __declspec(naked) void __cedel &AheadLib_AlphaBlend(void)
&&&&&&&& GetProcAddress(hmodule, "vSetDdrawflag ");& //获取真实导出函数地址
&&&&&&&& __asm JMP EAX;& //跳转
怎么利用劫持技术做坏事呢?
很简单,当应用软件调用这5个函数之一时,就要去寻找DLL。故当前目录下的DLL就会被加载。加载时会进入入口函数DllMain。在这里面HMODULE hMyDLL = LoadLibrary("xxx.dll");
xxx.dll就是做坏事的DLL。
说的比较粗糙。纯讨论技术。发帖的目的第一就是总结自己学习的东西,第二就是引起大家的思考,然后一起讨论。
&by cacorot
老胡推荐必为精品。&&转自&
8-queens弱爆了,来看看∞-queens
当 1848 年国际象棋玩家 Max Bezzel 提出八皇后问题(eight queens puzzle)时,他恐怕怎么也想不到,100 多年以后,这个问题竟然成为了编程学习中最重要的必修课之一。八皇后问题听上去非常简单:把八个皇后放在国际象棋棋盘上,使得这八个皇后互相之间不攻击(国际象棋棋盘是一个 8&8 的方阵,皇后则可以朝横竖斜八个方向中的任意一个方向走任意多步)。虽然这个问题一共有 92 个解,但要想徒手找出一个解来也并不容易。下图就是其中一个解:&&&&&&&&&八皇后问题有很多变种,不过再怎么也不会比下面这个变种版本更帅:请你设计一种方案,在一个无穷大的棋盘的每一行每一列里都放置一个皇后,使得所有皇后互相之间都不攻击。具体地说,假设这个棋盘的左下角在原点处,从下到上有无穷多行,从左到右有无穷多列,你需要找出一个全体正整数的排列方式 a1, a2, a3, ... ,使得当你把第一个皇后放在第一行的第 a1 列,把第二个皇后放在第二行的第 a2 列,等等,那么任意两个皇后之间都不会互相攻击。&&&&&
&&&&&&&&&&&&&下面给出一个非常简单巧妙的构造。首先,我们给出五皇后问题的一个解。并且非常重要的是,其中一个皇后占据了最左下角的那个格子。&&&&&&&&&接下来,我们把五皇后的解扩展到 25 皇后,而依据则是五皇后本身的布局:&&&&&&&&&这样一来,同一组里的五个皇后显然不会互相攻击,不同组的皇后之间显然也不会互相攻击,这便是一个满足要求的 25 皇后解了。注意到,在扩展之后,之前已经填好的部分并未改变。&&&&再接下来怎么办呢?没错,我们又把 25 皇后的解复制成五份,再次按照五皇后的布局来排列,从而扩展到 125 皇后!&&&&&&&&&像这样不断地根据已填的部分,成倍地向外扩展,便能生成一个无穷皇后问题的解。&&&&这个解法收录在了 Proofs without Words 一书中。
呃。果然without words&&转自&
[fun]Linuxer的Windows生存指南
按:一篇挺有趣的文章,经(为twitter链接,你懂的),转载到此,亮点自寻。原文地址:&说我是『』是不准确的。我从未逃离Linux,我逃离的只是Linux桌面。缺乏开发者,GNOME迎来地狱(,&),KDE继续叫好不叫座;一样开发者匮乏而且迟到了20年的Elementray Project 我从没正眼看待过。唯一有希望的是Unity,不过这已经不是Linux。当只有geek能使用时,这个OS的桌面基本上已经死了,大家洗洗睡吧。你不要悲伤,咱 Linux 桌面从未中兴过,没有期望就没有失落。Don&t Panic!
去 Windows 只是一个权宜之计,我的目标是在这里活下来,然后去Mac求生策略备份!备份你的所有数据!血的教训告诉我,一定要反复检查备份数据的完整性和可靠性。关键的部分(例如代码和文档)建议使用多种备份手段!因为我们一旦开始就不再回头。我使用的是一个移动磁碟作为主要迁移媒介,配合Dropbox和github,将~/下所有数据和通用配置文件转移到了Windows分区。气候与地形Windows 对我们 *nix 人来说宛如异星,诸方面颇有异域风情:
整个磁碟被分割成两部分,分别命名成 C 和 D ,其中 C 的 Cup 偏小,为64GB,D 的 cup 为 235 GB
修改注册表项将C:\Program Files和C:\Program Files (x86)指向D分区
以 $HOME 的标准合理建设 D:\生态与生物Windows 类星体的和 *nix 型星体有截然不同的生态环境。尤其在可食用和驱使奴役的生物方面和我们熟悉的 *nix 生物有较大的差异。因此我在对待 Windows 软体时使用如下原则:
尽可能地使用开放DNA的物种:这类物种有着开放的 DNA 编码,在食用安全性上有极大的保证
尽可能地使用跨星际物种:银河系有很多物种能够在多类型的星球中生存下来(他们中有相当的一部分是开放DNA物种),奴役他们可以帮助你更好地适应当地环境和气候
不要拒绝优秀的土著物种:Windows 星中一些物种是极其优秀的,不要因为他们的 Windows 星血统而拒绝食用他们。记住:『旅行即美食,美食即旅行』
不要拒绝优秀的商业物种:银河系是一个贸易活动发达的星系。物种贸易是其中重要的组成部分。某些商业物种是极其优秀的,不要因为他们需要花钱而拒绝食用他们。记住:『旅行即美食,美食即旅行』
谨慎选择『拆哪』集团的子公司出品的物种:该集团中很多子公司都被一伙不长脑子的龟孙控制,一旦革命来临,他们将是第一批被处决者,因此诸位一定要谨慎选择该集团出品的物种
绝对不要食用『拆哪』集团360子公司出品的物种:该公司的物种以价格低廉而著称,主要供集团内部人员食用。有慢性剧毒,致瘾,DNA窃取,智商下挫等特点。食用风险自担下面请看我的部分选择:
浏览器软体:Chrome & Firefox
终端模拟器:MinTTY
编辑器:GVIM
巴别鱼:Golden Dict
密码箱:Kee Pass 2
Windows强化:Listray & QtTabBar
可视化图像播放器:射手
安全通讯隧道:OPEN*** & Tor & Void
沙盒消化系统:SandboxIE回归之旅我们 *nix 人在外星球总是会想家的,我有三种方法保持血缘的联系:
环境模拟器 Cygwin:这是一个 *nix 模拟环境,我依赖它缓解思乡之情,并且它有效地隔离了 Windows 星恶劣的外部环境,保持我们开发工作的稳定和可持续
第二生物圈 VirtualBox:Cygwin 并不能提供完整的 *nix 氛围时,我们就需要完整地再造一个 Linux。VirtualBox 就是孕育第二生物圈的工具,我使用它保持了两个 debian 克隆。
全息成像 SSH:除了与远方的 Linux 星联系,配置得当,SSH 同样可以作为 Cygwin 和 第二生物圈中的通讯渠道。XShell 是非常好的 SSH 软体,如果你和我一样是学生,可以申请免费但是有限制的教育版本。
逃生飞艇 Linux liveUSB:那本包罗万象的工具书曾经明确指出,这对一个星际漫游者来说最有用的东西。如果别人发现一个漫游者随身带着liveUSB,那么他会很自然地认为,一个人,在广阔的银河系中漫游,在面对了许多可怕的困难并且成功地战而胜之以后,他如果仍然还弄得清楚自己的liveUSB在哪里,那么这显然是一个值得认真对待的人。在部署 liveUSB 时请确保所有必需工具都部署到位,最关键的包括密钥和 revoke token。并且飞艇上应该***有急救工具箱(testdisk, photorec, 等),武器(aircrack, nmap, metasploit 等)和基础开荒工具(gcc, python 等)治安与健康在历史上 Windows 是一类险象丛生的星球,到 7 世代时虽然治安好了很多,但是依然不可大意。守卫类生物可以在一定程度上在你入睡时保护你,但是&它们远不是专业杀手的对手,他们的意义仅仅在于对付小喽罗时不需要你亲自出手,切记!可选的守卫生物很多,由于自身的特点,推荐使用商业物种。历史上有一些优秀的守卫在 7 世代 Windows 已经灭绝了,现在我使用的是 Comodo 恶魔守卫,他相对适合对科学有一定了解的术士。对于普通旅行者,我推荐 ESET 公司出品的 Nod32 机械守卫,McAfee 白魔法师 或者是 Windows 联合政府旗下镖局免费提供的 Security Essentials 战士。不推荐『拆哪』集团旗下任何子公司,尤其是360子公司出品的守卫生物。最后,向伟大的星际旅行者致以崇高的敬意。
呵呵。&&转自&
运行在手机里的桌面系统,Ubuntu for Android发布
Ubuntu发布Android版系统,使用户可以在Android系统中运行一个全功能的桌面操作系统,同时不影响手机功能的正常使用。在***Ubuntu for Android后,用户可正常使用Google应用、应用市场、联系人以及打***等,对手机的日常功能没有任何影响。在需要的时候,你可以使用支持HDMI接口的配件与显示器连接,这样就可以获得完整的Unity大屏体验。当手机与显示器连接后,并不会影响信息的收发等手机正常功能的使用。但是你可以通过它进行图片编辑或展示,并且可以播放存储在手机中的视频等。不过目前该应用的外接硬件是个问题,同时只能通过HDMI输出也限制了其应用范围。另外还对手机本身的处理能力提出更高的要求。但是如果巨头都能参与其中,或是运营得当,或许这也将开辟出一片新的市场。目前该系统暂不支持消费者直接***,更多详情可到Ubuntu官方页面了解。
[转]Unix/Linux目录结构的来历
来自阮一峰的博客:
Unix(包含Linux)的初学者,常常会很困惑,不明白目录结构的含义何在。
举例来说,根目录下面有一个子目录/bin,用于存放二进制程序。但是,/usr子目录下面还有/usr/bin,以及/usr/local/bin,也用于存放二进制程序;某些系统甚至还有/opt/bin。它们有何区别?
长久以来,我也感到很费解,不明白为什么这样设计。像大多数人一样,我只是根据(Filesystem Hierarchy Standard),死记硬背不同目录的区别。
昨天,我读到了Rob Landley的,这才恍然大悟,原来Unix目录结构是历史造成的。
话说1969年,和在小型机PDP-7上发明了Unix。1971年,他们将主机升级到了PDP-11。
当时,他们使用一种叫做RK05的储存盘,一盘的容量大约是1.5MB。
没过多久,操作系统(根目录)变得越来越大,一块盘已经装不下了。于是,他们加上了第二盘RK05,并且规定第一块盘专门放系统程序,第二块盘专门放用户自己的程序,因此挂载的目录点取名为/usr。也就是说,根目录"/"挂载在第一块盘,"/usr"目录挂载在第二块盘。除此之外,两块盘的目录结构完全相同,第一块盘的目录(/bin, /sbin, /lib, /tmp...)都在/usr目录下重新出现一次。
后来,第二块盘也满了,他们只好又加了第三盘RK05,挂载的目录点取名为/home,并且规定/usr用于存放用户的程序,/home用于存放用户的数据。
从此,这种目录结构就延续了下来。随着硬盘容量越来越大,各个目录的含义进一步得到明确。
  /:存放系统程序,也就是At&t开发的Unix程序。
  /usr:存放Unix系统商(比如IBM和HP)开发的程序。
  /usr/local:存放用户自己***的程序。
  /opt:在某些系统,用于存放第三方厂商开发的程序,所以取名为option,意为"选装"。
CEdit 以回车结束输入
在一个输入控件里输入文字,然后点回车,响应你的输入这是多么自然的一件事情。所以,我想当然的认为CEdit 控件应该会有一个OnXXX的函数来响应回车这件事情。但是吊诡了,在输入控件里敲回车,整个对话框都挂了。现在才刚知道,其实,点回车,起响应的是Dialog的 OnOK() 函数。呵呵,也就是关闭对话框,这就是为什么对话框会挂了了。所以,真要实现这个功能的话,最好是覆写OnOK()。这样带来一个好处是,在对话框上误敲了回画,对话框也不会莫名其妙地关了。
女程序员发帖说,梦见男朋友和别的女人在逛街,梦里她的第一反应是查源代码…结果调试半天查不出来为什么显示的是那个女人不是她,最后含泪把那个女人给注释掉了,再一次运行就是她男朋友自己逛街了…早上醒来?了很久…回复更强:1L:谁让你把男朋友设成Public的。2L:把那个女人的指针指向你即可。3L:加个断点看看那个女人是谁4L:心真软,就该把他的接口屏蔽掉。//是我想多了么。5L:设计问题,应该采用单例模式。6L:Protected 逛街(youOnly)7L:没做回归测试。8L:不要忘记GC。9L:查一下Log吧,只逛街了吗?
一道概率题
人搜面试,貌似很多人都被问了这题,笔试的时候也有类似的题。&& &有一个0,1随机数发生器,每次生成一个(0,1)的随机数,如果这一次比上一次生成的随机数要小,则停止,否则则继续生成下一个随机数。问你生成的随机数序列的长度的期望是多少。&& &用X表示这个长度,则EX = 求和 P{X=k}*k,关键是要如何求这个&P{X=k},这个求出来就化简成一个无穷级数求和的问题了。我当时是用一个K重积分求的,求得累死我了,不过现在有了一个更加完美的解法:&& & 假设这个发生器每次生成的数已经固定,那么根据它生成的前k个随机数,满足题设条件的种类有多少种呢?要使生成序列长度正好是k的话,必须是这样的:前k-1个数是递增序列,然后第k个数比第k-1个数小,这样的顺序生成随机数的话,长度必然是k。我们不妨假设这K个数两两不等,那么满足这种要求的排列有k-1个(第k-1个位置必然是最大的数,第K个位置可以是任意一个数,这两个位置的数定了的话前边k-2个位置也就定了),所有的全排列是k!,所以长度正好是k得概率应该是(k-1)/k!,乘以k以后得到1/(k-2)!,注意到我们是从k=2开始求和,这样求出来的正好是e的无穷展开。是不是恨巧妙?我也这么觉得。。&& & &人搜特别喜欢考概率题,比如一个硬币掷11次比掷10次得到的正面的次数多得概率是多少?我当时这么想得:假设先掷10次比后一次掷10得到的正面的次数多得概率为a,相等的概率为b,那么显然2a+b=1.那么掷11次比掷10次多的概率为a+b*1/2=1/2.(要么前10次比他多,要么前面一样多,最后一次掷的正面)。但华哥给出了无敌解法:掷11次正面比10次多得概率应该和掷11次正面比掷10次少得概率(即反面比他多得概率)相等,二者之和为1,故为1/2!概率就这么神奇。。。所以,你可以找人和你玩个游戏,说你掷硬币掷100次,我掷一次,你得到的正面的次数也未必比我多。。等等,这个应该是出问题了。。。这里边的纰漏在于,两个人投掷的硬币次数不一样,所以你正面比他多并不意味着反面比它少,比如我6正5反,它5正5反。这么去理解的话,得到的***应该是一个略大于1/2的数。。。概率就是这么神奇。。。就像比如有三扇门,一扇门后边是汽车另外两扇后边是山羊,你随机的选了一扇,然后主持人在剩下的两扇中间打开了一扇是山羊的门,然后问你要不要拿你这扇门去换没打开那个来增加获得汽车的机会,***是要换,坑爹把。。。&& & &关于概率,好像考了不少题把,主要是做均匀化处理。比如,让你用rand5去生成rand7,0-1的p分布发生器去生成1/2发生器,在三角形里边找到一个点,使它完全均匀,还有百度那个题,m的缓存,海量未知长度的数据,问你怎么确定存储策略,使每个值被存储的概率都相等。还有就是如何确定策略使服务器负载均衡(一致性hash和虚拟节点)。。。感觉面试还是学到不少东西。。
&&来自&&的投稿
发两个O(lnn)的算法把
1.(人搜面试)一个递增序列,在某一个位置截断,截断成的两个子数组分别逆序,组成一个由两个递减序列组成的数组。比如,1,3,4,7,9,14,15,18,在9处截断,组成的新数组为7,4,3,1,18,15,14,9,然后让你用O(lnn)的复杂度查找元素k是否在数组中。&& &一般lnn级别的算法都是二分,所以这题也是要往这个方向靠,大概是这么做吧:&& &如果取 mid=(left+right)/2的话,mid左右两边必有一边是完全递减子序列,判断k是否在这边,在这边的话直接按二分查找,在另外一边的话则缩小范围递归。2. (搜狗笔试)一个n*n二维数组,这个数组的特征是同一行右边的元素比左边大,同一列下边的元素比上边大,然后让你查找某个元素k是否在这个数组里边。&& & &当时做完自以为做得还不错,这么写得:&& & &row=n-1;line=0;&& & &while(row&=0&&line&=n-1)&& & {&& & & & if(a[row][line]&k) & row--;&& & & &else & if(a[row[line]]&k) line++;&& & & &else &return 1;&& & }&& & &return 0;&& & &从左下角开始,要么删除一行,要么删除一列,最多经过2n-1次操作可以找出这个数,O(n)算法。面试的时候被要求用O(lnn),无语。。。&& & &怎么办呢,二分吧。把矩阵分成四块,每个小矩阵的最小值和最大值分别在左上角和右下角,这样直接判断可以去掉若干个小矩形。比如,左上角和右下角那两个小矩形必去其一,其他两个可以去掉也有可能去不掉把。当时我和他说这样做平均性能是O(lnn),但他说最坏性能也是O(lnn),虽然不解但也不便辩解,但现在想想,这样做平均性能应该是O(n),最好情况是O(lnn)。注意到平均情况下,每次需要继续在两个小矩形里查找,这样T(n)=2*T(n/2)=...=n,实际上可能要更好一点,因为如果不在任何一个矩形中有可能提前结束。可能有其他的二分查找的办法,但lnn得办法我现在还没想出来。&
&&来自&&的投稿
站长在关注

参考资料

 

随机推荐