<?xml version="1.0" encoding="utf-8"?><rss version="2.0">
<channel>
<title><![CDATA[算法驿站]]></title>
<link>http://blog.pfan.cn/rickone</link>
<description>编程爱好者博客</description>
<language>zh-cn</language>
			<item>
		<title><![CDATA[泛型数值STL算法]]></title>
		<link>http://blog.pfan.cn/rickone/39919.html</link>
		<description><![CDATA[iota(first, last, value)返回void，对于0 &lt;= n &lt; (last - first)，*(first + n) = value + n
accumulate(first, last, init)返回s，s = init + *first + *(first + 1) + ... + *(last -1)accumulate(first, last, init, pred)返回s，s = pred(pred(...pred(pred(init, *first), *(first + 1)),...), *(last - 1))
inner_product(first1, last1, first2, init)返回s，s = init + *first1 * *first2 + *(first1 + 1) * *(first2 + 1) + ... + *(last1 - 1) * *(first2 + (last1 - first1) - 1)inner_product(first1, last1, first2, init, pred1, pred2)返回s，s = init pred1 *first1 pred2 *first2 ...
partial_sum(first, last, result)返回result+(last-first)，对于0 &lt;= n &lt; (last-first)，*(result + n) = accumulate(first, first + n, 0)partial_sum(first, last, result, pred)返回result+(last-first)，对于0 &lt;= n &lt; (last-first)，*(result + n) = accumulate(first, first + n, 0, pred)
adjacent_difference(first, last, result)返回result+(last-first)，*result = *first，对于1 &lt;= n &lt; (last-first)，*(result + n) = *(first + n) - *(first + n - 1)
adjacent_diffe]]></description>
		<author><![CDATA[rickone]]></author>
		<pubDate>2008-12-15 15:07:00</pubDate>
		</item>
				<item>
		<title><![CDATA[SortingSTL算法]]></title>
		<link>http://blog.pfan.cn/rickone/39918.html</link>
		<description><![CDATA[sort(first, last)返回void，对[first, last)排序，要求随机访问迭代器sort(first, last, comp)返回void，对[first, last)排序，要求随机访问迭代器，使用comp比较（下略）
stable_sort(first, last)返回void，稳定的排序，对于相等的元素排序前和排序后不会改变先后关系stable_sort(first, last, comp)
partial_sort(first, mid, last)返回void，局部排序，选最小的(mid-first)个元素放在有序的[first, mid)中，[mid, last)中的剩余元素顺序未定义partial_sort(first, mid, last, comp)
partial_sort_copy(first, last, rfirst, rlast)返回rfirst+n，n=min{(last-first), (rlast-rfirst)}，从[first, last)中选最小的n个元素放在[rfirst, rlast)中partial_sort_copy(first, last, rfirst, rlast, comp)
is_sorted(first, last)返回bool，true当[first, last)为升序，否则falseis_sorted(first, last, comp)
nth_element(first, nth, last)返回void，相当于一次划分，以nth大元素为pivot的一次partition，其中[first, nth)中不存在元素i，*nth &lt; *i，[nth, last)中不存在元素j，*j &lt; *nth，他们中的元素不保证有序nth_element(first, nth, last, comp)
lower_bound(first, last, value)返回最远的i，使对于j在[first, i)中 *j &lt; value is truelower_bound(first, last, value, comp)
upper_bound(first, last, value)返回最远的i，使对于j在[first, i)中 value &lt; *j is fal]]></description>
		<author><![CDATA[rickone]]></author>
		<pubDate>2008-12-15 15:05:00</pubDate>
		</item>
				<item>
		<title><![CDATA[质变STL算法]]></title>
		<link>http://blog.pfan.cn/rickone/39778.html</link>
		<description><![CDATA[copy(first, last, result)返回result+(last-first)，拷贝[first, last)到[result, result + (last - first))，注意这些运算符：*result = *first; ++first, ++result
copy_n(first, n, result)返回result+n，拷贝[first, first + n)到[result, result + n)
copy_backward(first, last, result)返回result-(last-first)，拷贝[first, last)到[result - (last - first), result)
swap(a, b)返回void，交换a,b
iter_swap(a, b)返回void，等同于swap(*a, *b)
swap_ranges(first1, last1, first2)返回first2+(last1-first1)，交换区间[first1, last1)，[first2, first2 + (last1 - first1))
transform(first, last, result, op)返回result+(last-first)，对于0 &lt;= n &lt; (last - first)，*(result + n) = op(*(first + n))transform(first1, last1, first2, result, bi)返回result+(last-first)，对于0 &lt;= n &lt; (last1 - first1)，*(result + n) = bi(*(first1 + n), *(first2 + n))
replace(first, last, old_value, new_value)返回void，替换[first, last)中*i == old_value的*i = new_valuereplace_if(first, last, pred, new_value)返回void，替换[first, last)中pred(*i) is true的*i = new_value
replace_copy(first, last, result,]]></description>
		<author><![CDATA[rickone]]></author>
		<pubDate>2008-12-05 14:26:00</pubDate>
		</item>
				<item>
		<title><![CDATA[非质变STL算法]]></title>
		<link>http://blog.pfan.cn/rickone/39750.html</link>
		<description><![CDATA[for_each(first, last, pred)返回pred，对所有i在[first, last)中，执行pred(*i)
find(first, last, value)返回第一个i在[first, last)中，*i == value
find_if(first, last, pred)返回第一个i在[first, last)中，pred(*i) is true
adjacent_find(first, last)返回第一个i, *i == *(i + 1)adjacent_find(first, last, pred)返回第一个i, pred(*i, *(i + 1)) is true
find_first_of(first1, last1, first2, last2)返回第一个i在[first1, last1)中，且*i == *any[first2, last2)find_first_of(first1, last1, first2, last2, pred)返回第一个i在[first1, last1)中，且pred(*i, *any[first2, last2)) is true
count(first, last, value)返回i的个数，*i == valuecount(first, last, value, n)返回void, n = count(first, last, value)
count_if(first, last, pred)返回i的个数，pred(*i) is truecount_if(first, last, pred, n)返回void, n = count_if(first, last, pred)
mismatch(first1, last1, first2)返回第1个pair(i = first1 + n, j = first2 + n)，*i != *jmismatch(first1, last1, first2, pred)返回第1个pair(i = first1 + n, j = first2 + n)，pred(*i, *j) is false
equal(first1, last1, first2)返回true当且仅当2序列完全相同，否则falseequal(first1, last1,]]></description>
		<author><![CDATA[rickone]]></author>
		<pubDate>2008-12-03 19:03:00</pubDate>
		</item>
				<item>
		<title><![CDATA[很久没来了,喘个气]]></title>
		<link>http://blog.pfan.cn/rickone/38191.html</link>
		<description><![CDATA[对多个资源操作时,一次全部申请(等待),是最简单的防止死锁的方法,一次全申请并不会影响性能,如果占有时间不长的话~
Semaphore是对一种资源可同时占用的数量的描述,即被多少个线程使用,如果最大数为1,就是一个Mutex, binary semaphore~
中秋快乐~~]]></description>
		<author><![CDATA[rickone]]></author>
		<pubDate>2008-09-10 16:15:00</pubDate>
		</item>
				<item>
		<title><![CDATA[幻想中的typeof]]></title>
		<link>http://blog.pfan.cn/rickone/36461.html</link>
		<description><![CDATA[我想我的BLOG是不是要改名字了，还是C++相关。
想研究boost::lambda源码，找到这篇文章：http://www.cppblog.com/shifan3/archive/2006/06/09/8334.html&nbsp;还算写得不错，通俗啊，我写不出这样的文章，本来是带着一个问题去的，就是关于函数对象的返回类型如何确定。嗯，先从我对lambda库实现的想法说起吧。
简单描述，lambda库是用函数对象重新对程序进行编码。什么是程序的编码，程序是什么，C++程序？包括三个方面：面向类类型的表达式（泛型的），函数（包括成员函数）和控制语句（if,then,while等）。lambda的结果是，让‘程序’重新以‘函数’的方式存在。靠，C++语言并不是函数式语言，整个库出来实现函数式，太牛了。
1种幻想，如果lambda获得了成功，成了新的C++标准，那可否从C++语言的层面直接支持函数，比如定义一个函数本身就在定义一个函数对象！。。。不太可能，这需要支持和改变的东西太多了，是彻底的改变，那还要那些函数式语言干嘛~~
转到lambda的实现，那三个方面又是以表达式为核心的，绑定后的函数还是可以构造表达式，控制语句完了还是可以构造表达式。它的最基础的技术就是表达式模板技术。
表达式模板技术又不好一言两语说清楚，我写过一个Vector的表达式模板，有一些感悟。首先，确定构造后的表达式用来干什么，比如数组的表达式，用来数值计算，所以要定义哪些接口，这个接口是自上而下调用的，不管表达式有多复杂，都会自上而下的调用。lambda的表达式目的很明确，用来函数调用，所以要有operator()接口，那么它又多了一条本质，lambda表达式是一个函数对象。那你要问它有多少个参数？返回参数如何确定？多参数应该是不确定的，没有很好的方法，只能是定义足够用那么多，用宏控制，比如我定义最多十个参数的operator()，那就要从operator()(A1)一直定义到operator()(A1,A2,...A10)这么多。返回类型迟一点再说。
然后是设计托管的泛型的运算符类，比如：
template&lt;typename Arg1,typename Arg2&gt;class Mult{&nbsp; Arg1 arg1;&nbsp; Arg2 arg2;};
表示运算]]></description>
		<author><![CDATA[rickone]]></author>
		<pubDate>2008-07-05 01:16:00</pubDate>
		</item>
				<item>
		<title><![CDATA[C++中的指针]]></title>
		<link>http://blog.pfan.cn/rickone/36334.html</link>
		<description><![CDATA[C++的指针有4种：指向数据，指向函数，指向成员数据和指向成员函数；为什么不分两种，指向数据和指向函数，这个前2种和后2种不能一对一。可以这么分，指向非成员和指向成员，指向成员的简称成员指针。以下一一说明。
1，指向数据的指针
非常简单。例如：

int a = 100;int *p = &amp;a;cout&lt;&lt;*p&lt;&lt;endl;
2，指向函数的指针
函数名可以看成是一个单身函数对象，取值后是函数的入口地址，如：

void foo(int a){}
foo看成是一个类型是void (int)的单身对象，但是对名字foo取值后，它会退化成相应的指针类型void (*)(int)。注意那个括号不能少。当然如果对foo取地址也是这个类型（取两次？没考虑过~~哇靠~太绝了吧）。
所以指向函数的指针，申明起来比较怪，像这样：

void (*pf)(int) = &amp;foo;
申明一个类型是void (*)(int)的函数指针pf，并初始化为&amp;foo，这里的函数参数类型形式和返回类型要和foo的声明一致。再多一个例子吧：

int foo2(float a,double b){&nbsp;&nbsp;&nbsp; return 0;}
int (*pf2)(float,double) = &amp;foo2;
函数指针的使用，两种方式：

(*pf)(100);
即，先引用*，打括号，再传实参调用，或者直接，pf(100)。
函数指针的意义：一个函数可以看成是一个策略，对于一个问题，可以采用不同的策略和方法，这种对策略的选择推迟到运行期，即用一个变量保存起来，在程序跑起来的时候，决定使用什么策略，其本质即是动多态，对一个函数的调用延迟到运行时决定。
3，指向成员数据的指针
在要说成员指针之前，要先明确一个概念：名称的受限。C++有一套自己的名称查找机制，一个名称可以是一个类名，对象名，函数名等。受限是指是否用::,-&gt;,.中的一种符号作用。
看一般的成员数据访问：

struct A{int a;};
A a;A* p=&amp;a;cout&lt;&lt;a.a&lt;&lt;p-&gt;a&lt;&lt;endl;
当然类A的定义和下面三条语句不是在一起的，a.a是正确]]></description>
		<author><![CDATA[rickone]]></author>
		<pubDate>2008-06-28 22:18:00</pubDate>
		</item>
				<item>
		<title><![CDATA[Who&#39;s&nbsp;my&nbsp;friend[C++友元点滴]]]></title>
		<link>http://blog.pfan.cn/rickone/36219.html</link>
		<description><![CDATA[我不知道关于C++关键字friend的全部议题有多少，我只对我了解的做个小结。
1，friend申明一个友元
friend一般为一句申明式，它位于一个类的内部，它申明一个类或者一个函数为该类的友元。friend并不是定义一个成员函数，所以friend放在public,protected或者private前都可以，完全是一样的。做为一个友元，即表示在该类或者该函数内部可以访问这个类的私有成员，你和朋友之间是不是应该没有什么隐藏的呢。例子：

class A{public:&nbsp;A(int _a) : a(_a) {}&nbsp;friend void test(A&amp;);&nbsp;friend class B;private:&nbsp;&nbsp; int a;};
void test(A&amp; x){&nbsp;x.a=100;//拥有私有成员a的访问权限}
class B{public:&nbsp; void foo();};
如果friend申明式为一般的非模板类或者函数，则该处可以为首次申明。对于一个类，只能是申明式，对于函数，可以是它的定义式。

class A{public:&nbsp;A(int _a) : a(_a) {}&nbsp;friend void test(A&amp; x)&nbsp;{&nbsp;&nbsp;&nbsp; x.a = 100;//定义::test()友元函数&nbsp;}&nbsp;friend class B;private:&nbsp;&nbsp; int a;};
注意尽管将函数的定义式放在类内部，但它并不是一个成员函数，对于省略受限的定义形式它将成为一个全局函数::test()，当然你也可以申明另外一个类的成员函数为友元，如：

class A{public:&nbsp;A(int _a) : a(_a) {}&nbsp;friend void B::foo();private:&nbsp;&nbsp; int a;};
总的来说，如果你想在哪里访问类A的私有成员，就在类A内写上一句该处的申明式，并在前面加上friend关键字。
这是一般情况，很简单，但是它会破坏封装的初衷，所以尽量少用；Effective C++中有一个应用的例子，对一个类定义的二元操作符，如果你希]]></description>
		<author><![CDATA[rickone]]></author>
		<pubDate>2008-06-20 21:13:00</pubDate>
		</item>
				<item>
		<title><![CDATA[C++的const关键字]]></title>
		<link>http://blog.pfan.cn/rickone/36004.html</link>
		<description><![CDATA[想小结一下const的种种用法和相关知识
1,const修饰数据
见文:const指针和引用
2,const修饰成员函数
表示该成员函数为常量对象调用，首先来看C++的对象和绑定的成员函数是如何实现的。

class A{public:&nbsp;&nbsp;&nbsp; void Test(int _a)&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a = _a;&nbsp;&nbsp;&nbsp; }private:&nbsp;&nbsp;&nbsp; int a;};
A::Test(int)是A的成员函数，一个函数是一段可执行代码，它和对象的数据是两回事，它只需要一份拷贝，相当于它们是静态的不变的（static），而非static数据成员是可以有多份拷贝，它们是动态的可变的，它们之间如何关联起来？通过this指针，在成员函数内对成员变量调用时会省略this指针，上面的语句相当于‘this-&gt;a = _a’而this指针是如何传进成员函数的？this指针如何传进去这不是程序员关心的，有的编译器通过函数第一个参数，比如上面的A::Test(int)实际上是A::Test(A* this,int);函数参数的压栈顺序是反的，从汇编的角度看，就是通过系统栈传递this指针，当然，有的还会通过寄存器，如何传进去的不用担心，结果是它已经传进去了。所以可以这样理解下面的C++代码：

A a;a.Test(100);
理解为：

A a;A::Test(&amp;a,100);
好了，这样理解是最好的了，我们来看const成员函数，如果上面代码中a是常量，看看有什么问题：

const A a;A::Test(&amp;a,100);
由于Test()的第一个参数是A*，&amp;a的结果是const A*，不能将一个指向常量的指针赋给一个一般指针，编译错误。所以简单在Test定义式中尾部加一个const：

&nbsp;&nbsp;&nbsp; void Test(int _a) const&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a = _a;&nbsp;&nbsp]]></description>
		<author><![CDATA[rickone]]></author>
		<pubDate>2008-06-09 18:29:00</pubDate>
		</item>
				<item>
		<title><![CDATA[C++转型操作符]]></title>
		<link>http://blog.pfan.cn/rickone/35971.html</link>
		<description><![CDATA[C++有四种转型操作符,以下小结一下:
1,static_cast&lt;&gt;()
用得最多的，如果转换的是类型，则调用转型函数：比如int转float，float转int等基本数据类型的转型，如果是一个类，就调用类型转换函数，比如：

#include &lt;iostream&gt;
using namespace std;
class A{public:&nbsp;&nbsp;&nbsp; explicit A(int _a = 0) : a(_a) {}&nbsp;&nbsp;&nbsp; operator int() const&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return a;&nbsp;&nbsp;&nbsp; }private:&nbsp;&nbsp;&nbsp; int a;};int main(){&nbsp;&nbsp;&nbsp; A a(100);&nbsp;&nbsp;&nbsp; int b = static_cast&lt;int&gt;(a);&nbsp;&nbsp;&nbsp; cout&lt;&lt;b&lt;&lt;endl;&nbsp;&nbsp;&nbsp; system("PAUSE");&nbsp;&nbsp;&nbsp; return 0;};
可以转换一个基类指针到子类指针的转型，但是不做动态类型检查，可以不存在虚函数，因此转型可能是不安全的，但是是快速的。
2,dynamic_cast&lt;&gt;()
专门用于C++类的指针转型，且是用于多态继承体系中的类。public继承体现了‘is-a’的类关系，一个基类指针，可以指向子类对象，它的子类类型是动态类型，dynamic_cast&lt;&gt;()就是将基类指针转型成它动态类型的子类指针，如果类型不对，结果就是空。

#include &lt;iostream&gt;
using namespace std;
class B{public:&nbsp;&nbsp;&nbsp; virtual void foo() {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout&lt;&lt;"B.foo"]]></description>
		<author><![CDATA[rickone]]></author>
		<pubDate>2008-06-06 22:42:00</pubDate>
		</item>
				<item>
		<title><![CDATA[数独的基本玩法和解题模式]]></title>
		<link>http://blog.pfan.cn/rickone/34975.html</link>
		<description><![CDATA[学了很久数独，同是一个人工解独的爱好者，也是计算机解独的爱好者，另外还是一个解法研究的爱好者，写下一些感想，只希望有更多的人来玩这样一个好玩的游戏，数学游戏。
1 数独的基本玩法
第一次接触数独的人，恐怕都有一个想法，这个太难了，我要试多少次才能全部填出来？其实错了，数独绝对不是试着填填数字的小游戏。所以大多数人，都不愿意去接受它，觉得它太繁琐，太复杂。其实是一个方法问题，因为一些基本的方法还不了解。我有一个愿望，做一个数独软件，一个真的能让人一步一步了解数独学习数独的软件，让更多人为这个游戏疯狂。
问：玩这个游戏，需要什么知识？
答：1，逻辑推理；2，逻辑推理；3，还是逻辑推理。
数独的定义里除了约束条件外，还有两条规则：
1，任何数独的解都是唯一的2，数独是完全可以依靠推理，来一步一步确定数字来完成的，而不是乏味的‘猜测’+‘试探’
所以玩数独有一个心态，就是不要‘猜’，而是相信自己的推理。推理即‘解法’，有简单的，有复杂的，这和认识和学习数独的过程有关，比如有人一上来就学‘X环’，它已经习惯这个手段是‘基本方法’，那也没办法，每个人解数独的方法都不同，主要依赖的模式也不同。以下介绍一些基本的方法，我会把有些方法进行总结和归纳，有很多是异曲同工的，我会挖出方法背后的原理，同时进行一定的扩展。
a 直观法
这个名字很奇怪，言下之意，就是直接用眼睛看，就能看出来，很直观。它的基本出发点就是：在一个区域里，如果只可能位置p上是x，那x一定就在p上。听上去很废话，对，任何数独的基本出发点都很简单，关键是，你能不能运用它在一个数独题里去解题。运用这个方法解题的关键是，在各种区域间进行交运算，比如在一行上有数字3，那它将影响它所在行上的并排三个宫内的数字，那些与这一行相交的区域就不会再出现3了，这样对区域有意识地进行交运算+排除，你就有可能把另外一个区域中很多的位置‘否定’掉，那剩下唯一的位置，自然一定是3，填上去。如图1示：
图1
G1=3 =&gt; 第1列的其它位置不能是3，和第1宫求交后A1,B1,C1不可能是3，同理由A8,B5上的3可以得到第1宫中绿色区域内没有3，那么3一定在红圈所示位置C3。它的主要过程就是，考虑一个区域（行，列和宫），借助其它位置的数字排除这个区域内尽可能多的位置，从而最后确定只可能填的位置。
如果为每个格子建立一个]]></description>
		<author><![CDATA[rickone]]></author>
		<pubDate>2008-05-11 23:54:00</pubDate>
		</item>
				<item>
		<title><![CDATA[数独程序(sudoku&nbsp;boy&nbsp;2)设计报告]]></title>
		<link>http://blog.pfan.cn/rickone/34871.html</link>
		<description><![CDATA[因为一些原因，又把原来写过的数独程序重新翻出来改写。有朋友说原来的就写得不错了，还要改，我改的目的主要是想实践一下C++，尤其是设计方面。
1 面向对象吗？
不知道原来的程序算不算面向对象，一个类，比如class sudoku，有构造函数，求解函数，显示函数，等等，但是总是觉得有些乱，一但有了新的需求，整个代码就看起来像盘散沙。
经过这次的实践，我总结出来的规律是，一个类的设计，要使接口最小化，就是说接口集最小，接口数目最少，为了做到这一点，对类本身就要求，只完成功能上最小单位的部分，一个类，要么封装一些数据（容器），要么封装一个数据（元素），要么做一件事情（功能），容器类，只要设计元素的访问方法，元素类只要一个最小数据结构本身（不包括帮助函数算法的辅助数据结构），数据结构的算法留给专门的类设计（功能）。如何融合它们，数据+算法，干净的数据+干净的算法，用帮助函数，别小看写在类外面的帮助函数，有时候它们比成员函数好用得多，成员函数要么设计得好，要么就是累赘。而帮助函数可以看成是粘合剂，把用户的使用和数据＋算法很好的接合起来，同时，又容易改写。还有，容器的设计包含迭代器的设计，这可以为算法更好的抽象出来，算法面向迭代器，迭代器组织数据关系。算法的设计体现在，用仿函数做嵌入式，比如sudoku的构造函数，你可以写这样一个初始化函数：
sudoku::init(char* str){...}
实现的时候，就会问，用什么样的格式初始化呢？这样吧：
4...3.......6..8..........1....5..9..8....6...7.2........1.27..5.3....4.9........
但是有的人做的数独软件就不是这样，比如
400030000000600800000000001000050090080000600070200000000102700503000040900000000
那就不好了，你又要重载一个，这样做就相当于，为你的软件增添了‘规则’，而规则越多，越使接口复杂化。解决方法，1，可以是为专门的数据写适配器，把自己的数据定为标准；2，将这件事情，移给高层解决，用仿函数在外面完成。像下面这样：
class init_functor{public:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]]></description>
		<author><![CDATA[rickone]]></author>
		<pubDate>2008-05-07 01:52:00</pubDate>
		</item>
				<item>
		<title><![CDATA[计算机产生的随机数[1]]]></title>
		<link>http://blog.pfan.cn/rickone/34769.html</link>
		<description><![CDATA[写在最前面。我有一个朋友，一个女程序员，她的业余爱好是写小说，我看着她的小说里栩栩如生的人物觉得很了不起，她的脑子里可以想这么多好玩的人和事，于是我问，你为什么写小说啊，她只是简单的回答，我只是想写点很好的东西。我写不来那些，但我也希望我写的东西很好，我尽全力。
这篇由几个帖子引出，也是一直争论的焦点，std::rand()的性能怎样，随机数如何才算‘随机’，随机数如何检验。
它们是：
http://www.programfan.com/club/post-273908.htmlhttp://www.programfan.com/club/post-274446.html
1 随机数的应用
随机数应用在哪些方面？std::rand()有什么用？统计学在生产活动中有着非常广泛的应用，它深刻地影响到了科学界和人们的生活。工厂的产品检验，人口的普查，国家还有专门的统计局，资源能源等，几乎都离不开统计学。科学界，决策论，贝叶斯决策已经形成独立的理论，随机过程，计算机模拟，计算机访真，还有密码学，都是随着现代概率论和统计学的成熟而发展起来的一大批科学。
就计算机中的随机数来说，主要用处有2个：1，用于抽样的编号。这也是最原始和最主要的用途了，在没有计算机之前，人们是用随机数表来进行抽样的，做一个足够大的表，表中的数据是通过物理过程模拟得到，比如丢色子。比如，医学上有一种随机数表，叫乱数表，它是一个n*n的矩阵，每一个格子中填一个数字0-9，数字是混乱的，医学实验时，是这样得到随机数序列的，手指随便一指，指到一个格子，然后随机选一个方向，比如向右，然后延着这个方向读几个数字，组成随机数，然后将它平移到需要的范围内，比如，你要[0，150]的随机数，你得到的数字是378，那进行平移,378-150-150=78，就是78这个数。2，用于计算机模拟。比如统计计算中形成的一大类计算方法，蒙特卡罗方法，就是一种随机计算方法。比如，模拟退火算法中，会按当前温度和邻解和当前解的目标值差计算出一个概率值p，然后依这个概率p接受或者拒绝这个邻解，如果p=0.5，那就有一半的机会接受。再比如，遗传算法中的交叉概率和变异概率，都需要用到随机数来进行模拟。
2 随机数的经典产生
std::rand()算是比较经典的产生了。计算机产生之后，一开始只是将随机数表搬计算机的存储器，而本质上]]></description>
		<author><![CDATA[rickone]]></author>
		<pubDate>2008-05-03 01:23:00</pubDate>
		</item>
				<item>
		<title><![CDATA[遗传算法小记]]></title>
		<link>http://blog.pfan.cn/rickone/34323.html</link>
		<description><![CDATA[我的毕设是做TSP问题，给定一个图，n个顶点，求一个哈密顿圈（不连通认为以无穷大权连通），使总的权合最小，即最小哈密顿圈。它的通俗描述是，一个旅行商(traveling salesman)从一个城市出发，经过其它城市一次且仅一次，最后回到出发城市，求一个路径，使总的行程最短。
下面这个是用GA做的，城市数n=50，种群大小gn=100，交叉概率pc=0.98，变异概率pv=0.01，结束迭代的条件是，连续10个种群的平均评价值没有增长，图中值是种群平均评价值的倒数，也就是哈密顿圈总权和。从图中看出，它很好的收敛到某个较低值。但是最优个体并不一定出现在最后的种群，为什么？这很容易理解，算法是用种群为单位计算的，但我要的结果却是一个个体，以种群为单位是为了很好的避开局部最优，但是全局最优可能会存在于较后期的某个种群，而不一定是最后一个种群，以人类的历史为比喻，最聪明的人一定是今天地球上的某个人吗？人类历史也可能停止不前，只能说总体水平在优化，但我个人认为比爱因斯坦聪明的人还没有过，但它却不在最后一个种群当中。

GA收敛得很好，但是比较慢，它竟然进化了1千多代！相比SAA对一个相同数据的计算结果图如下：

它没有优化到前者那个水平，最后只能划一条直线的原因是温度已经降得过低了，已经没有可能再优化了。它的起伏比较大，但是它的优点是收敛快，它从17000左右优化到7000左右，只迭代了100次不到，而且它只迭代一个个体，相比之下GA优化到那个水平却进化了500代左右。SAA还有改进的空间，比如温度的控制，迭代次数和温度的关系，等。而GA就要从交叉的方法等改进。]]></description>
		<author><![CDATA[rickone]]></author>
		<pubDate>2008-04-19 15:54:00</pubDate>
		</item>
				<item>
		<title><![CDATA[去掉C/C++源程序中的注释]]></title>
		<link>http://blog.pfan.cn/rickone/34091.html</link>
		<description><![CDATA[一道题目，输入是一个正确的C/C++源程序，输出是将所有注释去掉之后的程序。不细想觉得很简单，字符串搜索，找到//后再找一个回车，删掉，找到/*后再找一个*/，删掉，还有什么好做的，太简单了。
给个测试例子：
#include "stdafx.h"#include &lt;iostream&gt;using namespace std;
int main(){&nbsp;cout&lt;&lt;"line 1 // hello"&lt;&lt;endl; // line 1&nbsp;cout&lt;&lt;"line 2 /* haha~ */"&lt;&lt;endl; // line 2&nbsp;cout&lt;&lt;"line 3 \" /* hehe */"&lt;&lt;endl; /* line 3 */&nbsp;/* ********\\\\\\\\\\/////////********&nbsp;this is test program&nbsp;this is test program&nbsp;this is test program&nbsp;*/&nbsp;return 0;}
这是正确的C++程序，它的输出要是：
#include "stdafx.h"#include &lt;iostream&gt;using namespace std;
int main(){&nbsp;cout&lt;&lt;"line 1 // hello"&lt;&lt;endl; &nbsp;cout&lt;&lt;"line 2 /* haha~ */"&lt;&lt;endl; &nbsp;cout&lt;&lt;"line 3 \" /* hehe */"&lt;&lt;endl; &nbsp;&nbsp;return 0;}
哇，这么一来想想就觉得复杂，字符串，先要找到字符串，字符串里的不算，字符串里还有转义符。。。
用状态机做会不会很方便，输入集中比较特殊的就这几个：/,*,",\，关键是在它的构造，在本子上画个表，纵向是表示状态，横向表示特殊的输入，表中的值就是状态的变化，再在旁边记录各个状态的含义，它大概是这样：
&nbsp;&nbsp; \输入&nbsp; /&nbsp;&nbsp; *&nbsp;&nbsp; "&nb]]></description>
		<author><![CDATA[rickone]]></author>
		<pubDate>2008-04-12 16:27:00</pubDate>
		</item>
				<item>
		<title><![CDATA[TMP计算素数]]></title>
		<link>http://blog.pfan.cn/rickone/33487.html</link>
		<description><![CDATA[这个程序不能通信编译,说明它并不是运行在运行期,它借助编译错误信息报出'指定范围的素数',比如下面程序将会在primes&lt;x&gt;中x是素数的类中发生错误,看错误信息吧...
#include &lt;cstdlib&gt;#include &lt;iostream&gt;
using namespace std;
struct true_type{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; true_type(){};};struct false_type{};
template&lt;bool,typename,typename B&gt;struct IfThenElse{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typedef B result_type;};
template&lt;typename A,typename B&gt;struct IfThenElse&lt;true,A,B&gt;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typedef A result_type;};
template&lt;int d,int i = d/2 &gt;struct is_prime{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typedef typename IfThenElse&lt;d%i==0,false_type,typename is_prime&lt;d,i-1&gt;::result_type&gt;::result_type result_type;};
template&lt;int d&gt;struct is_prime&lt;d,1&gt;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typedef true_type result_type;};
template&lt;int d&gt;struct primes{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typedef]]></description>
		<author><![CDATA[rickone]]></author>
		<pubDate>2008-03-21 22:45:00</pubDate>
		</item>
				<item>
		<title><![CDATA[[笔记].template&nbsp;修饰&nbsp;,&nbsp;双重模板]]></title>
		<link>http://blog.pfan.cn/rickone/33474.html</link>
		<description><![CDATA[代码：
template&lt;int N&gt;void printBitset(std::bitset&lt;N&gt; const&amp; bs){&nbsp;&nbsp;&nbsp;&nbsp; std::cout&lt;&lt;bs.template to_string&lt;char,char_traits&lt;char&gt;,allocator&lt;char&gt; &gt;();}
能在DevCPP里编译通过，那个.template的意思就是告诉编译器，紧跟to_string的&lt;并不是一个小于号，而是模板参数；需要这个 template修饰的地方（.或者-&gt;）是当前正处在一个模板中，前面的bs还未具现，它是一个模板函数里的某个参数，所以编译器是不知道它是什么东西的，如果你具现了，比如std::bitset&lt;100&gt; bs；那就不需要再加.template了。这和typename的第二个重要用法是一样的，用以申明模板中的参数的内嵌类型是一个类型，而不是静态变量。
双重模板是在模板参数中再用模板，比如
template &lt;typename T,template &lt;typename&gt; class CONT &gt;stack{...};
不是所有编译器都支持这个较后增加的C++特性，当然你需要在这个类里面形式化的具现这个模板模板参数，像CONT&lt;T&gt;...。]]></description>
		<author><![CDATA[rickone]]></author>
		<pubDate>2008-03-20 22:38:00</pubDate>
		</item>
				<item>
		<title><![CDATA[我写的多维数组auto_array[续]]]></title>
		<link>http://blog.pfan.cn/rickone/32766.html</link>
		<description><![CDATA[实现生成器,语法更简洁:
shape是一个全局唯一对象,用来生成多维数组的'外观',可以拿传统的C语法进行比较:
定义一个三维数组(传统):
int a[3][4][5];
一个动态三维数组:
auto_array&lt;int,3&gt; a(shape[3][4][5]);
形式上很相似,如果你不进行特殊的操作,完全可以拿下面的a代替上面的.所不同的是,传统的[3][4][5]是需要在编译期确定的,而下面的可以是运行期的动态变量,所在的存储空间也不同,上面占用栈空间,下面的是在堆上,由指定的分配器优化分配的.
你如果随意乱用shape,比如
auto_array&lt;int,3&gt; a(shape[3][4]);
将会引发编译错误,同样的,对其它维度数和shape后面的[]数不同的形式都会报错.换句话说,shape的[]会返回不同的类型,这取决于你用了几次[].
shape还可以用来传给reshape,形式是
a.reshape(shape[3][4][5]);
它不能再继续加括号指定范围了,他不能指定起始下标,如果希望不从0开始下标数组,只能使用另一种形式的reshape,这种形式值得再说明一下.
reshape(dim0,width0,start0)(dim1,width1,start1)(...)...;
为了防止空间的重复无用的分配,这里的reshape,在调用operator()的时候,并没有真的去'分配'它,只是设定了相应的维度宽度等值.而需要真正分配空间,可以几种方法:
1,调用一次operator[],哪怕没任何用.
2,在reshape语句末尾,加上一句now(),如
a.reshape(0,4)(1,5).now();
则会马上发生分配.有没有真的分配,会影响到其它和容器相关的函数,包括:
safe_bool转型,可以这样使用:
if(a)&nbsp; cout&lt;&lt;"a is not empty!"&lt;&lt;endl;
a可以自动转型,但这是安全的,你不能指望这样的代码通过编译:
bool b=a;
或者其它形式的头疼地隐式转换:
a &amp;&amp; true;
[这种安全转型是从boost里学的;)]
此外还有一些标准的迭代器函数,begin(),end()等]]></description>
		<author><![CDATA[rickone]]></author>
		<pubDate>2008-02-19 19:00:00</pubDate>
		</item>
				<item>
		<title><![CDATA[我写的多维数组auto_array]]></title>
		<link>http://blog.pfan.cn/rickone/32745.html</link>
		<description><![CDATA[练手的
[定义]
auto_array&lt;typename T, std::size_t dim, typename Allocator = _test_allocator&lt;T&gt; &gt; a;
第一个参数是元素类型,第二个是最高维度,维度标记从0到dim-1,第三个是一个分配器
[重塑数组大小]
reshape(std::size_t dim_index, std::size_t width, long start = 0);
第一个参数是指定第几维,第二个参数是指定该维的宽度,第三个参数是起始下标. 这个函数可以重叠使用,如
a.reshape(0,4);a.reshape(1,5);
等价于
a.reshape(0,4)(1,5);
[operator[]操作]
和C语言的数组[]操作一样,没有任何不同,只是多了运行时越界检查.
测试代码(编译环境Dev C++(GCC)):
#include &lt;iostream&gt;#include "auto_array.hpp"
using namespace std;
int main(int argc, char *argv[]){&nbsp;&nbsp;&nbsp; auto_array&lt;int,1&gt; a;&nbsp;&nbsp;&nbsp; a.reshape(0,5);&nbsp;&nbsp;&nbsp; try {&nbsp;&nbsp;&nbsp; a[0]=1;&nbsp;&nbsp;&nbsp; a[0]+=2;&nbsp;&nbsp;&nbsp; a[1]=3;&nbsp;&nbsp;&nbsp; a[4]=a[0]*a[1];&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; catch(runtime_error &amp;err)&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout&lt;&lt;err.what()&lt;&lt;endl;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; system("PAUSE");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;&nbsp;&nbsp;&nbsp;]]></description>
		<author><![CDATA[rickone]]></author>
		<pubDate>2008-02-19 00:08:00</pubDate>
		</item>
				<item>
		<title><![CDATA[[笔记]enable_if的原理]]></title>
		<link>http://blog.pfan.cn/rickone/32706.html</link>
		<description><![CDATA[enable_if是用来(可以用来)控制重载函数的是否可用,这一点没有直观感受,比如,我写了一个形式的重载函数,但是我需要在某种条件下取消它,这时候它就可以派上用场,当然这里是模板函数.
function的构造函数有类似下面的形式:
&nbsp;&nbsp;&nbsp; template&lt;typename Functor&gt;&nbsp;&nbsp;&nbsp; BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &amp;) f#ifndef BOOST_NO_SFINAE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ,typename enable_if_c&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (boost::type_traits::ice_not&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (is_integral&lt;Functor&gt;::value)&gt;::value),&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&n]]></description>
		<author><![CDATA[rickone]]></author>
		<pubDate>2008-02-16 02:34:00</pubDate>
		</item>
		</channel>
</rss>