馨荣家园

室主感言:可以走错路,不可不走路,也不可总踩别人脚印走路。

  VC知识库BLOG :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 登录 ::
  51 随笔 :: 5 文章 :: 1328 评论 :: 18 Trackbacks
<2004年6月>
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

News

阿荣陋室更名为馨荣家园,寓指温馨和繁荣。

留言簿(195)

随笔分类

随笔档案

文章分类

文章档案

相册

友情链接

搜索

最新评论

阅读排行榜

评论排行榜

2004年6月10日 #

欧几里德算法

欧几里德算法又称辗转相除法,用于计算两个整数a,b的最大公约数。其计算原理依赖于下面的定理:

定理:gcd(a,b) = gcd(b,a mod b)

 证明:a可以表示成a = kb + r,则r = a mod b
 假设d是a,b的一个公约数,则有
 d|a, d|b,而r = a - kb,因此d|r
 因此d是(b,a mod b)的公约数
 
 假设d 是(b,a mod b)的公约数,则
 d | b , d |r ,但是a = kb +r 
 因此d也是(a,b)的公约数
 
 因此(a,b)和(b,a mod b)的公约数是一样的,其最大公约数也必然相等,得证

欧几里德算法就是根据这个原理来做的,其算法用C++语言描述为:

    void swap(int & a, int & b)
    {
        int c = a;
        a = b;
        b = c;
    }
    int gcd(int a,int b)
    {
        if(0 == a )
        {
            return b;
        }
        if( 0 == b)
        {
            return a;
        }
        if(a > b)
        {
            swap(a,b);
        }
        int c;
        for(c = a % b ; c > 0  ; c = a % b)
        {
            a = b;
            b = c;
        }
        return b;
    }

模P乘法逆元

对于整数a、p,如果存在整数b,满足ab mod p =1,则说,b是a的模p乘法逆元。

定理:a存在模p的乘法逆元的充要条件是gcd(a,p) = 1

 证明:
 首先证明充分性
 如果gcd(a,p) = 1,根据欧拉定理,aφ(p) ≡ 1 mod p,因此
 显然aφ(p)-1 mod p是a的模p乘法逆元。
 
 再证明必要性
 假设存在a模p的乘法逆元为b
 ab ≡ 1 mod p
 则ab = kp +1    ,所以1 = ab - kp
 因为gcd(a,p) = d 
 所以d | 1
 所以d只能为1

扩展欧几里德算法

扩展欧几里德算法不但能计算(a,b)的最大公约数,而且能计算a模b及b模a的乘法逆元,用C语言描述如下:

 int    gcd(int    a,    int    b    ,    int&    ar,int    &    br)
 {
  int    x1,x2,x3;
  int    y1,y2,y3;
  int    t1,t2,t3;
  if(0    ==    a)
  {//有一个数为0,就不存在乘法逆元
               ar    =    0;
               br    =    0    ;
               return    b;
  }
  if(0    ==    b)
  {
               ar    =    0;
               br    =    0    ;
               return    a;
  }
  x1    =    1;
  x2    =    0;
  x3    =    a;
  y1    =    0;
  y2    =    1;
  y3    =    b;
  int    k;
  for(    t3    =    x3    %    y3    ;    t3    !=    0    ;        t3    =    x3    %    y3)
  {
   k    =    x3    /    y3;
   t2    =    x2    -    k    *    y2;
   t1    =    x1    -    k    *    y1;
   x1    =    y1;
   x1    =    y2;
   x3    =    y3;
   y1    =    t1;
   y2    =    t2;
   y3    =    t3;
  }
  if(    y3    ==    1)
  {
   //有乘法逆元
   ar    =    y2;
   br    =    x1;
   return    1;
  }else{
          //公约数不为1,无乘法逆元
           ar    =    0;
           br    =    0;
           return    y3;
  }
 }

扩展欧几里德算法对于最大公约数的计算和普通欧几里德算法是一致的。计算乘法逆元则显得很难明白。我想了半个小时才想出证明他的方法。

首先重复拙作整除中的一个论断:

如果gcd(a,b)=d,则存在m,n,使得d = ma + nb,称呼这种关系为a、b组合整数d,m,n称为组合系数。当d=1时,有 ma + nb = 1 ,此时可以看出m是a模b的乘法逆元,n是b模a的乘法逆元。

为了证明上面的结论,我们把上述计算中xi、yi看成ti的迭代初始值,考察一组数(t1,t2,t3),用归纳法证明:当通过扩展欧几里德算法计算后,每一行都满足a×t1 + b×t2 = t3

 第一行:1 × a + 0 × b = a成立
 第二行:0 × a + 1 × b = b成立
 假设前k行都成立,考察第k+1行
 对于k-1行和k行有
 t1(k-1)    t2(k-1)  t3(k-1)
 t1(k)      t2(k)    t3(k)
 分别满足:
 t1(k-1) × a + t2(k-1) × b = t3(k-1)
 t1(k)   × a + t2(k)   × b = t3(k)
 根据扩展欧几里德算法,假设t3(k-1) = j t3(k) + r
 则:
  t3(k+1) = r
  t2(k+1) = t2(k-1) - j × t2(k)
  t1(k+1) = t1(k-1) - j × t1(k)
 则
         t1(k+1) × a + t2(k+1) × b 
        =t1(k-1) × a - j × t1(k) × a +
         t2(k-1) × b - j × t2(k) × b
       = t3(k-1) - j t3(k) = r 
       = t3(k+1)
 得证

因此,当最终t3迭代计算到1时,有t1× a + t2 × b = 1,显然,t1是a模b的乘法逆元,t2是b模a的乘法逆元。

发表于 2004-06-10 22:33 馨荣家园 阅读(22868) | 评论 (25)编辑 收藏

一个奇怪的工厂

我一直想用一种浅显易懂的方式来解释进程、线程的概念,但是总不成功。

在我看来,进程就象一个工厂,工厂有厂房、设备。其中厂房就象内存空间,摆在哪里由工人使用。 如果厂房内的一块地方已经处于使用中了,这叫内存提交(Commit),如果一块地方打算用做某个用途 但是还没有使用,这叫内存保留(Reserve),其他的地方就是空闲厂房,就是自由内存(Free Memory)。 设备是进程内的对象,他占用一定的厂房空间,允许工人去操作它。

进程这个工厂是很奇怪的,它的厂房和设备都允许多个工人去操作它,但是如果多个工人去 操作它,就叫并发操作,此时设备就不能正常运行了。工厂的工人从来不遵守规章,他们不顾别人 是否在操作工厂中的设备和厂房,只要需要就会去操作。因此为了正常运行,必须由设备绑一个锁, 每个工人要操作设备时,就去锁上它,这样别人就不能操作设备和厂房了,这叫并发控制或并发保护。

工厂是一个可以运营的实体,但是它本身是没有能力运营的,运营完全靠它的工人进行。这个 工人就称为线程。一个工厂开始建立时总有一个工人,这个工人称为主线程。根据需要,它创建其他的 工人来做事情,这些工人虽然是它创建的,但是不具有父子关系,其实他们的低位是对等的。所有的工人 都能同时做事情,因此多个工人做事比一个工人要快。

这个工厂还很不人道,这个工厂要结束运营,必须所有的工人都死亡才行。而如果主动杀调工人 又会导致一定问题,因此要求工人最好都是自杀的。当所有工人都自杀以后,工厂也就终结了。

有些工人干同样的活,我个人称呼他们为同态线程。同态线程操作厂房里的空间时,由于思维一样, 因此总是到同一个地方去操作。为了不让这些工人操作工厂内同一个空间,工厂提供了一种叫TLS的 通道,当工人通过TLS去操作空间时,看起来象操作同一个空间,实际上是完全不相关的。

需要注意的是,这种TLS通道存取的空间虽然看起来是工人自己的,实际上他们还是属于进程的。这样,线程没有自己的 厂房和设备,它始终使用进程的。而进程自己不会动,它所有动作都是由线程完成的。

发表于 2004-06-10 05:30 馨荣家园 阅读(1354) | 评论 (1)编辑 收藏