日志分类:数学类文档

你的手机号码是质数吗?

2009/03/14 | 13:30 | 分类:数学类文档 | 标签: | 1,114次阅读

  Happy PI Day !
  PI Day当然要装模作样研究一下数学了。刚才做了一项无聊的工作,统计了一下北京移动动感地带早期号段(13810000000~13811999999)以及我的手机通信录中的质数手机号码。结果见下表:

你的手机号码是质数吗?

  Wikipedia的Prime number页面提供了一些在线的质数计算、生成、校验工具的链接。你的手机号码是质数吗?如果一眼看不出来,可以上去查查。
  进一步统计了以下数据(写了一个isprime小程序,然后用shell脚本东拼西凑来计算:

你的手机号码是质数吗?

  1、3、7、9结尾的所有1~4位数均是13810000000~13811999999号段中至少一个质数号码的结尾。不知道这个性质对于所有11位数是否全部成立。或者推广开,1、3、7、9结尾的所有m~n位数是否至少是一个p~q位质数的结尾?这东西我就不会证明了,不知道前人有没有相关的工作。
  数学迷们是否愿意选择一个质数手机号码呢?至少有人喜欢以质数结尾的。不过我想更Geek一些的人可能会选择包含PI或e之类的号码吧。包含的位数越多,这样的号码越少。1314159号段属于湖南郴州联通,当地的数学迷有福了。
  冠仔的手机号码就是一个质数。他觉得手机号码可以用作数据挖掘。嗯,我暂时没有想到能从中挖出什么特别的东西(所谓的“吉祥号”就算了,这个不用挖也看得出来),想来想去总觉得像是算命。

基于Excel的数独辅助填充表

2007/02/02 | 20:00 | 分类:数学类文档 | 标签: | 743次阅读

基于Excel的数独辅助填充表

下载:
http://www.linjian.cn/files/excel/SudokuTable.rar
http://files.linjian.org/excel/SudokuTable.rar
 
截图:
 
★简介★
  本表是数独游戏的辅助填充工具,旨在方便游戏者正确快速地完成数独,省去铅笔橡皮之烦。本表并非数独自动求解工具,深度推理判断仍需人脑介入,不失游戏之乐趣。
  本表使用 Excel 2007 的公式与条件格式功能完成,不涉及宏与 VBA 编程,可以放心使用。
★功能★
  1、左上表为游戏填充区,游戏者应在此区域填写题目及答案。对于同一行、列或九宫格出现相同数字的错误情况,予以高亮显示。
  2、右上表为可能性提示区,提示每个单元格在不使得同一行、列或九宫格出现相同数字的情况下允许填写的数字。对于其它单元格已存在的错误数字致使某一单元格无数可填的错误情况,予以高亮显示。
  3、左下表为直接判断提示区,数字对应右上表相应单元格中可能性的种数。对于唯一可能性的单元格示以黄色标志,对于已经填充过的单元格示以绿色标志,对于不可直接判断的单元格示以红色标志。
  4、右下表为冲突提示区,对于某些错误数字致使同一行、列或九宫格中的两个或两个以上单元格只能填写相同数字的错误情况,将出现非零数字并予以高亮显示。
★备注★
  对于猜测的数字,可以用特殊的格式(如下划线)标识。此后填充时如果出现错误情况,可以连续使用撤销功能,直到标识过的数字被清除。
  本表应用了 Excel 2007 的条件格式新特性,因此另存为早期 Excel 格式后不能保证功能完整。

基于复杂系统理论的计算机病毒传播模型的计算机仿真分析

2006/07/23 | 20:05 | 分类:数学类文档 | 标签: | 709次阅读

基于复杂系统理论的计算机病毒传播模型的计算机仿真分析

(北京理工大学2006年全国大学生数学建模竞赛建模辅导选修课程作业)

林健,范舟斌
计算机科学技术学院01110407班

2006年5月

摘要

  现实生活中,存在大量具有众多状态变量、反馈结构复杂、输入与输出呈现非线性特征的复杂系统。现有的理论不能通过简单的公式或统计方法来精确地研究它们的行为。目前人们对复杂系统的描述和研究,主要是将多学科知识综合,结合定性研究和定量分析方法,对低层次子系统进行宏观集成,对系统较高层次部分微观化处理,通过计算机仿真技术建立系统模型并调试模型参数,同时辅以知识工程技术(如专家系统)等。复杂系统理论作为知识爆炸的时代信息整合的工具,是未来科学发展的必然选择。

  本文以计算机病毒传播模型为例,通过设定实时状态参量、状态转移因子,表达计算机病毒传播系统在各个时刻的不同状态和发展趋势。使用计算机编程模拟复杂系统中的诸多因素的相互作用及系统长期演化过程,比较成功地演示了计算机病毒在不同条件下传播的趋势,同时给出了具有针对性的病毒防控方案。计算机仿真方法充分利用了计算机强大的逻辑功能和计算能力,是一种初等的、容易理解的复杂系统分析方法。与传统的微分方程乃至更复杂的数学模型相比,它更注重问题本身的性质,对数学理论的要求相对较低,同时对各类现实问题的适应性和应变性强,是应用领域值得推广的方法。

关键词

  复杂系统,计算机病毒,计算机仿真

全文下载地址:
http://www.linjian.cn/files/works/virus_model.pdf
http://files.linjian.org/works/virus_model.pdf

用Excel实现生命游戏

2006/05/07 | 21:21 | 分类:数学类文档 | 标签: | 872次阅读

用Excel实现生命游戏

  同学的数据结构课程作业是实现生命游戏的演示。经典的生命游戏规则不再赘述,网上也有很多用C等其它编程语言的实现。这里我们看看如何用Excel快速地实现生命游戏。注意我们仅使用Excel函数即可,无需调用宏与VBA。
  步骤:
  1、新建一个空的Excel工作表,选中所有单元格,调小字号,并调整单元格长宽使之成为恰好容纳一个字符的小正方形。
  2、为方便后续观察,对所有单元格设置条件格式:当单元格值为1时背景变为红色。
  3、在A1单元格填0,拖动A1句柄将A1:P16单元格(当然可以更大范围)全部填充为0,表示无生命点。
  4、设置初始生命状态:将B2:O15单元格中任意个填为1,表示有生命点。第1、16行与第A、P列用作边界限制,不作为生命点。
  5、将A18:P33单元格全部填充为0(空出第17行以免上下混淆),用来显示生命过程第一次迭代的结果。
  6、在B19单元格中输入以下公式:
=IF(B2=1,IF(OR(A1+B1+C1+A2+C2+A3+B3+C3=2,A1+B1+C1+A2+C2+A3+B3+C3=3),1,0),IF(A1+B1+C1+A2+C2+A3+B3+C3=3,1,0))
用以计算该位置当前生命状态。拖动B19句柄填充B19:O32单元格,Excel将自动修改公式中的相对引用地址。
  7、A18:P33单元格已随即显示生命过程第一次迭代的结果。将A18:P33单元格选中并复制,依次粘贴到A35:P50、A52:P67等与上次结果相隔一行的位置,Excel将自动计算后续的生命迭代状态。
  8、现在修改A1:P16单元格中的初始生命状态,会看到下方的迭代生命状态自动更新。
  事实上,我们可以把一个Excel单元格理解为一个有限状态的自动机。一群相互关联的自动机在确定的规则(公式)下以相同的周期改变自身状态,从而形成复杂但有序的群体行为。Excel为我们提供了这样一个平面结构的自动机运作平台,大家能否在其基础上构思出一些更有意思、更加实用的应用呢?
  下载:
http://www.linjian.cn/files/excel/LifeGame.rar
http://files.linjian.org/excel/LifeGame.rar

浅议Fibonacci(斐波纳契)数列求解

2006/05/05 | 20:18 | 分类:数学类文档 | 标签: | 1,812次阅读

浅议Fibonacci(斐波纳契)数列求解

  Fibonacci数列:

浅议Fibonacci(斐波纳契)数列求解

  描述了动物繁殖数量、植物花序变化等自然规律。作为一个经典的数学问题,Fibonacci数列常作为例子出现在程序设计、数据结构与算法等多个相关学科中。

  下面简单地分析一下常见的Fibonacci数列求解算法。

  1、递归法。大多数教材在讲解递归算法时总喜欢以Fibonacci数列为例,这是因为我们可以直观地从定义公式的第三行看出Fibonacci数列的递归性。其C++实现如下:

unsigned long Fib(int n)
{
    if (n <= 1) {
        return n;
    } else {
        return Fib(n - 1) + Fib(n - 2);
    }
}

  递归算法与定义公式十分吻合,容易理解,但计算过程存在大量重复的运算,时间复杂度达到了O(2^n),使用的内存空间也随着函数调用栈的增长而增长。这显然不适于实用的程序。

  2、表驱动的递归法。这里不提纯粹的表驱动法,因为对于项数未知的Fibonacci数列开启大片的空间来换取时间未免不值得且不负责。我们只是为了消除递归法中大量重复的运算,可以将已经计算过的中间值存入一个表,已备后续使用:

#define MAX_LOG 20
static unsigned long Logs[MAX_LOG] = {0};
unsigned long Fib(int n)
{
    if (n <= 1) {
        return n;
    } else if (n < MAX_LOG && Logs[n] != 0) {
        return Logs[n];
    } else {
        Logs[n] = Fib(n - 1) + Fib(n - 2);
        return Logs[n];
    }
}

  当n小于保存的表长时,由于每个中间值只计算一次,时间复杂度降为O(n)。但随着n的增大,要想维持O(n)的时间复杂度,就必须扩大保存的表长,这就造成了存储空间的浪费。

  3、迭代法。求Fibonacci数列第n项时虽然要用到前面两项的值,但它们仅作为临时计算的中间值,不作为结果输出,因此无保留的必要,完全可以转化成迭代法求解:

unsigned long Fib(int n)
{
    int i;
    unsigned long a = 0, b = 1, c;
    if (n <= 1) {
        return n;
    } else {
        for (i = 2; i <= n; i++) {
            c = a + b;
            a = b;
            b = c;
        }
        return c;
    }
}

  迭代法的时间复杂度为O(n),使用的内存空间也不会动态上涨。个人认为Fibonacci数列更适宜作为迭代法而非递归法的典例出现在教材上。

  下面给出两种数学性较强的算法。考虑到表达的简洁性,用Matlab实现:

  4、转移矩阵法。此方法通常见于线性代数中的Markov过程示例。Fibonacci数列第n项与第n-1项可以通过转移矩阵的n-1次迭代求出:

浅议Fibonacci(斐波纳契)数列求解

  代码如下:

function y = Fib(n)
    first = [1; 0];
    trans = [1 1; 1 0];
    last = trans ^ (n - 1) * first;
    y = last(1, 1);
end

  此算法的时间复杂度相当于计算矩阵乘方的时间复杂度。在计算2阶矩阵n次方时,如果直接按矩阵乘法定义式展开,不加特别优化,其时间复杂度为O(n)。

  5、通项公式法。Fibonacci数列的通项公式如下(证明略):

浅议Fibonacci(斐波纳契)数列求解

  利用通项公式可以得到Fibonacci数列的任何项:

function y = Fib(n)
    sr5 = sqrt(5);
    y = uint32((((1 + sr5) / 2) ^ n - ((1 - sr5) / 2) ^ n) / sr5);
end

  该方法的时间复杂度貌似为O(1),但我们还应该考虑乘方运算的时间消耗。不加特别优化时,用乘法实现n次乘方的时间复杂度为O(n)。考虑到浮点数计算效率和精度问题,此方法在计算机实现时不如转移矩阵法。

  下面再给出两种对计算机实现有特别意义,但同时有一定局限性的实现方法(只是实现方法,不能称为新的算法)。其中使用了一些C++编程技巧,对使用其它语言实现也有一定的参考价值:

  6、模板元编程法。通常我们在C++中使用模板,仅限于类模板与函数模板。事实上C++支持模板元编程,理论上可以在编译时执行任何计算(甚至包含选择、循环、递归等结构)。代码如下:

#define Fib(N) FibT<N>::Val
template<int n> struct FibT
{
    enum
    {
        Val = FibT<n - 1>::Val + FibT<n - 2>::Val
    };
};
template<> struct FibT<0>
{
    enum
    {
        Val = 0
    };
};
template<> struct FibT<1>
{
    enum
    {
        Val = 1
    };
};

  我们用一个结构体作为模板的载体,用一个枚举值保存运算结果。其中第一个模板为基本递归过程(使用递归算法是为了说明的简便,完全可以用其它算法替代,以加速编译过程),后两个模板为n=0、1时的模板特化。通过#define语句将模板调用简写成类似函数调用的方式。程序在编译时运算所需的 Fibonacci数列项,将结果作为常量嵌入编译好的程序。运行时直接使用结果,时间复杂度真正地变成了O(1)。但这一方法最大的局限就是只能对常量嵌入,程序中出现诸如计算Fib(i++)的情况则无能为力。尽管如此,这比在代码中手工计算并写入所需的值要直观准确,比通过纯粹的表驱动法“空间换时间”要方便快捷。

  7、函数对象法。此方法主要用于C++ STL编程的通用算法方面,其执行行为也有别于以上其它方法:

class Fib
{
public:
    Fib() : a(0), b(1), n(0)
    {
    }
    unsigned long operator()()
    {
        if (n <= 1) {
            n++;
            return n - 1;
        } else {
            int c;
            c = a + b;
            a = b;
            b = c;
            return c;
        }
    }
private:
    int a, b, n;
};

  这个函数类对象的行为可以理解为一个“Fibonacci数列发生器”,其测试性调用如下,程序将依次打印

void test(int i)
{
    Fib fib;
    do {
        cout << fib() << endl;
    } while (i--);
}

  函数对象具有与函数指针类似的行为,同时又能保存自身的一些属性,因此常用于STL通用算法编程。但针对单个的Fibonacci数列项求值,灵活性不如一般的方法。

  希望读者能够从上面的算法分析中举一反三,有所领悟。

参考资料:
  1、Bruce Eckel,Thinking In C++ Volume 2: Practical Programming,机械工业出版社,2006
  2、William J. Collins,Data Structures and the Standard Template Library,机械工业出版社,2003
  3、Knott's Surrey University,The Home page for Fibonacci Numbers and the Golden Section,http://www.mcs.surrey.ac.uk/Personal/R.Knott/Fibonacci/

页面存档: 上页 1 2 下页