精华内容
下载资源
问答
  • 二柱子四则运算3

    2016-03-19 21:23:00
    可怜的二柱子……又次被坑了…… 老师又在上次的“二柱子四则运算2”的基础上增添了要求,如下: 1、学生写的程序必须能判定用户的输入答案是否正确。直到题目结束,告诉用户做对了几道题。 2、程序必须能处理...

    二柱子四则运算3

    可怜的二柱子……又一次被坑了……

    老师又在上次的“二柱子四则运算2”的基础上增添了要求,如下:

    1、学生写的程序必须能判定用户的输入答案是否正确。直到题目结束,告诉用户做对了几道题。

    2、程序必须能处理四种运算的混合模式。

    注意:连续的减法和除法,应该遵守左结合的规定。

            连续除法要打括号,否则会引起歧义。


    一、实验思路

          这次的实验是结对开发的项目第一次,我的合作小伙伴是孔宇航孔同学,说实话这是我俩第一次合作,因此各方面都还需要磨合和适应,不过总体来说分工合作明确,效果还算可以~鉴于我们编程能力和逻辑思维方式的差异,最后决定由我来执行编写程序,她来把握总体流程、分析并设计算法并适当的查阅相关的资料。   

          关于这次实验,由于上次实验我的思维有点混乱,写出的代码老师说重复率太高,而她的代码也是很多功能没有实现,所以我们决定重新静下心来编写代码。这次我们延续上次的思想,将很多内容封装到函数里,包括:“选择打印方式”、“判断输入的01菜单是否正确”、“生成某一个范围内的随机数”、“生成随机的分数”、“生成一个运算符”、“判断整数的正负并取相反数”、“把int类型装换为string类型”、以及“含有括号的运算”、“含有真分数的运算”和“不含真分数的运算”等等。运行程序时用户先选择相关的参数定制:题目个数、数值范围、是否打印到文件里、是否含有括号、加减或者四则运算等等。

    部分函数的思路和功能:

    1、  生成一个随机运算符:

          根据从主函数读取到的用户的选择:是否包含乘除运算来随机生成0-3四个数字分别代表+-*/四则运算,并将其作为函数的返回值。单独列出这个函数的目的是防止出现像上次的程序一样分析switch语句的四种情况时代码冗余而导致思维混乱。

    2、  把int类型转换为string:

          经过我们查阅资料,决定使用:#include<stdio.h>类库中的str=itoa(shu, zhuan, 10)函数来将生成的随机整数保存成string字符串的形式。

    编写此函数是因为,所有的算式都是用string字符串存的,方便输出和查重,因此每一个操作符都要转换成string才能直接插到算式中。

    3、  生成某一个范围内的真分数:

          通过判断分子小于分母(真分数)、分子分母没有公约数(最简分式)产生那个数:分子和分母的值,再通过随机生成正负号来决定分数值的正负,最后将符号、分子、分数线和分母写到一个string类型里,并将分数形式和分数的值返回。

    4、  查重:

          查重的函数上次的实验中有一些问题,因为是使用int类型的二维数组存的因此不能查关于真分数的重复,而这次采用string类型数组的方法,将所有的算式依次存到string类型的数组中,然后逐个比较新生成的算式与其是否相等。如果相等就舍掉相应的式子,并且计数的值-1。

    5、  关于含有真分数和不含有真分数的计算:

          就是调用以上各个函数,再根据用户选择的是否含有负数、除法有无余数等等进行选择和判断,但是要将结果保存下来,便于判断是否回答正确。

    6、  含有括号的计算:

          这个我们讨论了很久……也阅读了很多资料和同学们的代码,有了基本的思路,但是在我编写代码实现的过程中发现思路还存在漏洞,根本进行不下去了。今天的时间有限,对于两个星期还是没有研究出这个算法的我也是十分懊恼的……我发誓,下周有时间我一定要把含有括号的式子写出来,一定!!!!!!!

          但是我们编写的含有括号的函数我没有删掉,附在了实验源码里。思路如下:

          我们打算用“递归”的思想先随机生成一个二元运算的式子,当然这里的操作数和运算符都是随机生成的,然后用double类型变量记录算式的值,然后随机生成加不加括号、并且下一个运算符是加在前面还是后面。然后将生成的式子再作为二元运算的操作数,直到随机生成的是不加括号,则输出式子。

    7、  主函数:

          本次实验最大的差异就是要用户计算结果、系统判断是否回答正确并记录正确的题目数。一次我们的函数中只是返回一个算式和算式的值,在主函数中循环N次,每一次输出就让用户输入,并判断是否正确。算式是用string类型存放,算式的值用double类型存放,如果答案是整数,直接让用户输入一个整数;如果答案是小数,先输入int型分子,再输入分母,并强制转换double计算结果。判断对错时,设定一个精度(10的负7次方),如果用户的输入在此范围内则认定正确。

        (PS.在这里我不得不说,我们本来打算接收用户输入的string类型的值(可以直接输入分数),这就要用ASC码分离出分子分母和分数线。最后我们还是输给了时间……┑( ̄Д  ̄)┍唉……)

    二、实验源代码

     实验的源代码如下:

      1 //二柱子四则运算3,2016/3/14,赵子茵&孔宇航
      2 
      3 #include<iostream>
      4 #include<time.h>
      5 #include<stdlib.h>
      6 #include<stdio.h>
      7 #include<string>
      8 #include<fstream>
      9 #include<iomanip>
     10 #include<cmath> 
     11 #define random(x) (rand()%x)
     12 using namespace std;
     13 
     14 /*选择打印方式*/
     15 void Output(int sf)
     16 {
     17     if (sf == 1)//保存文档
     18     {
     19         ofstream outfile("formula.txt", ios::out);
     20         if (!outfile)
     21         {
     22             cout << "Open error!!" << endl;
     23             exit(1);
     24         }
     25         outfile << "----------------欢迎!小学生四则运算答题系统:-D----------------" << endl;
     26         outfile.close();
     27     }
     28 }
     29 
     30 /*判断输入0.1的是否输入正确*/
     31 int Istrue_input(int mnu01)
     32 {
     33     while (1)
     34     {
     35         if (mnu01 != 0 && mnu01 != 1)
     36         {
     37             cout << "输入有误,请重新输入(请输入0或1):" << endl;
     38             cin >> mnu01;
     39         }
     40         else
     41             break;
     42     }
     43     return mnu01;
     44 }
     45 
     46 /*生成一个某范围内的随机数(正负都有)*/
     47 int Creat_random(int r1, int r2)
     48 {
     49     int r, shu;
     50     /*srand((int)time(0));*/
     51     r = r2 - r1;
     52     shu = r1 + rand() % r;
     53     return shu;
     54 }
     55 
     56 /*生成一个随机运算符*/
     57 string Create_oper(int lai)
     58 {
     59     srand((int)time(0));
     60     string sign;
     61     int Num_sym, Sign_num;
     62     if (lai == 0)//加减
     63         Num_sym = 2;
     64     else if (lai == 1)//加减乘除
     65         Num_sym = 4;
     66     Sign_num = rand() % Num_sym;//生成随机的数字代表运算符
     67     switch (Sign_num)
     68     {
     69     case(0) : sign = '+'; break;
     70     case(1) : sign = '-'; break;
     71     case(2) : sign = '*'; break;
     72     case(3) : sign = '/'; break;
     73     }
     74     return sign;
     75 }
     76 
     77 /*判断整数正负并取相反数*/
     78 int Opp_zf(int a)
     79 {
     80     if (a < 0)
     81         a = -a;
     82     return a;
     83 }
     84 
     85 /*把int类型转换为string类型*/
     86 string Int_str(int shu)
     87 {
     88     char zhuan[100];
     89     string str,zuo="(",you=")";
     90     str=itoa(shu, zhuan, 10);
     91     if (shu < 0)
     92         str = zuo + str + you;
     93     return str;
     94 }
     95 
     96 /*生成一个(某范围)真分数*/
     97 void Creat_fen(int r1, int r2, string &fenshu, double &zhi)
     98 {
     99     /*srand((int)time(0));*/
    100     int i, r = r2 - r1, up, down, s;
    101     bool flag;
    102     string xian = "/", fu = "-", zuo = "(", you = ")";
    103     /*char zhuan1[10], zhuan2[10];*/
    104     string zhuan1, zhuan2;
    105 loop:do
    106     {
    107          flag = false;//不能定义全局变量!!
    108          up = r1 + rand() % r;
    109          up = Opp_zf(up);
    110          down = r1 + rand() % r;
    111          down = Opp_zf(down);
    112     } while ((up >= down) || (down == 0) || (up == 0));//分子≥分母 or 分母=0 or 分子=0 重新生成
    113     
    114     for (i = 2; i <= up; i++)
    115     {
    116         /*if ((i == -1)|| (i == 0))
    117         continue;*/
    118         if (up%i == 0 && down%i == 0)
    119         {
    120             flag = true;//有公约数    
    121             break;
    122         }
    123     }
    124     if (flag == true)
    125     {
    126         goto loop;
    127     }
    128     else
    129     {
    130         zhi = (double)up / (double)down;
    131         //itoa(up, zhuan1, 10);//分子转换成string类型
    132         //itoa(down, zhuan2, 10);//分母转换成string类型
    133         zhuan1 = Int_str(up);//up/down都是正数不会再加一层括号
    134         zhuan2 = Int_str(down);
    135         s = rand() % 2;
    136         switch (s)
    137         {
    138             //正分数
    139             case(0) : 
    140                 fenshu = zuo + zhuan1 + xian + zhuan2 + you; 
    141                 break;
    142             //负分数
    143             case(1) : 
    144                 fenshu = zuo + fu + zhuan1 + xian + zhuan2 + you;
    145                 zhi = -zhi;
    146                 break;
    147         }
    148     }
    149     //return fenshu;
    150 }
    151 
    152 ///*查重*/
    153 //bool Is_rept(string str1, string str2)
    154 //{
    155 //    if (str1 == str2)
    156 //        return true;//重复
    157 //    return false;//不重复
    158 //}
    159 
    160 /*含有括号*/
    161 void Have_kuohao(int r1, int r2, string &formula,double &zhi)
    162 {
    163     srand((int)time(0));
    164     int op,op1, op2;
    165     int yn, qh;//代表“是否加括号”和“运算符在前后”的数字
    166     string symbol1,symbol2;
    167     string zhuan,zhuan1, zhuan2;
    168     string jia = "+", jian = "-", cheng = "*", chu = "/",zuo="(",you=")";
    169 
    170     zhi = (double)Creat_random(r1, r2);
    171     op1 = Creat_random(r1, r2);
    172     op2 = Creat_random(r1, r2);
    173     op = Creat_random(r1, r2);//假设op2做分母不能为0
    174     while (1)
    175     {
    176         if (op == 0)
    177             op = Creat_random(r1, r2);
    178         else
    179             break;
    180     }
    181     zhuan1 = Int_str(zhi);
    182     zhuan2 = Int_str(op);
    183     symbol1 = Create_oper(1);
    184 
    185     if (symbol1 == "+")
    186     {
    187         zhi = (double)op1 + (double)op2;
    188         formula = zhuan1 + jia + zhuan2;
    189         yn = rand() % 2;
    190         switch (yn)
    191         {
    192             //外面不加括号
    193             case(0) : break;
    194             //外面加括号
    195             case(1) :
    196             {
    197                         formula = zuo + formula + you;
    198                         qh = rand() % 2;
    199                         symbol2 = Create_oper(1);
    200                         switch (qh)
    201                         {
    202                             //加到前面
    203                             case(0) :
    204                            {
    205                                     formula = symbol2 + formula;
    206                                     op = Creat_random(r1, r2);
    207                                     zhuan = Int_str(op);
    208                                     if (symbol2 == "+")
    209                                     {
    210                                         zhi = (double)op + zhi;
    211                                         formula = zhuan + jia + formula;
    212                                     }
    213                                     else if (symbol2 == "-")
    214                                     {
    215                                         zhi = (double)op - zhi;
    216                                         formula = zhuan + jian + formula;
    217                                     }
    218                                     else if (symbol2 == "*")
    219                                     {
    220                                         zhi = (double)op * zhi;
    221                                         formula = zhuan + cheng + formula;
    222                                     }
    223                                     else if (symbol2 == "/")
    224                                     {
    225                                         if (zhi == 0)//防止出现随机生成的除号后面的值为0;
    226                                             break;
    227                                         else
    228                                         {
    229                                             zhi = (double)op / zhi;
    230                                             formula = zhuan + chu + formula;
    231                                         }    
    232                                     }
    233                                     break;
    234 
    235                              }
    236                              //加到后面
    237                             case(1) :
    238                             {
    239                                     formula = formula + symbol2;
    240                                     op = Creat_random(r1, r2);//防止后面随机产生除号,分母为0
    241                                     while (1)
    242                                     {
    243                                         if (op == 0)
    244                                             op = Creat_random(r1, r2);
    245                                         else
    246                                             break;
    247                                     }
    248                                     zhuan = Int_str(op);
    249                                     if (symbol2 == "+")
    250                                     {
    251                                         zhi = zhi + (double)op;
    252                                         formula = formula + jia + zhuan;
    253                                     }
    254                                     else if (symbol2 == "-")
    255                                     {
    256                                         zhi = zhi - (double)op;
    257                                         formula = formula + jian + zhuan;
    258                                     }
    259                                     else if (symbol2 == "*")
    260                                     {
    261                                         zhi = zhi * (double)op;
    262                                         formula = formula + cheng + zhuan;
    263                                     }
    264                                     else if (symbol2 == "/")
    265                                     {
    266                                         zhi = zhi / (double)op;
    267                                         formula = formula + chu + zhuan;
    268                                     }
    269                                     break;
    270                               }
    271 
    272                         }
    273                         break;
    274             }
    275                 
    276                 
    277         }
    278         
    279         
    280     }
    281     else if (symbol1 == "-")
    282     {
    283         zhi = (double)op1 - (double)op2;
    284         formula = zhuan1 + jian + zhuan2;
    285     }
    286     else if (symbol1 == "*")
    287     {
    288         zhi = (double)op1 * (double)op2;
    289         formula = zhuan1 + cheng + zhuan2;
    290     }
    291     else if (symbol1 == "/")
    292     {
    293         zhi = (double)op1 / (double)op2;
    294         formula = zhuan1 + chu + zhuan2;
    295     }
    296 
    297         
    298     
    299     
    300 
    301 }
    302 
    303 /*含有真分数*/
    304 void Have_fenshu(int LL, int r1, int r2, string &formula, double &zhi, int jj)
    305 {
    306     srand((int)time(0));
    307     string F1, F2, symbol, zhuan;
    308     double Z1, Z2;//
    309     int inter, type;
    310     inter = Creat_random(r1, r2);//整数
    311     zhuan = Int_str(inter);
    312     Creat_fen(r1, r2, F1, Z1);//分数1
    313     Creat_fen(r1, r2, F2, Z2);//分数2
    314     symbol = Create_oper(LL);//符号
    315     type = rand() % 3;//类型
    316 
    317     if (jj == 0)//加减没有负数
    318     {
    319         inter = Opp_zf(inter);
    320         zhuan = Int_str(inter);
    321         while (1)
    322         {
    323             if (Z1 <0)
    324                 Creat_fen(r1, r2, F1, Z1);
    325             else
    326                 break;
    327         }
    328         while (1)
    329         {
    330             if (Z2 <0)
    331                 Creat_fen(r1, r2, F2, Z2);
    332             else
    333                 break;
    334         }
    335     }
    336 
    337     switch (type)
    338     {
    339         //op1分数
    340     case(0) :
    341         formula = F1 + symbol + zhuan;
    342         if (symbol == "+")
    343             zhi = Z1 + (double)inter;
    344         else if (symbol == "-")
    345         {
    346             if (jj == 0)
    347                 break;
    348             else
    349                 zhi = Z1 - (double)inter;
    350         }
    351         else if (symbol == "*")
    352             zhi = Z1 * (double)inter;
    353         else if (symbol == "/")
    354         {
    355             if (inter != 0)
    356                 break;
    357             else
    358                 zhi = Z1 / (double)inter;
    359         }
    360         break;
    361         //op2分数
    362     case(1) :
    363         formula = zhuan + symbol + F1;
    364         if (symbol == "+")
    365             zhi = (double)inter + Z1;
    366         else if (symbol == "-")
    367             zhi = (double)inter - Z1;
    368         else if (symbol == "*")
    369             zhi = (double)inter * Z1;
    370         else if (symbol == "/")
    371         {
    372             if (Z1 != 0)
    373                 zhi = (double)inter / Z1;
    374             else
    375                 break;
    376         }
    377         break;
    378         //全分数  
    379     case(2) :
    380         formula = F1 + symbol + F2;
    381         if (symbol == "+")
    382             zhi = Z1 + Z2;
    383         else if (symbol == "-")
    384         {
    385             if ((jj == 0) && (Z1 < Z2))
    386                 break;
    387             else
    388                 zhi = Z1 - Z2;
    389         }
    390         else if (symbol == "*")
    391             zhi = Z1 * Z2;
    392         else if (symbol == "/")
    393         {
    394             if (Z1 != 0)
    395                 zhi = Z1 / Z2;
    396             else
    397                 break;
    398         }
    399         break;
    400     }
    401 
    402 }
    403 
    404 /*不含有真分数*/
    405 void Only_integer(int LL, int r1, int r2, string &formula, double &zhi,int jj,int cc)
    406 {
    407     srand((int)time(0));
    408     int op1, op2;
    409     string symbol,zhuan1,zhuan2;
    410     op1 = Creat_random(r1, r2);//整数1
    411     op2 = Creat_random(r1, r2);//整数2
    412     symbol = Create_oper(LL);//符号
    413 
    414     if (jj == 0)//加减不含负号
    415     {
    416         op1 = Opp_zf(op1);
    417         op2 = Opp_zf(op2);
    418         if ((symbol == "-") && (op1 < op2))
    419         {
    420             int temp;
    421             temp = op1;
    422             op1 = op2;
    423             op2 = temp;
    424         }
    425     }
    426 
    427     if ((cc == 0) && (symbol == "/"))//除法不含余数(去除负号计算的情况)
    428     {
    429         while (1)
    430         {
    431             op1 = Opp_zf(op1);
    432             op2 = Opp_zf(op2);
    433             if (op1 % op2 != 0)//有余数,重新生成
    434             {
    435                 op1 = Creat_random(r1, r2);
    436                 op2 = Creat_random(r1, r2);
    437             }
    438             else
    439                 break;
    440         }
    441     }
    442 
    443     zhuan1 = Int_str(op1);
    444     zhuan2 = Int_str(op2);
    445     formula = zhuan1 + symbol + zhuan2;
    446     if (symbol == "+")
    447         zhi = op1 + op2;
    448     else if (symbol == "-")
    449         zhi = op1 - op2;
    450     else if (symbol == "*")
    451         zhi = op1*op2;
    452     else if (symbol == "/")
    453         zhi = op1 / op2;
    454 }
    455 
    456 void main()
    457 {
    458     ofstream outfile("formula.txt", ios::out);
    459     if (!outfile)
    460     {
    461         cout << "open error!" << endl;
    462         exit(1);
    463     }
    464     outfile << "----------------欢迎!小学生四则运算答题系统:-D----------------" << endl;
    465 
    466     int i,j,N, R1, R2;
    467     int SF, KH, FS, Lei,JJ,CC,count=0;
    468     string question="";//生成的问题
    469     double Zhi, answer;
    470     int fenzi, fenmu;
    471     bool repeat = false;
    472     
    473     cout << "----------------欢迎!小学生四则运算答题系统:-D----------------"<<endl;
    474     /*选择题目范围和数量*/
    475     cout << "您想为孩子定制什么范围的题目呢?(可含有负数 && 上限≥下限):" << endl;
    476     cout << "下限:";
    477     cin >> R1;
    478     cout << "上限:";
    479     cin >> R2;
    480     while (1)//是否输入合法
    481     {
    482         if (R2 < R1)
    483         {
    484             cout << "输入的范围不合理,请重新输入(上限≥下限):" << endl;
    485             cout << "下限:";
    486             cin >> R1;
    487             cout << "上限:";
    488             cin >> R2;
    489         }
    490         else
    491             break;
    492     }
    493 
    494     cout << "订制多少道题呢?请输入个数:" << endl;
    495     cout << "(友情提示:您不要为孩子出太多的题目(最多1000道)!谢谢合作!)" << endl;
    496     cin >> N;
    497     while (1)//是否输入合法
    498     {
    499         if (N<=0||N>1000)
    500         {
    501             cout << "输入的题目数量不合理,请重新输入:" << endl;
    502             cin >> N;
    503         }
    504         else
    505             break;
    506     }
    507 
    508     /*选择打印方式*/
    509     cout << "您是否需要保存文档?(0、不需要 1、需要)" << endl;
    510     cin >> SF;
    511     SF=Istrue_input(SF);//是否输入合法
    512     Output(SF);
    513 
    514     cout << "*********下面请按照孩子的学习程度选择题目的难度!!*********"<<endl;
    515     /*是否含有括号*/
    516     cout << "是否练习带有括号的难度运算?(0、不需要 1、需要)";
    517     cin >> KH;
    518     KH=Istrue_input(KH);//是否输入合法
    519     if (KH == 1)//含括号
    520     {
    521         for (i = 1; i <= N; i++)
    522         {
    523             string Formula = "";
    524             double Zhi;
    525             Have_kuohao(R1, R2,Formula,Zhi);  
    526         }
    527         
    528 
    529     }
    530 
    531     //不含括号
    532     else if (KH == 0)
    533     {
    534         /*加减运算或者四则运算*/
    535         cout << "请选择:0、只进行加减运算? 1、进行四则运算?";
    536         cin >> Lei;
    537         Lei=Istrue_input(Lei);//是否输入合法
    538 
    539         cout << "加减运算中是否有负数?(0、没有 1、有)";
    540         cin >> JJ;
    541         JJ = Istrue_input(JJ);
    542     
    543         if (Lei == 1)//乘除
    544         {
    545             cout << "除法中是否出现余数?(0、没有 1、有)";
    546             cin >> CC;
    547             CC = Istrue_input(CC);
    548         }
    549 
    550         /*是否含有真分数*/
    551         cout << "题目中是否含有真分数?(0、不需要 1、需要)";
    552         cin >> FS;
    553         Istrue_input(FS);//是否输入合法
    554 
    555         cout << N << "道题目如下:" << endl;
    556         if (SF == 1)//文件输出
    557         {
    558             outfile << N << "道题目如下:" << endl;
    559         }
    560         string ku[10000] = {};
    561         
    562         for (i = 1; i <= N; i++)
    563         {
    564             if (FS == 0)//全整数
    565                 Only_integer(Lei, R1, R2, question, Zhi, JJ, CC);
    566             else if (FS == 1)//含真分数
    567                 Have_fenshu(Lei, R1, R2, question, Zhi, JJ);
    568 
    569             ku[i] = question;
    570             /*repeat = false;*/
    571             for (j = 0; j <i; j++)
    572             {
    573                 if (ku[j] == ku[i])
    574                 {
    575                     i = i - 1;
    576                     repeat = true;//重复
    577                     break;
    578                 }
    579             }
    580             /*if (repeat) ku[i+1] = "";*/
    581             if (!repeat)//不重复
    582             {
    583                 /*Is_rept(i,str);*/
    584                 cout << i << "" << question << " = " << endl;
    585                 if (SF == 1)//文件输出
    586                 {
    587                     outfile << i << "" << question << " = " << Zhi << endl;
    588                 }
    589 
    590                 if ((Zhi - (int)Zhi)< 1E-7 && (Zhi - (int)Zhi)> -(1E-7))//可认为它是整数
    591                 {
    592                     cin >> answer;
    593                 }
    594                 else
    595                 {
    596                     cout << "    分子:";
    597                     cin >> fenzi;
    598                     cout << "    分母:";
    599                     cin >> fenmu;
    600                     answer = (double)fenzi / (double)fenmu;
    601                 }
    602                 
    603                 if ((answer - Zhi) < 1E-7 && (answer - Zhi) > -(1E-7))
    604                 {
    605                     cout << "" << endl;
    606                     count++;
    607                 }
    608                 else
    609                 {
    610                     cout << "                        ×" << endl;
    611                     cout << "答案是:" << Zhi << endl;
    612                 }
    613             }
    614         }
    615         
    616         cout << "您的孩子一共答对了" << count << "道题目!! 恭喜!!" << endl;
    617         if (SF == 1)//文件输出
    618         {
    619             outfile << "您的孩子一共答对了" << count << "道题目!! 恭喜!!" << endl;
    620         }
    621         cout << "答错的" << N - count << "道题目请分析原因并改正~~  加油!!" << endl;
    622         if (SF == 1)//文件输出
    623         {
    624             outfile << "答错的" << N - count << "道题目请分析原因并改正~~  加油!!" << endl;
    625         }
    626     }
    627     outfile.close();
    628 
    629 }

    下面是代码的部分功能截图:

    测试一:

           

    选择了保存到文件中,下面我们来看文件中:文件中可以保存系统出的题目以及孩子答对的题目数!!!<( ̄ˇ ̄)/

     

    测试二:

          

    同样也可以保存到文件里:

     

    三、实验总结和反思

          通过这次实验的合作我了解到在软件工程的实际开发中团队合作的力量,从前编写代码都是一个人“孤军奋战”,现在起码有一个小伙伴能够在旁边提供一些思路和鼓励。但是我觉得能够让合作更加完美我们要做的还是尽自己最大的努力提高自己的能力,让自己不要成为团队中的短板。 第一次合作我们的用时比较长,因为花费了一个晚上来确定编程的代码规范、了解彼此的编程特点、设计函数和思路等等。希望下次能够在完成任务的基础上提高效率。

     

    最后,附上我和我的小伙伴的工作照……没有正脸。老师们不要介意啦啦啦~~~~

    小伙伴博客内容页:http://www.cnblogs.com/kongyuhang/p/5295894.html

    四、PSP和缺陷日志

     

    项目计划日志

     

    项目计划总结

    周活动总结表

    姓名:赵子茵                                              日期:2016/3/19

    任务

    日期

    听课

    编写

    程序

    阅读

    课本

    准备

    考试

     

     

    日总计

    (分钟)

    周日

     

     

     

     

     

     

     

    周一

    100

    120

    60

     

     

     

    280

    周二

     

    120

    30

     

     

     

    150

    周三

     

    300

    60

     

     

     

    360

    周四

    100

    120

    90

     

     

     

    310

    周五

     

    300

    30

     

     

     

    330

    周六

     

    720

     

     

     

     

    720

     

    阶段时间和效率

    周数:1

    总计

    200

    1680

    270

     

     

     

    2160

    平均

    30

    240

    40

     

     

     

    310

    最大

    100

    720

    90

     

     

     

    910

    最小

    100

    120

    30

     

     

     

    250

     

     

    2,时间记录日志:

    学生:赵子茵                                   日期:2016/3/19

    老师:王建民                                    课程:PSP

    日期

    开始时间

    结束时间

    中断时间

    净时间

    活动

    备注

    3/14

    14:00

    16:00

    20

    100

    上课

     

    17:00

    19:00

     

    60

    编程

     

    20:00

    21:00

     

    60

    读课本

     

    3/15

    14:00

    16:00

     

    120

    编程

     

    18:00

    19:00

     

    60

    查资料

     

    21:00

    21:30

     

    30

    读课本

     

    3/16

    10:00

    12:00

    20

    100

    查资料

     

    15:00

    20:00

     

    300

    编程

     

    20:30

    21:30

     

    60

    读课本

     

    3/17

    14:00

    16:00

    20

    100

    上课

     

    16:00

    18:00

     

    120

    编程

     

    21:00

    21:30

    30

    30

    读课本

     

    3/18

     

     

    08:00

    13:30

    15:00

    9:00

    15:00

    20:00

     

    60

    90

    300

    查资料

    休息

    编程

     

    3/18

     

     

    08:00

    13:30

    19:00

    12:00

    18:30

    21:00

     

    240

    300

    180

    编程

    编程

    编程

     

     

     

     

     

     

    3,缺陷记录日志:

    学生:赵子茵                                       日期:2016/3/19

    老师:王建民 

     

    日期

    编号

    类型

    引入阶段

    排除阶段

    修复阶段

    修复缺陷

    3/16

    1

     

    设计

    编码

    15min

     知识漏洞

    描述:设计函数的结构和变量时有知识点掌握的不牢固,比如地址传递参数的使用等等。

    3/18

     

     

     

     

    2

     

    编码

    编译

    20min

     知识漏洞

    描述:想要随机生成两个或多个不同的随机数作为运算的操作数,但是使用种子的代码有误导致每次生成的不随机或者比率不合理。

    3

     

    编码

    编译

    15min

     逻辑错误

    描述:do…while循环语句的循环条件和结束条件写错了,导致程序一直是朝着相反的方向去。

    3/19

    4

     

    编码

    编译

    30min

    知识漏洞

    描述:计算结果会出现小数因此要以double形式存放,就要将操作数的int类型进项转换,以及后面涉及到的int类型转换为string编写时都出现了知识掌握不全面的问题。

    5

     

    编码

    编译

    30min

    逻辑错误

    描述:编写查重函数时候因为内层循环和外层循环的i,j问题,导致程序不能有效的查重。

    转载于:https://www.cnblogs.com/2016helen/p/5296378.html

    展开全文
  • 二柱子“个人项目

    2016-03-06 17:22:00
    二柱子“个人项目 关于二柱子的个人项目,据说……是这么发生的…… 二柱子因为懒(,,• ₃ •,,),要给他上小学的儿子编写个能够出小学四则运算题目的程序。老师上课的时候又添加了条件: 1、打印至少30道题 2...

    ”二柱子“个人项目

    关于二柱子的个人项目,据说……是这么发生的……

    二柱子因为懒(,,• ₃ •,,),要给他上小学的儿子编写个能够出小学四则运算题目的程序。老师上课的时候又添加了条件:

    1、打印至少30道题

    2、除了整数之外,还要支持真分数的四则运算。


          老师上课的时候教导我们,写代码的时候不能拿起来就写,因为我们不能做到一气呵成的连贯式思维,要先列出程序的逻辑思路,而且语言不要过于“官方”,自己能看懂就行,越通俗越好。因此我的简单思路如下:

    1、定义两个整型操作数
    2、生成两个1-100随机数,并赋值给两个操作数
    3、循环输出加减乘除四个运算符
        用1234代替加减乘除四则运算,生成随机数代表随机的运算符(除4求余,case语句)
    4、输出
    5、真分数:分子比分母小的分数,以分数的形式显示出来
    6、30次循环

    其中涉及到“C++中生成随机数”这个知识点,我忘记了,就百度了一下,参考了CSDN个人博客上面的代码。如下:

    C/C++怎样产生随机数:这里要用到的是rand()函数, srand()函数,C语言/C++里没有自带的random(int number)函数。
    (1)  如果你只要产生随机数而不需要设定范围的话,你只要用rand()就可以了:rand()会返回一随机数值, 范围在0至RAND_MAX 间。RAND_MAX定义在stdlib.h, 其值为2147483647。

    (2)  如果你要随机生成一个在一定范围的数,你可以在宏定义中定义一个random(int number)函数,然后在main()里面直接调用random()函数。

    (3)但是上面两个例子所生成的随机数都只能是一次性的,如果你第二次运行的时候输出结果仍和第一次一样。这与srand()函数有关。srand()用来设置rand()产生随机数时的随机数种子。在调用rand()函数产生随机数前,必须先利用srand()设好随机数种子(seed), 如果未设随机数种子, rand()在调用时会自动设随机数种子为1。上面的两个例子就是因为没有设置随机数种子,每次随机数种子都自动设成相同值1 ,进而导致rand()所产生的随机数值都一样。

    srand()函数定义 : void srand (unsigned int seed); 
    通常可以利用geypid()或time(0)的返回值来当做seed;

    我的个人项目代码如下:(仅供参考,功能不全,写的还有点啰嗦)

      1 //Zhao Ziyin,20160303,Four arithmetics
      2 
      3 #include<iostream>
      4 #include<time.h>
      5 #include<string>
      6 using namespace std;
      7 #define N 30
      8 #define random(x) (rand()%x)
      9 
     10 void main()
     11 {
     12     //循环打印
     13     while (true)
     14     {
     15         cout << "-----------Choose the form of formulas 1 or 2:--------------" << endl;
     16         cout << "              Ⅰ. Integers(like  35 + 64 = )                " << endl;
     17         cout << "              Ⅱ. Proper fraction(like  5/6 × 7/10 = )     " << endl;
     18         int num, i;
     19         int sign_num;//记录运算符号代表的数字
     20         int change;//数值交换的中间值
     21         cin >> num;
     22 
     23         //选择整数运算
     24         if (num == 1)
     25         {
     26             srand((int)time(0));
     27             cout << endl;
     28             cout << "-----There are " << N << " arithmetic problems:-----" << endl;
     29 
     30             //循环打印30次
     31             for (i = 1; i <= N; i++)
     32             {
     33                 int one, two;
     34                 /*srand((int)time(0));*/
     35                 one = rand() % (99 + 1) + 1;
     36                 two = rand() % (99 + 1) + 1;
     37 
     38                 /*srand((int)time(0));*/
     39                 sign_num = (rand() % (99 + 1) + 1) % 4;
     40                 switch (sign_num)
     41                 {
     42                 case(0) :
     43                     cout << i << ".  ";
     44                     cout << one << " + " << two << " = " << endl;
     45                     break;
     46                 case(1) :
     47                     if (one < two)//减法的被减数要大于减数
     48                     {
     49                         change = one;
     50                         one = two;
     51                         two = change;
     52                     }
     53                     cout << i << ".  ";
     54                     cout << one << " - " << two << " = " << endl;
     55                     break;
     56                 case(2) :
     57                     cout << i << ".  ";
     58                     cout << one << " × " << two << " = " << endl;
     59                     break;
     60                 case(3) :
     61                     if (one < two)//除法的被除数要大于除数
     62                     {
     63                         change = one;
     64                         one = two;
     65                         two = change;
     66                     }
     67                     cout << i << ".  ";
     68                     cout << one << " ÷ " << two << " = " << endl;
     69                     break;
     70                 }
     71             }
     72         }
     73 
     74         //选择含有真分数的四则运算
     75         else if (num == 2)
     76         {
     77             string sign;
     78             srand((int)time(0));
     79             cout << endl;
     80             cout << "-----There are " << N << " proper fraction arithmetic problems:-----" << endl;
     81 
     82             for (i = 1; i <= N; i++)
     83             {
     84                 sign_num = (rand() % (99 + 1) + 1) % 4;
     85                 switch (sign_num)//利用随机数随机产生运算符
     86                 {
     87                 case(0) :
     88                     sign = '+'; break;
     89                 case(1) :
     90                     sign = '-'; break;
     91                 case(2) :
     92                     sign = '*'; break;
     93                 case(3) :
     94                     sign = '/'; break;
     95                 }
     96 
     97                 //生成四个随机数分别做两个真分数的分子和分母
     98                 int one, two, three, four;
     99                 /*srand((int)time(0));*/
    100                 one = rand() % (99 + 1) + 1;
    101                 two = rand() % (99 + 1) + 1;
    102                 three = rand() % (99 + 1) + 1;
    103                 four = rand() % (99 + 1) + 1;
    104                 if (one > two)//第一个真分数的分子要小于分母
    105                 {
    106                     change = one;
    107                     one = two;
    108                     two = change;
    109                 }
    110                 if (three > four)//第二个真分数的分子要小于分母
    111                 {
    112                     change = three;
    113                     three = four;
    114                     four = change;
    115                 }
    116 
    117                 int oper_num;
    118                 oper_num = (rand() % (99 + 1) + 1) % 3;
    119                 switch (oper_num)
    120                 {
    121                 case(0) ://真分数与真分数运算
    122                     cout << i << ".  ";
    123                     cout << one << "/" << two << " " << sign << " " << three << "/" << four << " = " << endl;
    124                     break;
    125                 case(1) ://真分数与整数运算
    126                     cout << i << ".  ";
    127                     cout << one << "/" << two << " " << sign << " " << four << " = " << endl;
    128                     break;
    129                 case(2) ://整数与真分数运算
    130                     cout << i << ".  ";
    131                     cout << one << " " << sign << " " << three << "/" << four << " = " << endl;
    132                     break;
    133                 }
    134             }
    135         }
    136         //输入的数字错误
    137         else
    138         {
    139             cout << "Choose again!" << endl;
    140         }
    141 
    142     }
    143 
    144 }

    程序的截图如下:

     

    最后!!老师说我们每次写代码之前都要估计自己完成任务的时间,然后抓紧时间去完成就会慢慢的提高效率。完成这项任务我用了上课的后20分钟(包括老师的讲解和同学的自我展示交流),还有本周日(20160306)下午三点到四点二十左右的时间。((ㆀ˘・з・˘)我知道自己写代码的速度实在是太慢了,我会以后多多锻炼,提高效率,其实主要是提高自己的智商让自己的逻辑水平更上一层楼。)

          终于完成了人生中第一篇含有代码的博客,虽然累但是还是蛮开森(* ̄ω ̄)真心~

    转载于:https://www.cnblogs.com/2016helen/p/5247978.html

    展开全文
  • 自西方文艺复兴以来,中国在自然科学方面落后西方很多,软件领域也不例外。当然现在中国的许多程序员们对此可能有许多不同的意见,有些人认为中国的程序员水平远落后...要解决这个问题,必须先知道程序员有多少种技术

    自西方文艺复兴以来,中国在自然科学方面落后西方很多,软件领域也不例外。当然现在中国的许多程序员们对此可能有许多不同的意见,有些人认为中国的程序员水平远落后于西方,有些则认为中国的程序员个人能力并不比西方的程序员差,只是整个软件产业落后而已。


    那么,到底中国的程序员水平比西方程序员水平差,还是中国有许多优秀的程序员达到或超过了西方程序员同等水平呢?要解决这个问题,必须先知道程序员有多少种技术层级,每个层级需要什么样的技术水平,然后再比较中国和西方在各个技术层级的人数,就可以知道到底有没有差距,差距有多大。
    当然,对于如何划分程序员的技术层级,不同公司或不同人会有不同的划分标准,下面的划分仅代表个人的观点,如有不当之处,还请砸板砖予以纠正。


    1层 菜鸟
    1层楼属于地板层,迈进这层楼的门槛是很低的。基本上懂计算机的基本操作,了解计算机专业的一些基础知识,掌握一门基本的编程语言如C/C++,或者Java,或者JavaScript...,均可入门迈进这层。
    在这层上,中国有着绝对的优势,除了从计算机专业毕业的众多人数外,还有大量的通信、自动化、数学等相关专业的人士进入这一行,此外还有众多的其他专业转行的人士,人数绝对比西方多出甚多。并且还有一个优势就是我们这层人员的平均智商比西方肯定高。
    没有多少人愿意一辈子做菜鸟,因为做"菜鸟"的滋味实在是不咋的,整天被老大们吆喝着去装装机器,搭建一下测试环境,或者对照着别人写好的测试用例做一些黑盒测试,好一点的可以被安排去写一点测试代码。当然如果运气""的话,碰到了国内的一些作坊式的公司,也有机会去写一些正式的代码。
    所以,菜鸟们总是在努力学习,希望爬更高的一层楼去。


    2层 大虾
    从第1层爬到第2层相对容易一些,以C/C++程序员为例,只要熟练掌握C/C++编程语言,掌握C标准库和常用的各种数据结构算法,掌握STL的基本实现和使用方法,掌握多线程编程基础知识,掌握一种开发环境,再对各种操作系统的API都去使用一下,搞网络编程的当然对socket编程要好好掌握一下,然后再学习一些面向对象的设计知识和设计模式等,学习一些测试、软件工程和质量控制的基本知识,大部分人经过23年的努力,都可以爬到第2层,晋升为"大虾"
    中国的"大虾"数量和"菜鸟"数量估计不会少多少,所以这层上仍然远领先于西方。
    大虾们通常还是有些自知之明,知道自己只能实现一些简单的功能,做不了大的东西,有时候还会遇到一些疑难问题给卡住,所以他们对那些大牛级的人物通常是非常崇拜的,国外的如Robert C. MartinLinus Torvalds,国内的如求伯君、王志东等通常是他们崇拜的对象。其中的有些人希望有一天也能达到这些大牛级人物的水平,所以他们继续往楼上爬去。


    3层 牛人
    由于"大虾"们经常被一些疑难问题给卡住,所以有了"大虾"们只好继续学习,他们需要将原来所学的知识进一步熟练掌握,比如以熟练掌握C++编程语言为例,除了学一些基础性的C++书籍如《C++ Primer》,《Effective C++》,《Think in C++》,《Exception C++》等之外,更重要的是需要了解C++编译器的原理和实现机制,了解操作系统中的内部机制如内存管理、进程和线程的管理机制,了解处理器的基础知识和代码优化的方法,此外还需要更深入地学习更多的数据结构与算法,掌握更深入的测试和调试知识以及质量管理和控制方法,对各种设计方法有更好的理解等。
    学习上面说的这些知识不是一挥而就的,不看个三五十本书并掌握它是做不到的。以数据结构算法来说,至少要看个510本这方面的著作;以软件设计来说,光懂结构化设计、面向对象设计和一些设计模式是不够的,还要了解软件架构设计、交互设计、面向方面的设计、面向使用的设计、面向数据结构算法的设计、情感化设计等,否则是很难进到这个楼层的。
    当然除了上面说的知识外,大虾们还需要去学习各种经验和技巧。当然这点难不倒他们,现在出版的书籍众多,网络上的技术文章更是不胜数,然后再去各种专业论坛里泡一泡,把这些书籍和文章中的各种经验、技能、技巧掌握下来,再去学习一些知名的开源项目如ApacheLinux操作系统的源代码实现等。此时对付一般的疑难问题通常都不在话下,菜鸟和大虾们会觉得你很"",你也就爬到了第3层,晋升为"牛人"了。
    看了上面所讲的要求,可能有些大虾要晕过去了,成为牛人要学这么多东西啊!要求是不是太高了?其实要求一点也不高,这么点东西都掌握不了的话,怎么能让别人觉得你""呢?
    需要提一下的是,进入多核时代后,从第2层爬到第3层增加了一道多核编程的门槛。当然要迈过这道门槛并不难,已经有很多前辈高人迈进了这道门槛,只要循着他们的足迹前进就可以了。想迈进这道门槛者不妨去学习一下TBB开源项目的源代码(链接:http://www.threadingbuildingblocks.org/),然后上Intel的博客(http://softwareblogs-zho.intel.com/)和多核论坛(http://forum.csdn.net/Intel/IntelMulti-core/)去看看相关文章,再买上几本相关的书籍学习一下。
    在国内, 一旦成为"牛人",通常可以到许多知名的公司里去,运气好者可以挂上一个架构师的头衔,甚至挂上一个"首席架构师"或者"首席xx学家"的头衔也不足为奇。有不少爬到这层的人就以为到了楼顶了,可以眼睛往天上看了,开始目空一切起来,以为自己什么都可以做了,什么都懂了,经常在网络上乱砸板砖是这个群体的最好写照。由此也看出,国内的牛人数量仍然众多,远多于西方的牛人数量,在这层上仍然是领先的。
    也有不少谦虚的"牛人",知道自己现在还不到半桶水阶段。他们深知爬楼的游戏就像猴子上树一样,往下看是笑脸,往上看是屁股。为了多看笑脸,少看屁股,他们并没有在此停步不前,而是继续寻找到更上一层的楼梯,以便继续往上爬。


    4层 大牛
    从第3层爬到第4层可不像上面说过的那几层一样容易,要成为大牛的话,你必须要能做牛人们做不了的事情,解决牛人们解决不了问题。比如牛人们通常都不懂写操作系统,不会写编译器,不懂得TCP/IP协议的底层实现,如果你有能力将其中的任何一个实现得象模象样的话,那么你就从牛人升级为"大牛"了。
    当然,由于各个专业领域的差别,这里举操作系统、编译器、TCP/IP协议只是作为例子,并不代表成为"大牛"一定需要掌握这些知识,以时下热门的多核编程来说,如果你能比牛人们更深入地掌握其中的各种思想原理,能更加自如的运用,并有能力去实现一个象开源项目TBB库一样的东西,也可以成为"大牛",又或者你能写出一个类似Apache一样的服务器,或者写出一个数据库,都可以成为"大牛"
    要成为"大牛"并不是一件简单的事情,需要付出比牛人们多得多的努力,一般来说,至少要看过200~400本左右的专业书籍并好好掌握它,除此之外,还得经常关注网络和期刊杂志上的各种最新信息。
    "牛人"晋升为"大牛",让"牛人们"发现有比他们更牛的人时,对"牛人"们的心灵的震撼是可想而知的。由于牛人们的数量庞大,并且牛人对大虾和菜鸟阶层有言传身教的影响,所以大牛们通常能获得非常高的社会知名度,几乎可以用"引无数菜鸟、大虾、牛人竞折腰"来形容,看看前面提过的Linus Torvalds等大牛,应该知道此言不虚。
    虽然成为"大牛"的条件看起来似乎很高似的,但是这层楼并不是很难爬的一层,只要通过一定的努力,素质不是很差,还是有许多"牛人"可以爬到这一层的。由此可知,"大牛"这个楼层的人数其实并不像想像的那么少,例如比尔·盖茨之类的人好像也是属于这一层的。
    由于"大牛"这层的人数不少,所以也很难统计除到底是中国的"大牛"数量多还是西方的大牛数量多?我估计应该是个旗鼓相当的数量,或者中国的"大牛"们会更多一些。
    看到这里,可能会有很多人会以为我在这里说瞎话,Linus Torvalds写出了著名的Linux操作系统,我国并没有人写出过类似的东西啊,我国的"大牛"怎么能和西方的比呢不知大家注意到没有,Linus Torvalds只是写出了一个"象模象样"的操作系统雏形,Linux后来真正发展成闻名全球的开源操作系统期间,完全是因为许多支持开源的商业公司如IBM等,派出了许多比Linus Torvalds更高楼层的幕后英雄在里面把它开发出来的。
    可能有些菜鸟认为Linus Torvalds是程序员中的上帝,不妨说个小故事:
    LinusRichard StallmanDon Knuth(高德纳)一同参加一个会议。
    Linus 说:"上帝说我创造了世界上最优秀的操作系统。"
    Richard Stallman自然不甘示弱地说:"上帝说我创造了世界上最好用的编译器。"
    Don Knuth一脸疑惑的说:"等等,等等,我什么时候说过这些话?"
    由此可以看出,Linus Torvalds的技术水平并不像想像中那么高,只是"牛人""大虾"觉得"大牛"比他们更牛吧了。在我国,有一些当时还处于"大虾"层的人物,也能写出介绍如何写操作系统的书,并且书写得非常出色,而且写出了一个有那么一点点象模象样的操作系统来。我想中国的"大牛"们是不会比西方差的,之所以没有人写出类似的商业产品来,完全是社会环境的原因,并不是技术能力达不到的原因。
    "大牛"们之所以成为大牛,主要的原因是因为把"牛人"给盖了下去,并不是他们自己觉得如何牛。也许有很多菜鸟、大虾甚至牛人觉得"大牛"这层已经到顶了,但大多数"大牛"估计应该是有自知之明的,他们知道自己现在还没有爬到半山腰,也就勉强能算个半桶水的水平,其中有些爬到这层没有累趴下,仍然能量充沛,并且又有志者,还是会继续往更上一层楼爬的。
    看到这里,也许有些菜鸟、大虾、牛人想不明白了,还有比"大牛"们更高的楼层,那会是什么样的楼层?下面就来看看第5层楼的奥妙。


    5层 专家
    当大牛们真正动手做一个操作系统或者类似的其他软件时,他们就会发现自己的基本功仍然有很多的不足。以内存管理为例,如果直接抄袭Linux或者其他开源操作系统的内存管理算法,会被人看不起的,如果自动动手实现一个内存管理算法,他会发现现在有关内存管理方法的算法数量众多,自己并没有全部学过和实践过,不知道到底该用那种内存管理算法。
    看到这里,可能有些人已经明白第5层楼的奥妙了,那就是需要做基础研究,当然在计算机里,最重要的就是"计算"二字,程序员要做基础研究,主要的内容就是研究非数值"计算"
    非数值计算可是一个非常庞大的领域,不仅时下热门的"多核计算""云计算"属于非数值计算范畴,就是软件需求、设计、测试、调试、评估、质量控制、软件工程等本质上也属于非数值计算的范畴,甚至芯片硬件设计也同样牵涉到非数值计算。如果你还没有真正领悟"计算"二字的含义,那么你就没有机会进到这层楼来。
    可能有人仍然没有明白为什么比尔·盖茨被划在了大牛层,没有进到这层来。虽然比尔·盖茨大学未毕业,学历不够,但是家有藏书2万余册,进入软件这个行业比绝大部分人都早,撇开他的商业才能不谈,即使只看他的技术水平,也可以算得上是学富五车,顶上几个普通的计算机软件博士之和是没有问题的,比起Linus Torvalds之类的"大牛"们应该技高一筹才对,怎么还进不了这层楼呢?
    非常遗憾的是,从Windows操作系统的实现来看,其对计算的理解是很肤浅的,如果把Google对计算方面的理解比做大学生,比尔·盖茨只能算做一个初中生,所以比尔·盖茨永远只能做个大牛人,成不了"专家"
    看到这里,也许国内的大牛们要高兴起来了,原来比尔·盖茨也只和我等在同一个层次,只要再升一层就可以超越比尔·盖茨了。不过爬到这层可没有从"牛人"升为"大牛"那么简单,人家比尔·盖茨都家有2万多册书,让你看个500~1000本以上的专业书籍并掌握好它应该要求不高吧。当然,这并不是主要的条件,更重要的是,需要到专业的学术站点去学习了,到ACMIEEEElsevierSpringerLinkSIAM等地方去下载论文应该成为你的定期功课,使用Google搜索引擎中的学术搜索更是应该成为你的日常必修课。此外,你还得经常关注是否有与你研究相关的开源项目冒出来,例如当听到有TBB这样针对多核的开源项目时,你应该第一时间到Google里输入"TBB"搜索一下,将其源代码下载下来好好研究一番,这样也许你的一只脚已经快迈进了这层楼的门槛。
    当你象我上面说的那样去做了以后,随着时间的推移,总会有某天,你发现,在很多小的领域里,你已经学不到什么新东西了,所有最新出来的研究成果你几乎都知道。此时你会发现你比在做"牛人""大牛"时的水平不知高出了多少,但是你一点也""不起来,因为你学的知识和思想都是别人提出来的,你自己并没有多少自己的知识和思想分享给别人,所以你还得继续往楼上爬才行。
    我不知道国内的"专家"到底有多少,不过有一点可以肯定的是,如果把那些专门蒙大家的"砖家"也算上的话,我们的砖家比西方的要多得多。


    6层 学者
    "专家"们想继续往上一层楼爬时,他们几乎一眼就可以看到楼梯的入口,不过令他们吃惊的是,楼梯入口处竖了一道高高的门槛,上面写着"创新"二字。不幸的是,大多数人在爬到第5层楼时已经体能消耗过度,无力翻过这道门槛。
    有少数体能充足者,可以轻易翻越这道门槛,但是并不意味着体力消耗过度者就无法翻越,因为你只是暂时还没有掌握恢复体能的方法而已,当掌握了恢复体能的方法,将体能恢复后,你就可以轻易地翻越这道门槛了。
    怎么才能将体能恢复呢?我们的老祖宗"孔子"早就教导过我们"温故而知新",在英文里,研究的单词是"research",其前缀"re""search"分别是什么意思不用我解释吧。或许有些人觉得"温故而知新""research"有些抽象,不好理解,我再给打个简单的比方,比如你在爬一座高山,爬了半天,中途体力不支,怎么恢复体力呢?自然是休息一下,重新进食一些食物,体力很快就可以得到恢复。
    由此可知,对体能消耗过度者,休息+重新进食通常是恢复体能的最佳选择。可惜的是,国内的老板们并不懂得这点,他们的公司里不仅连正常国家规定的休息时间都不给足,有些公司甚至有员工"过劳死"出现。所以国内能翻越"创新"这道门槛的人是"少之又少",和西方比起来估计是数量级的差别。
    再说说重新进食的问题,这个重新进食是有讲究的,需要进食一些基础性易消化的简单食物,不能进食山珍海味级的复杂食物,否则很难快速吸收。以查找为例,并不是去天天盯着那些复杂的查找结构和算法进行研究,你需要做的是将二分查找、哈希查找、普通二叉树查找等基础性的知识好好地复习几遍。
    以哈希查找为例,首先你需要去将各种冲突解决方法如链式结构、二次哈希等编写一遍,再试试不同种类的哈希函数,然后还需要试试在硬盘中如何实现哈希查找,并考虑数据从硬盘读到内存后,如何组织硬盘中的数据才能快速地在内存中构建出哈希表来,...,这样你可能需要将一个哈希表写上十几个不同的版本,并比较各个版本的性能、功能方面的区别和适用范围。
    总之,对任何一种简单的东西,你需要考虑各种各样的需求,以需求来驱动研究。最后你将各种最基础性的查找结构和算法都了然于胸后,或许某天你再看其他更复杂的查找算法,或者你在散步时,脑袋里灵光一现,突然间就发现了更好的方法,也就从专家晋升为"学者"了。
    学者所做的事情,通常都是在前人的基础上,进行一些小的优化和改进,例如别人发明了链式基数排序的方法,你第1个发现使用一定的方法,可以用数组替代链表进行基数排序,性能还能得到进一步提高。
    由于学者需要的只是一些小的优化改进,因此中国还是有一定数量的学者。不过和国外的数量比起来,估计少了一个数量级而已。
    也许有人会觉得现在中国许多公司申请专利的数量达到甚至超过西方发达国家了,我们的学者数量应该不会比他们少多少。因此,有必要把专利和这里说的创新的区别解释一下。
    所谓专利者,只要是以前没有的,新的东西,都可以申请专利;甚至是以前有的东西,你把他用到了一个新的领域的产品里去,也可以申请专利。比如你在房子里造一个水泥柱子,只要以前没有人就这件事申请专利,那么你就可以申请专利,并且下次你把水泥柱子挪一个位置,又可以申请一个新的专利;或者你在一个柜子上打上几个孔,下次又把孔的位置改一改,...,均可申请专利。
    这层楼里所说的创新,是指学术层面的创新,是基础研究方面的创新,和专利的概念是完全不同的,难度也是完全不同的。你即使申请了一万个象那种打孔一类的专利,加起来也够不到这层楼里的一个创新。
    当你爬到第6层楼时,你也许会有一种突破极限的快感,因为你终于把那道高高的写着"创新"二字的门槛给翻过去了,实现了"0"的突破。这时,你也许有一种"独上高楼,欲望尽天涯路"的感觉,但是很快你会发现看到的都是比较近的路,远处的路根本看不清楚。如果你还有足够的体力的话,你会想爬到更高一层的楼层去。


    7层 大师
    从第6层楼爬到第7层楼,并没有多少捷径可走,主要看你有没有足够的能量。你如果能象Hoare一样设计出一个快速排序的算法;或者象Eugene W. Myers一样设计出了一个用编辑图的最短路径模型来解决diff问题的算法;或者象M.J.D. Powell一样提出了一个能够处理非线性规划问题的SQP方法;或者你发现基于比较的排序算法,它的复杂度下界为O(NLogN);或者你发现用栈可以将递归的算法变成非递归的;或者你设计出一个红黑树或者AVL树之类的查找结构;或者你设计出一个象C++Java一样的语言;或者你发明了UML...,你就爬到了第7层,晋升为"大师"了。
    上面举的这些例子中,其中有些人站的楼层比这层高,这里只是为了形象说明而举例他们的某个成就。从上面列出的一些大师的贡献可以看出,成为大师必须要有较大的贡献。首先解决问题必须是比较重要的,其次你要比前辈们在某方面有一个较大的提高,或者你解决的是一个全新的以前没有解决过的问题;最重要的是,主要的思路和方法必须是你自己提供的,不再是在别人的思路基础上进行的优化和改进。
    看了上面这些要求,如果能量不够的话,你也许会觉得有些困难,所以不是每个人都能成为"大师"的。中国软件业里能称得上是"大师"的人,用屈指可数来形容,估计是绰绰有余。值得一提得是,国外的"大师"就象我们的"大牛"一样满天飞的多。
    我把我猜测本国有可能进到这层楼的大师列一下,以起个抛砖引玉的作用。汉王的"手写识别"技术由于是完全保密的,不知道它里面用了什么思想,原创思想占的比重有多少,因此不知道该把它划到这层楼还是更高一层楼去。原山东大学王小云教授破解DESMD5算法时,用到的方法不知道是不是完全原创的,如果是的话也可进到这层楼来。
    陈景润虽然没有彻底解决哥德巴赫猜想,但他在解决问题时所用的方法是创新的,因此也可以进到这层楼来。当然,如果能彻底解决哥德巴赫猜想,那么可以算到更高的楼层去。
    求伯君和王志东等大牛们,他们在做WPS和表格处理之类的软件时,不知是否有较大的原创算法在里面,如果有的话就算我错把他们划到了大牛层。由于所学有限,不知道国内还有那些人能够得上"大师"的级别,或许有少量做研究的教授、院士们,可以达到这个级别,有知道的不妨回个帖子晾一晾。
    鉴于"大师"这个称号的光环效应,相信有不少人梦想着成为"大师"。或许你看了前面举的一些大师的例子,你会觉得要成为大师非常困难。不妨说一下,现在有一条通往"大师"之路的捷径打开了,那就是多核计算领域,有大量的处女地等待大家去挖掘。
    以前在单核时代开发的各种算法,现在都需要改写成并行的。数据结构与算法、图像处理、数值计算、操作系统、编译器、测试调试等各个领域,都存在大量的机会,可以让你进到这层楼来,甚至有可能让你进到更高一层楼去。


    8层 科学家
    科学家向来都是一个神圣的称号,因此我把他放在了大师之上。要成为科学家,你的贡献必须超越大师,不妨随便举一些例子。
    如果你象Dijkstra一样设计了ALGOL语言,提出了程序设计的三种基本结构:顺序、选择、循环,那么你可以爬到第8层楼来。顺便说一下,即使抛开这个成果,Dijkstra凭他的PV操作和信号量概念的提出,同样可以进到这层楼。
    如果你象Don Knuth一样,是数据结构与算法这门学科的重要奠基者,你也可以进到这层楼来。当然,数据结构和算法这门学科不是某个人开创的,是许多大师和科学家集体开创的。
    如果你象巴科斯一样发明了Fortran语言,并提出了巴科斯范式,对高级程序语言的发展起了重要作用,你也可以进到这层楼来。
    或者你象Ken ThompsonDennis Ritchie一样发明了Unix操作系统和功能强大、高效、灵活、表达力强的C语言,对操作系统理论和高级编程语言均作出重大贡献,那么你也可以进到这层楼来。
    或者你有Frederick P. Brooks一样机会,可以去领导开发IBM的大型计算机System/360OS/360操作系统,并在失败后反思总结,写出《人月神话》,对软件工程作出里程碑式的贡献,你也可以进到这层来。
    或者你提出了面向对象设计的基本思想,或者你设计了互联网的TCP/IP协议,或者你象Steven A.Cook一样奠定NP完全性的理论基础,或者你象Frances Allen一样专注于并行计算来实现编译技术,在编译优化理论和技术取得基础性的成就,,均可进入这层。
    当然,如果你发明了C++语言或者Java语言,你进不到这层来,因为你用到的主要思想都是这层楼中的科学家提出的,你自己并没有没有多少原创思想在里面。
    看了上面列出的科学家的成就,你会发现,要成为科学家,通常要开创一门分支学科,或者是这个分支学科的奠基者,或者在某个分支学科里作出里程碑式的重大贡献。如果做不到这些的话,那么你能象Andrew C. Yao(姚期智)一样在对计算理论的多个方向如伪随机数生成,密码学与通信复杂度等各个方向上作出重要贡献,成为集大成者,也可以进入这层楼。
    成为科学家后,如果你有幸象Dijkstra一样,出现在一个非常重视科学的国度。当你去世时,你家乡满城的人都会自动地去为你送葬。不过如果不幸生错地方的话,能不挨板砖估计就算万幸了。
    从上面随便举的一些例子中,你可能能猜到,西方科学家的数量是非常多的,于是你会想中国应该也有少量的科学家吧?我可以很负责任地告诉你一个不幸的结果,中国本土产生的科学家的数量为0。目前在国内,软件领域的唯一的科学家就是上面提过的姚期智,还是国外请回来的,并不是本土产生的。
    可能你不同意我说的本土科学家数量为0的结论,因为你经常看到有许多公司里都有所谓首席XX科学家的头衔。我想说的是,这些所谓的首席XX科学家都是远远够不到这层楼的级别的,有些人的水平估计也就是一个牛人大牛的级别,好一点的最多也就一个学者的级别。尤其是那些被称作首席经X学家的,基本上可以把称号改为首席坑大家
    虽然我国没有人能爬到这层楼上来,但是西方国家仍然有许多人爬到了比这层更高的楼上。如果要问我们比西方落后多少?那么可以简单地回答为:落后了三层楼。下面就来看看我们做梦都没有到过的更高一层楼的秘密。


    9层 大科学家
    进入这层楼的门槛通常需要一些运气,比如某天有个苹果砸到你头上时,你碰巧发现了万有引力,那么你可以进到这层楼来。当然,万有引力几百年前就被人发现了,如果你现在到处嚷嚷着说你发现了万有引力,恐怕马上会有人打110,然后警察会把你送到不正常人类的聚集地去。因此,这里举万有引力的例子,只是说你要有类似的成就才能进到这层楼来。
    牛顿发现万有引力定律开创了经典物理运动力学这门学科,如果你也能开创一门大的学科,那么你就从科学家晋升为大科学家。比如爱因斯坦创建了相对论,从一个小职员变成了大科学家。当然大科学家可远不止这两人,数学界里比物理学界更是多得多,如欧几里得创建了平面几何,笛卡尔开创解析几何,还有欧拉、高斯、莱布尼茨等数不清的人物,跟计算相关的大科学家则有图灵等人。
    从上面列出的一些大科学家可以发现,他们的成就不仅是开创了一个大的学科,更重要的是他们的成就上升到了公理的层面。发现公理通常是需要一点运气的,如果你的运气不够好的话,另外还有一个笨办法也可以进到这层楼来,那就是成为集大成者。例如冯·诺伊曼,对数学的所有分支都非常了解,许多领域都有较大的贡献,即使撇开他对计算机的开创贡献,成为大科学家照样绰绰有余。
    当然,程序员们最关心的是自己有没有机会变成大科学家。既然计算机这门大学科的开创性成果早就被冯·诺伊曼、图灵等人摘走了,那么程序员们是不是没有机会变成大科学家了呢?我们的古人说得好:江山代有才人出,各领风骚数百年,现在在计算机这门学科下面诞生了许多非常重要的大的分支,所以你还是有足够的机会进到这层楼的。
    如果你能够彻底解决自然语言理解(机器翻译)这门学科中的核心问题, 或者你在人工智能或者机器视觉(图像识别)方面有突破性的发现,那么你同样可以轻易地晋升为大科学家。这样当某天你老了去世时,或许那天国人已经觉醒,你也能享受到如Dijkstra一样的待遇,有满城甚至全国的人去为你送葬。
    现在还剩下另外一个大家感兴趣的问题没有讨论,那就是这层中已经出现了牛顿、爱因斯坦、高斯等我们平常人都认为是顶级的科学家,是不是这层已经是楼顶了呢?相信还记得本文标题的人应该知道现在仅仅是第9层,还有第10层没有到达呢。可能不少人现在要感到困惑了,难道还有人站在比牛顿、爱因斯坦、高斯等人更高的楼层上?
    这个世界上确实存在可以用一只手的手指数得清的那么几个人,他们爬到了第10层楼上。因此,第10层楼不是虚构的,而是确实存在的。如果对此有疑惑或者认为我在胡诌一番的话,那么不妨继续往下看下去,窥一下第10层楼的秘密。


    10层 大哲
    看了这层楼的名字大哲,可能不少人已经猜到了这层楼的秘密,那就是你的成果必须要上升到哲学的高度,你才有机会能进到这层来。
    当然,上升到哲学高度只是一个必要条件,牛顿的万有引力似乎也上升到了哲学的高度,因为不知道引力到底是怎么来的,但是牛顿没有被划到这一层,因为进到这层还有另外的条件,那就是你的成果必须引起了哲学上的深度思考,并能让人们的世界观向前跨进一大步。窃以为牛顿、爱因斯坦等人的成就还达不到让人们世界观向前跨进一大步的程度。
    所以,这层楼中的人的成就对我们普通人认识世界非常重要,你可以不学相对论,但是你不可以不对这层楼的人所作出的成就不了解,否则你的世界观就是极其不完整的,会犯许多认识上的错误。不幸的是,中国的科普知识普及还不够到位,知道这层楼成就的人好像并不多,程序员中恐怕更少。下面就来看看这些用一只手的手指数得清的大哲们,到底有什么成就,能比万有引力定律和相对论还重要。
    1、希尔伯特 (18621943)
    1位进到此楼层是一位名叫希尔伯特的大数学家,如果你学过《泛函分析》,那么你在学习希尔伯特空间时可能已经对这位大数学家有所了解;如果你不是学数学出身的,又对数学史不感兴趣的话,恐怕你从来没有听说过这个名字。不过如果我问一下,知不知道二次世界大战前世界数学中心在那里,你肯定会有兴趣想知道。
    不妨说一下,二战前整个世界的数学中心就在德国的哥廷根,而我们这位大数学家希尔伯特便是它的统帅和灵魂人物。即使在二战期间,希特勒和丘吉尔也有协定,德国不轰炸牛津和剑桥,作为回报,英国不轰炸海德堡和哥廷根。
    整个二十世纪上半期的超一流数学家,几乎都出自其门下。这里不妨举几个我们熟悉的人物,例如冯·诺伊曼就曾受到他和他的学生施密特和外尔的思想影响,还到哥廷根大学任过希尔伯特的助手,钱学森的老师冯·卡门是在哥廷根取得博士学位的。顺便提一下,这位大数学家发现当时物理学上出了很多大的成果如相对论和量子力学,但是这些物理学家的数学功力明显不足,因此有一段时间带领他的学生们研究过物理学,并独立发现了广义相对论,只是不好意思和物理学家争功劳,将广义相对论的功劳全部让给了爱因斯坦。
    广义相对论相对于这位大数学家在数学上的贡献,其实是算不了什么的,只是由此可看出这位大数学家品格的高尚之处。如果再去看看牛顿之流的人物的品行,整天和莱布尼茨、虎克等人争功劳,利用自己的优势地位打压他人,甚至闹得上法庭,和这位希尔伯特先生比起来,简直就是个小丑。
    说到这里,你可能对这位大数学家希尔伯特有了一些初步映象,感觉到了他的重要性,不过他在数学上的主要成就可不是几句话说得清楚的。首先,他是一位集大成者,精通当时数学所有分支领域,在数学的各个领域都有较大的贡献,当然这些成就只能让他成为一个大科学家,不能带他进入这层楼。事实上这位希尔伯特解决的任何一个数学问题都够不到这层楼的高度,那么他怎么混到这层楼来了呢?
    话得从1900年说起,当时还很年轻的希尔伯特在当时的世界数学大会上做了一个报告,高屋建瓯地提出了著名的23个未解决的数学问题,然后整个二十世纪上半期,全世界的数学家们都在这23个问题的指导下展开研究,直到现在仍然有许多数学家受这23个问题的指导在进行研究。例如我们熟知的哥德巴赫猜想,就属于其中第8个问题素数分布的一个子问题。
    如果用高瞻远瞩来形容这位大数学家的话,那么这个世界上恐怕没有第二个人再配得上高瞻远瞩这四个字,不论是欧拉、高斯、牛顿、爱因斯坦还是被誉为最有才华的数学家伽罗华,概不例外。
    虽然那23个问题是归纳总结出来的,并不全是原创,但是其中有不少问题是可以上升到哲学的高度,引起深度思考的。可能大多数人都会觉得希尔伯特是进不到这层楼的,我们知道提出问题的人和解决问题的人是一样伟大的,何况他提出的问题是如此之多,基于这点,个人觉得应该让希尔伯特跨进这层楼的门槛里。
    看完这位希尔伯特的成就,你可能会觉得对你的世界观并没有产生任何影响。确实如此,他提出的问题不是用来影响你的,而是用来影响其他大科学家和大哲的,下面再来说说另一位对他提出的23个问题中的第2个问题有杰出贡献的大哲,你就会感觉到大哲们的成果的威力了。


    2、哥德尔 (1906~1978)
    这位大哲的名字叫哥德尔 (G?del) ”,你可能从来也没有听说过这个名字,即使你读了一个数学系的博士学位,如果你的研究方向不和这位大哲对口的话,你也不一定了解这位大哲的成就,更不知道他的成果对我们这个世界有何意义。
    简单地说,这位大哲20多岁时就证明了两个定理,一个叫做哥德尔完全性定理,另一个更重要的叫做哥德尔不完全性定理。你也许会觉得奇怪,第9层楼的成就就已经上升到了公理的高度,这种证明定理的事情不是学者和大师们做的事情吗?怎么能比第9层楼的成就还高呢?下面就来简单说一下这两个定理的含义,你就会明白这属于系统级的定理,绝不是普通的定理和公理所能比拟的。
    哥德尔完全性定理证明了逻辑学的几条公理是完备的,即任何一个由这些公理所产生出的问题,在这个公理系统内可以判定它是真的还是假的,这个结论表明了我们人类所拥有的逻辑思维能力是完备的。这条定理并不能将其带入这层楼来,带其进入这层楼的是另一条定理。
    哥德尔不完全性定理是在1930年证明的,它证明了现有数学的几条公理(ZF公理系统)是不完备的,即由这些公理产生出的问题,无法由这几条公理判断它是真的还是假的。例如希尔伯特23个问题中的第1个问题,也就是著名的康托尔连续统假设,哥德尔在1938年证明了现有公理系统中不能证明它是的,科恩(Cohen,或许也可以称得上是个大哲)在1963年证明了现有公理系统不能证明它是的。最有趣的是,即使你将某个不可判定的问题,作为一条新的公理加入进去,所组成的新的公理系统仍然是不完备的,即你无法构造一个有限条公理的系统,让这个公理系统是完备的。
    也许你仍然无法理解上面这段话的含义,不妨先说一下它对我们现实世界的影响。你可能知道1936年出现的图灵机是现代计算机的理论模型,如果没有哥德尔不完全性定理的思想,图灵机什么时候能出来是很难说的,所以这位哥德尔可以算作计算机理论的奠基者的奠基者。计算机对我们这个世界产生的影响比原子弹大了多少,我想不用我说大家也都清楚。当然,对现实世界的影响只能把哥德尔同图灵等人一样划到大科学家那一层去,能进入这层乃是另有原因。
    可能你看过《未来战士》、《黑客帝国》、《IRobot》之类的科幻电影,于是你产生制造一个和人一样或者比人更高一级的智能机器人的想法,这就引入了一个达到哲学高度的问题,人到底能不能制造出具有和人一样的思维能力的机器来?
    我只能告诉你,你的愿望是良好的,但现实是残酷的。如果你仔细思考一下不完全性定理的含义,并结合现代计算机所具有的能力分析一下,你会发现这个问题的答案暂时是否定的。如果你想造出和人一样思维能力的机器,那么你需要去好好学习这位大哲及其后续研究者的成果,并在他们的基础上有新的突破才行。
    为了说明这位大哲所研究领域的重要性,这里顺便再讨论一个我们日常争议不休的问题,那就是孔夫子的人之初、性本善以及西方认为人之初、性本恶的观点孰优孰劣的问题。可能有许多人发现西方社会现在领先我们,于是就认为性本恶是对的,性本善是错的,中国应该抛弃以前的旧思想,改用西方的思想。当然也有一些老学究们,认为中国的人文思想是领先于西方的,自然而然地认为性本善是对的,性本恶是错的。
    如果你学过大哲用过的公理化的分析方法,你就知道一套系统的多条公理间只要不会推导出矛盾的地方,即可以自圆其说,那么它可以看作是对的。这样你可以很轻易地给这个问题下一个结论,即性本善性本恶是对等的,不存在孰优孰劣的问题,更不存在谁对谁错的问题。只要你不同时将性本善性本恶放入一个系统内,那么是不会有问题的,甚至你也可以认为人之初、既无善、亦无恶,或者认为人之初、部分善、部分恶,都是可以自圆其说的,所以我们的老祖宗提出的思想并没有问题,之所以落后乃是其他原因造成的。这个问题其实在高斯所处的时代就有了结论,那时有人提出了非欧几何,即平行线公理问题,有人认为过一点可以作多条平行线,还有人认为平行线在无穷远点是相交的,和欧氏几何关于过一点只能作一条平行线的公理都是矛盾的,但是他们各自的系统内推导出的结论都是正确的。
    上面说的只是对哥德尔不完全性定理的一些粗浅解析,实际上如果深入思考一下它的含义的话,你会发现它对物理学等许多学科有重大影响,包含的道理实在是深刻,远非一般的思想所能比拟,有兴趣者不妨“google”百度一下哥德尔。或许只有我们的老祖宗老子提出的哲学思想,深度可以有得一比。
    哥德尔不完全性定理也给那些认为科学是严谨的人当头一棒,原来连数学这样的纯理论学科都是不严谨的,其他学科就更不用说了。
    至此,已经说完数学上的大哲,下面不妨再看看物理学上的大哲,物理学上好像只出过一位叫海森堡的大哲(注:由于本人对物理学不甚了解,不知道霍金够不够得上大哲的称号)。
    3、海森堡 (1901~1976)
    海森堡这个名字相信没有几个人不知道的,大部分人在学习物理时都学过他的测不准关系,也就是因为这个测不准关系,海森堡爬到了第十层楼。
    如果你看过《时间简史》和《霍金讲演录-黑洞、婴儿宇宙及其他》,你也许已经了解测不准关系的威力,所以这里不想做过多的讨论,只谈一些和本土产生的哲学思想相关的东西。
    首先看看争论了几千年,并且现在仍然有人在争论不休的宿命论问题。霍金认为,只要这个宇宙有一个初始状态,粒子的运动是按照一定物理定律进行的(比如相对论、量子力学属于这些物理定律的一部分),那么所有的粒子运动轨迹将是确定的,然后只要你承认唯物论,即精神是由物质决定的,那么宿命论就是的。当然由于测不准关系的存在,对人而言,又是无法准确预测的,因此也可以将其看作是不对的。简单的说,可以认为宿命论是的是绝对的,宿命论是不对的是相对的。
    可能上面这段话你现在仍然难以理解,或许你又觉得你的命运并不是上天注定的,而是可以通过自己的努力可以改变的。我要告诉你的是,你在想什么也是事先已注定的,包括你在预测本身也是事先注定的,因为大脑思考问题最终是基本粒子运动的结果,而这些粒子的运动必然要遵循物理定律进行,所以你会不会努力,想不想努力,包括你在想你该不该努力这件事本身也是事先注定的。顺便说一下,你现在正在看这篇文章,可能正在想这个宿命论问题值得怀疑,或者觉得写得不够好,准备砸个板砖上来;或者你在想这篇问题写得有点意思,准备看完后转给朋友看一看;又或者你看到这里,觉得很累了,准备休息一下;;这些都是上天事先就注定的。从你自身的相对角度看,因为你事先不知道后来会发生什么,也可以认为不是事先注定的,可能这句话有些不好理解,不妨好好理解前面说过的公理化思想。
    如果你没看过《霍金讲演录-黑洞、婴儿宇宙及其他》,你可能会觉得很惊讶,宿命论历来不都被认为是唯心论吗,怎么由唯物论推导出了宿命论呢?现实就是这样和你开了一个大的玩笑,不过这个玩笑也是事先注定的。如果你再仔细用公理化的方法思考一下唯物论和唯心论的矛盾性,就像前面分析性善论和性恶论一样,你会发现唯物论、唯心论不一定就是冲突的,矛盾的双方是可以统一的,只要你不要同时将唯物和唯心放进同一个系统中就行。
    当然也有聪明者仍然会怀疑宿命论问题的正确性,因为这里有一个前提条件,即宇宙要有一个初始状态。宇宙有没有初始状态,我们并不知道啊,虽然有大爆炸学说,但那也只是假说而已,并没有得到确证,有些人就认为宇宙是一直都存在的。这样看来似乎你又有合理的理由在怀疑宿命论了,不过我仍然要告诉你,你现在在怀疑宿命论仍然是事先注定的,不相信的话就来看看下面的分析。
    虽然宇宙的初始状态值得怀疑,但是这个宇宙至少已经存在了一段时间,这点我想是毋庸置疑的。我们可以在我们已知的宇宙存在的这段时间内,任意取一个时间点t0,那么在这个时间点t0上,所有的粒子都有一个运动状态。在时间点t0之后的时间里,由于粒子运动是按照物理定律进行的,因此粒子运动轨迹由时间点t0的状态决定。说白一点,如果取100年前的一个时间点作为t0,那么现在的所有粒子运动状态100年前就已经确定了,如果取10000年前一个时间点作为t0,那么最近10000年内所有粒子运动的轨迹在10000年前就确定了,当然,你可以取更早的时间,比如100亿年前的时间点。
    总之,现在你会发现宇宙有没有初始状态并不会影响宿命论的正确性,所以这个世界的一切都是注定的。只不过由于粒子间相互影响过于复杂,我们无法知道这些粒子的运动轨迹而已。当然,如果将测不准关系用上的话,那么就是这个运动轨迹对人来说是无法准确预测的,所以不妨开个玩笑:算命先生经常算得不准大概是测不准关系的缘故吧
    如果你再深入思考一下测不准关系,你会发现这是一个测量系统的问题。由于宿命论的存在,这个世界本身实际上是确定的,是的,之所以测不准乃是我们人类所具有的测量能力依赖于基本粒子造成的。所以我在前面说宿命论是不对的是相对的,它是相对于我们人类的测量能力而言的。根岑(Gentzen,曾任希尔伯特的助手)在一个更强的系统内证明了ZF系统内的问题都是可判定的,从一个侧面说明这个世界本身是确定的。(注:它和哥德尔不完全性定理并不矛盾,由于数学上的复杂性,这里就不详细解释了)
    不妨再想想我们老祖宗提出的是庄周梦见了蝴蝶?还是蝴蝶梦见了庄周?风动?幡动?还是心动?之类的问题,当然以前你都认为这是纯粹的唯心主义,甚至认为是封建糟粕,但是如果结合测不准关系的内涵,再结合前面所说的公理化分析方法进行分析,估计你现在不敢轻易地下结论。
    也许到现在你仍然无法理解为什么把大哲们划在了大科学家的上一层,你可能仍然觉得万有引力、相对论等成果是最伟大的。下面就来谈谈为什么大哲比大科学家高一层。
    如果把人类在现有能力情况下,将来所能够拥有的知识总集看成是一个集合A,人类现在已有的知识总集看成是集合B,显然,集合B只是集合A的一个子集,并且是很小的一个子集。牛顿力学、相对论这些理论只能算作集合B里的一个子集,相对于集合A,只能算作是沧海一粟。 换句话说,在人类现有能力可做的事情集合中,牛顿力学和相对论等理论给出了详细的办法让你可以做其中的一些事情,当然剩下的更多的事情是牛顿力学和相对论所无法解决的。
    哥德尔不完全性定理和测不准关系的意义在于,它指出集合A的范围,即将人类现有能力发挥到极限的情况下,那些事情是你能做到的,那些是你不能做到的。当然,它并没有给出具体的方法让你去做你能做到的事情,它只是告诉我们我们人类现在发现的能力所能达到的极限。或许将来发现人类有其他新的未发现的能力,那么这个极限就被打破了。比如将来能发现不依赖于基本粒子的其他测量方法,并且测量过程中不会改变其他粒子的状态,那么测不准关系就被打破了。
    看到这里,估计你已经发现了一些秘密,科学兜了一大圈,最终还是回到了哲学,也就是我们所认为的玄学上。同时你也会发现,我们老祖宗提出的所谓玄学,原来和现代科学是相通的,并非象某些人想像的那样全是糟粕。如果有人认为西方现代暂时领先我们,进而就认为西方古代就已经超越我们,我们老祖宗就已经落后西方,他们的思想都是糟粕的话,那么我认为他可能犯了崇洋媚外的毛病。我不得不化用一句周杰伦在春晚上的歌词送给他:你不妨抓一副我们祖传的中医良方,治一治你那崇洋媚外的内伤。顺便告诉他一下,中医用的阴阳五行理论,它的前提假设就是宿命论。
    上面说的这几位大哲的成果,可能对你的世界观会有很大的影响,于是你可能会羡慕起这些大哲们的成果来。如果你有大志的话,你会希望有朝一日你也能变成大哲,但是你发现上面的大哲是研究数学和物理学的,而你是学计算机的程序员,那么是不是没有机会变成大哲呢?
    如果你能将NP难题给彻底解决掉,意味着计算机内的计算的奥秘基本被揭开,或许你可以进到这层楼来;或者你能发现另外一套计算机可以理解的数学公理系统,并且这个公理系统是完备的,那么计算机取代人类进行思维的一个必要条件就满足了,计算机将具有真正意义上的逻辑思维和推理能力,你可以轻松地进到这层楼来。如果你发现了新的方法可以打破测不准关系,同样你也可以轻松地进到这层楼来。
    如果你能彻底揭开人类抽象思维的奥妙,并让计算机懂得了如何创建抽象,具备抽象思维能力,那么也就具备了设计能力,可以取代人类进行各种设计了,你也可以轻松地进到这层楼来。顺便说一下,如果你对软件设计有真正深刻理解的话,就会明白这不是在写科幻小说。对此感兴趣者,不妨好好地研究一下程序切片方面的技术,会让你对软件设计和测试等方面的理解有质的提高,或许有一天你能打开这扇大门。
    当然,计算机要完全取代人还有其他必要条件,后面还会提及。
    值得一提的是,虽然第10层楼是本文中所写的最高层,但是大哲们并没有觉得他们到了顶层,他们通常都还会努力寻找通往更高一层的楼梯。如果你也有成为天下第一的想法,那么你或许会想要做什么事情才能超越大哲们的成就,当然,这都得依赖于找到更高一层楼的楼梯。
    个人认为,再往上一层楼的楼梯是通往天堂的道路,也就是说第11层楼的名字叫天堂,是上帝住的地方,而不是人住的地方。如果将来某天有人能爬到天堂的话,那么他已经不是人了,而是由人变成了上帝
    你也许会怀疑这个世界到底有没有天堂上帝是否根本就不存在,我也很有同感。因此有必要再写上一段文字,讨论一下上帝的问题。如果你想了解天堂的奥妙,有没有办法让你变成上帝,不妨看看继续往下看看第11层楼的玄妙。注意我这里用的是玄妙二字,因为上帝在大部分人眼里估计都是玄之又玄的东西。


    11层 上帝
    看了上面的小标题,你可能会觉得奇怪,这篇文章不是讲程序员的十层楼吗?怎么冒出了第11层来了?
    其实这并不矛盾,程序员确实只有十层楼,因为爬到第11层时,已经变成上帝,不再是程序员了;所以超出10层楼本身并不重要,关键的问题是看你有没有能力变成上帝。
    1、谁是上帝?
    菜鸟们认为Linus Torvalds是程序员中的上帝,看完了前面各层楼的介绍,此时再看到这句话,相信你要忍不住在心里笑起来。当然,你会不会笑起来是事先注定的。Don Knuth也不是上帝,他离上帝还有三层楼的距离。即使是大哲们,他们离天堂也还差一层楼,因此这个世界上有史以来还没有任何一个人变成过上帝。
    我们感兴趣的是,将来会不会有人爬到比大哲们更高的楼层上,变成了上帝。
    要变成上帝,你得有上帝一样的能力,上帝会造人,你会吗?
    你也许会怯生生地问:我可以和爱人生小孩,算不算造人?,你可能还会理直气壮地说:现在生物学上都可以克隆人了,早就有人掌握了造人的方法
    事实上克隆人需要有人的体细胞,必须要先有人才会有体细胞。上帝造人时,这个世界上并没有人,是从无生命的物质尘土中创造出的人。因此,用最原始的方法生人和克隆人都是从有生命信息的物质中生人,不能算作造人。
    这样看来,你根本不会造人,不过我可以告诉你一个玄方,让你有机会学会如何造人。
    如果你揭开了人类情感的奥秘,让计算机也可以拥有和人类一样的情感,那么计算机将可以理解人类的需求,具有了情商,将具有完整的和人一样的能力。此时,人类进化到了机器人,科幻小说将变成现实,也就是说你已经掌握了真正的造人能力,晋升为上帝了。
    未来到底有没有人能变成上帝,人能不能进化到机器人,这是宿命论中事先注定了的。说到这里,不妨再告诉你一个打破宿命论的方法,这个方法就是你要爬到比上帝还要高的楼层。
    还有比上帝还高的楼层?,你可能会第1时间内冒出这个问题,其实我也有同样的怀疑。因此在写第12层楼前,有必要弄清楚它到底存不存在,即你可不可以骑到上帝的头上的问题。
    2. 骑到上帝的头上?
    为了解决是否可以骑到上帝的头上这个问题,不妨先假设存在比上帝高的楼层,也就是存在打破宿命论的方法。
    宿命论的本质原因是因为时间是单向运行,不可逆转造成的。如果你找到一种可以使时间逆转的方法,那么你就打破了宿命论,爬到了比上帝还高的楼层。
    看到这里,你也许会摆脱刚才陷于宿命论的困惑情绪,变得充满希望般高兴起来。不过,如果你的逻辑思维能力足够好,仔细思考一下,会发现存在一个逻辑上的悖论。
    在你找到时间逆转的方法之前,显然这个世界仍然是需要服从宿命论的,也就是说你能不能找到打破宿命论的方法是事先注定的。假设你在某个时间点t0处找到了打破宿命论的方法,你在打破宿命论后,想利用时间逆转的方法回到某个时间点t2。下面来看看你到底能不能回到时间点t2
    取位于t0t2之间的任意一个时间点t1,你在回到时间点t2之前,必须先经过时间点t1,考虑你到达t1的那一时刻,由于t1t0要早,这个时间点上你还没有找到时间逆转的方法,所以到了时间t1点后,你无法再使用时间逆转的能力回到时间点t2去,所以你永远也回不到时间点t2,由于时间点t2是任意取的,因此,你永远也无法使时间逆转,或者说你根本就没打破过宿命论,这与你在时间点t0打破了宿命论产生了矛盾。
    上面这段话看起来似乎有点像人永远迈不出一步的诡辩一样,你可能会想返回到时间点t1时,仍然可以拥有时间逆转能力啊。不过你又会发现一个新的问题,时间点t1本来是没有时间逆转能力的,现在又认为时间点t1又有时间逆转能力,那时间点t1到底是有还是没有时间逆转能力呢?或者说在时间点t0前,宿命论注定了时间点t1是没有时间逆转能力的,现在你又认为时间点t1具有时间逆转能力,那么这两个时间点t1究竟是不是同一个时间点?如果不是同一个时间点,说明你没有回到过去;如果是同一个时间点的话,岂不是自相矛盾吗?
    为了说得更形象一些,不妨假设你坐一艘超光速飞船,准备从时间点t0回到时间点t2去,假设你回到t2后,随着时间的流逝,又达到了时间点t0,如果这时你又再次坐超光速飞船返回时间点t2,那么一个值得思考的问题就出现了,你在时间点t2能不能看到上次返回时间点t2的飞船?
    如果回答不能看到飞船,那么上次返回的飞船那里去了呢?显然很难解释通。如果回答能看到飞船,那么你可以到达时间点t2后,下次时间到达t0时,你又坐飞船返回t2,这次你将可以看到上两次的两艘飞船。如果这样一直循环下去,最后你会发现你可以在时间点t2看到无穷多的飞船。用程序员的术语说,叫做程序陷入了死循环,最后系统必然会出现“Out of Memory”现象而崩溃。
    当然,你也可以认为有其他的方法,不需要飞船,可以一次性从时间点t0直接跳跃到时间点t2,并不需要经过时间点t1。下面不妨来分析一下这个方法是否可行。
    既然是直接跳跃到时间点t2,那么你必然是在一个无穷小的时间里出现在时间点t2的某个空间里,例如你要在时间点t2回到某个广场上。首先说明一下为什么是无穷小的时间里出现的,因为如果不是无穷小的时间里出现的话,那么必然可以取到一个时间点t1,会导致前面所说的时间点t1上出现悖论。
    你在广场上出现的时,广场上的空气必然要为你让开空间,而这是在无穷小的时间里完成的,那么很容易推导出你周围的空气获得的加速度和速度都是无穷大,因而它具有的动能也是无穷大,无穷大的能量和无穷大的速度意味着什么?一只鸟都可以将飞机撞下来,如果宇宙是有限大的话,它可以让这个宇宙炸毁无穷次;即使宇宙是无限大,它也足以让宇宙炸毁一次。宇宙都毁灭了,又何来的时间?还能说你回到了时间点t2吗?
    也许上面说的这些你仍然难以相信,不妨再说得更现实一些,假设你要回到100年前的一个时间点,这100年中,天上有多少流星湮灭了?有多少新星生成了?宇宙膨胀了多少?你有能力让湮灭的流星复原、生成的新星重新返回未生成前的状态,膨胀的宇宙收缩回去吗?如果这些东西的状态没有回复到100年前,又怎么能说明你回到的是100年前的时间点呢?
    根据上面的推导和分析,个人认为使时间逆转的方法是不存在的,所以第12层楼是不存在的,自然没有人可以骑到上帝的头上。
    宿命论将在有时间的时间里永远统治这个世界。
     

    展开全文
  • 自西方文艺复兴以来,中国在自然科学方面落后西方很多,软件领域也不例外。当然现在中国的许多程序员们对此可能有许多不同的意见,有些人认为中国的程序员水平远落后...要解决这个问题,必须先知道程序员有多少种技术

    自西方文艺复兴以来,中国在自然科学方面落后西方很多,软件领域也不例外。当然现在中国的许多程序员们对此可能有许多不同的意见,有些人认为中国的程序员水平远落后于西方,有些则认为中国的程序员个人能力并不比西方的程序员差,只是整个软件产业落后而已。

    那么,到底中国的程序员水平比西方程序员水平差,还是中国有许多优秀的程序员达到或超过了西方程序员同等水平呢?要解决这个问题,必须先知道程序员有多少种技术层级,每个层级需要什么样的技术水平,然后再比较中国和西方在各个技术层级的人数,就可以知道到底有没有差距,差距有多大。

    当然,对于如何划分程序员的技术层级,不同公司或不同人会有不同的划分标准,下面的划分仅代表个人的观点,如有不当之处,还请砸板砖予以纠正。

    第1层  菜鸟

    第1层楼属于地板层,迈进这层楼的门槛是很低的。基本上懂计算机的基本操作,了解计算机专业的一些基础知识,掌握一门基本的编程语言如C/C++,或者Java,或者JavaScript,...,均可入门迈进这层

    在这层上,中国有着绝对的优势,除了从计算机专业毕业的众多人数外,还有大量的通信、自动化、数学等相关专业的人士进入这一行,此外还有众多的其他专业转行的人士,人数绝对比西方多出甚多。并且还有一个优势就是我们这层人员的平均智商比西方肯定高。

    没有多少人愿意一辈子做菜鸟,因为做"菜鸟"的滋味实在是不咋的,整天被老大们吆喝着去装装机器,搭建一下测试环境,或者对照着别人写好的测试用例做一些黑盒测试,好一点的可以被安排去写一点测试代码。当然如果运气"好"的话,碰到了国内的一些作坊式的公司,也有机会去写一些正式的代码。

    所以,菜鸟们总是在努力学习,希望爬更高的一层楼去。

    第2层 大虾

    从第1层爬到第2层相对容易一些,以C/C++程序员为例,只要熟练掌握C/C++编程语言,掌握C标准库和常用的各种数据结构算法,掌握STL的基本实现和使用方法,掌握多线程编程基础知识,掌握一种开发环境,再对各种操作系统的API都去使用一下,搞网络编程的当然对socket编程要好好掌握一下,然后再学习一些面向对象的设计知识和设计模式等,学习一些测试、软件工程和质量控制的基本知识,大部分人经过2~3年的努力,都可以爬到第2层,晋升为"大虾"。

    中国的"大虾"数量和"菜鸟"数量估计不会少多少,所以这层上仍然远领先于西方。

    大虾们通常还是有些自知之明,知道自己只能实现一些简单的功能,做不了大的东西,有时候还会遇到一些疑难问题给卡住,所以他们对那些大牛级的人物通常是非常崇拜的,国外的如Robert C. Martin、Linus Torvalds,国内的如求伯君、王志东等通常是他们崇拜的对象。其中的有些人希望有一天也能达到这些大牛级人物的水平,所以他们继续往楼上爬去。

    第3层 牛人

    由于"大虾"们经常被一些疑难问题给卡住,所以有了"大虾"们只好继续学习,他们需要将原来所学的知识进一步熟练掌握,比如以熟练掌握C++编程语言为例,除了学一些基础性的C++书籍如《C++ Primer》,《Effective C++》,《Think in C++》,《Exception C++》等之外,更重要的是需要了解C++编译器的原理和实现机制,了解操作系统中的内部机制如内存管理、进程和线程的管理机制,了解处理器的基础知识和代码优化的方法,此外还需要更深入地学习更多的数据结构与算法,掌握更深入的测试和调试知识以及质量管理和控制方法,对各种设计方法有更好的理解等。

    学习上面说的这些知识不是一挥而就的,不看个三五十本书并掌握它是做不到的。以数据结构算法来说,至少要看个5~10本这方面的著作;以软件设计来说,光懂结构化设计、面向对象设计和一些设计模式是不够的,还要了解软件架构设计、交互设计、面向方面的设计、面向使用的设计、面向数据结构算法的设计、情感化设计等,否则是很难进到这个楼层的。

    当然除了上面说的知识外,大虾们还需要去学习各种经验和技巧。当然这点难不倒他们,现在出版的书籍众多,网络上的技术文章更是不胜数,然后再去各种专业论坛里泡一泡,把这些书籍和文章中的各种经验、技能、技巧掌握下来,再去学习一些知名的开源项目如Apache或Linux操作系统的源代码实现等。此时对付一般的疑难问题通常都不在话下,菜鸟和大虾们会觉得你很"牛",你也就爬到了第3层,晋升为"牛人"了。

    看了上面所讲的要求,可能有些大虾要晕过去了,成为牛人要学这么多东西啊!要求是不是太高了?其实要求一点也不高,这么点东西都掌握不了的话,怎么能让别人觉得你"牛"呢?

    需要提一下的是,进入多核时代后,从第2层爬到第3层增加了一道多核编程的门槛。当然要迈过这道门槛并不难,已经有很多前辈高人迈进了这道门槛,只要循着他们的足迹前进就可以了。想迈进这道门槛者不妨去学习一下TBB开源项目的源代码(链接:http://www.threadingbuildingblocks.org/),然后上Intel的博客(http://softwareblogs-zho.intel.com/)和多核论坛(http://forum.csdn.net/Intel/IntelMulti-core/)去看看相关文章,再买上几本相关的书籍学习一下。

    在国内, 一旦成为"牛人",通常可以到许多知名的公司里去,运气好者可以挂上一个架构师的头衔,甚至挂上一个"首席架构师"或者"首席xx学家"的头衔也不足为奇。有不少爬到这层的人就以为到了楼顶了,可以眼睛往天上看了,开始目空一切起来,以为自己什么都可以做了,什么都懂了,经常在网络上乱砸板砖是这个群体的最好写照。由此也看出,国内的牛人数量仍然众多,远多于西方的牛人数量,在这层上仍然是领先的。

    也有不少谦虚的"牛人",知道自己现在还不到半桶水阶段。他们深知爬楼的游戏就像猴子上树一样,往下看是笑脸,往上看是屁股。为了多看笑脸,少看屁股,他们并没有在此停步不前,而是继续寻找到更上一层的楼梯,以便继续往上爬。

    第4层 大牛

    从第3层爬到第4层可不像上面说过的那几层一样容易,要成为大牛的话,你必须要能做牛人们做不了的事情,解决牛人们解决不了问题。比如牛人们通常都不懂写操作系统,不会写编译器,不懂得TCP/IP协议的底层实现,如果你有能力将其中的任何一个实现得象模象样的话,那么你就从牛人升级为"大牛"了。

    当然,由于各个专业领域的差别,这里举操作系统、编译器、TCP/IP协议只是作为例子,并不代表成为"大牛"一定需要掌握这些知识,以时下热门的多核编程来说,如果你能比牛人们更深入地掌握其中的各种思想原理,能更加自如的运用,并有能力去实现一个象开源项目TBB库一样的东西,也可以成为"大牛",又或者你能写出一个类似Apache一样的服务器,或者写出一个数据库,都可以成为"大牛"。

    要成为"大牛"并不是一件简单的事情,需要付出比牛人们多得多的努力,一般来说,至少要看过200~400本左右的专业书籍并好好掌握它,除此之外,还得经常关注网络和期刊杂志上的各种最新信息。

    当"牛人"晋升为"大牛",让"牛人们"发现有比他们更牛的人时,对"牛人"们的心灵的震撼是可想而知的。由于牛人们的数量庞大,并且牛人对大虾和菜鸟阶层有言传身教的影响,所以大牛们通常能获得非常高的社会知名度,几乎可以用"引无数菜鸟、大虾、牛人竞折腰"来形容,看看前面提过的Linus Torvalds等大牛,应该知道此言不虚。

    虽然成为"大牛"的条件看起来似乎很高似的,但是这层楼并不是很难爬的一层,只要通过一定的努力,素质不是很差,还是有许多"牛人"可以爬到这一层的。由此可知,"大牛"这个楼层的人数其实并不像想像的那么少,例如比尔·盖茨之类的人好像也是属于这一层的。

    由于"大牛"这层的人数不少,所以也很难统计除到底是中国的"大牛"数量多还是西方的大牛数量多?我估计应该是个旗鼓相当的数量,或者中国的"大牛"们会更多一些。

    看到这里,可能会有很多人会以为我在这里说瞎话,Linus Torvalds写出了著名的Linux操作系统,我国并没有人写出过类似的东西啊,我国的"大牛"怎么能和西方的比呢? 不知大家注意到没有,Linus Torvalds只是写出了一个"象模象样"的操作系统雏形,Linux后来真正发展成闻名全球的开源操作系统期间,完全是因为许多支持开源的商业公司如IBM等,派出了许多比Linus Torvalds更高楼层的幕后英雄在里面把它开发出来的。

    可能有些菜鸟认为Linus Torvalds是程序员中的上帝,不妨说个小故事:

    Linus,Richard Stallman和Don Knuth(高德纳)一同参加一个会议。

    Linus 说:"上帝说我创造了世界上最优秀的操作系统。"

    Richard Stallman自然不甘示弱地说:"上帝说我创造了世界上最好用的编译器。"

    Don Knuth一脸疑惑的说:"等等,等等,我什么时候说过这些话?"

    由此可以看出,Linus Torvalds的技术水平并不像想像中那么高,只是"牛人"和"大虾"觉得"大牛"比他们更牛吧了。在我国,有一些当时还处于"大虾"层的人物,也能写出介绍如何写操作系统的书,并且书写得非常出色,而且写出了一个有那么一点点象模象样的操作系统来。我想中国的"大牛"们是不会比西方差的,之所以没有人写出类似的商业产品来,完全是社会环境的原因,并不是技术能力达不到的原因。

    "大牛"们之所以成为大牛,主要的原因是因为把"牛人"给盖了下去,并不是他们自己觉得如何牛。也许有很多菜鸟、大虾甚至牛人觉得"大牛"这层已经到顶了,但大多数"大牛"估计应该是有自知之明的,他们知道自己现在还没有爬到半山腰,也就勉强能算个半桶水的水平,其中有些爬到这层没有累趴下,仍然能量充沛,并且又有志者,还是会继续往更上一层楼爬的。

    看到这里,也许有些菜鸟、大虾、牛人想不明白了,还有比"大牛"们更高的楼层,那会是什么样的楼层?下面就来看看第5层楼的奥妙。

    第5层 专家

    当大牛们真正动手做一个操作系统或者类似的其他软件时,他们就会发现自己的基本功仍然有很多的不足。以内存管理为例,如果直接抄袭Linux或者其他开源操作系统的内存管理算法,会被人看不起的,如果自动动手实现一个内存管理算法,他会发现现在有关内存管理方法的算法数量众多,自己并没有全部学过和实践过,不知道到底该用那种内存管理算法。

    看到这里,可能有些人已经明白第5层楼的奥妙了,那就是需要做基础研究,当然在计算机里,最重要的就是"计算"二字,程序员要做基础研究,主要的内容就是研究非数值"计算"。

    非数值计算可是一个非常庞大的领域,不仅时下热门的"多核计算"与"云计算"属于非数值计算范畴,就是软件需求、设计、测试、调试、评估、质量控制、软件工程等本质上也属于非数值计算的范畴,甚至芯片硬件设计也同样牵涉到非数值计算。如果你还没有真正领悟"计算"二字的含义,那么你就没有机会进到这层楼来。

    可能有人仍然没有明白为什么比尔·盖茨被划在了大牛层,没有进到这层来。虽然比尔·盖茨大学未毕业,学历不够,但是家有藏书2万余册,进入软件这个行业比绝大部分人都早,撇开他的商业才能不谈,即使只看他的技术水平,也可以算得上是学富五车,顶上几个普通的计算机软件博士之和是没有问题的,比起Linus Torvalds之类的"大牛"们应该技高一筹才对,怎么还进不了这层楼呢?

    非常遗憾的是,从Windows操作系统的实现来看,其对计算的理解是很肤浅的,如果把Google对计算方面的理解比做大学生,比尔·盖茨只能算做一个初中生,所以比尔·盖茨永远只能做个大牛人,成不了"专家"。

    看到这里,也许国内的大牛们要高兴起来了,原来比尔·盖茨也只和我等在同一个层次,只要再升一层就可以超越比尔·盖茨了。不过爬到这层可没有从"牛人"升为"大牛"那么简单,人家比尔·盖茨都家有2万多册书,让你看个500~1000本以上的专业书籍并掌握好它应该要求不高吧。当然,这并不是主要的条件,更重要的是,需要到专业的学术站点去学习了,到ACM,IEEE,Elsevier,SpringerLink,SIAM等地方去下载论文应该成为你的定期功课,使用Google搜索引擎中的学术搜索更是应该成为你的日常必修课。此外,你还得经常关注是否有与你研究相关的开源项目冒出来,例如当听到有TBB这样针对多核的开源项目时,你应该第一时间到Google里输入"TBB"搜索一下,将其源代码下载下来好好研究一番,这样也许你的一只脚已经快迈进了这层楼的门槛。

    当你象我上面说的那样去做了以后,随着时间的推移,总会有某天,你发现,在很多小的领域里,你已经学不到什么新东西了,所有最新出来的研究成果你几乎都知道。此时你会发现你比在做"牛人"和"大牛"时的水平不知高出了多少,但是你一点也"牛"不起来,因为你学的知识和思想都是别人提出来的,你自己并没有多少自己的知识和思想分享给别人,所以你还得继续往楼上爬才行。

    我不知道国内的"专家"到底有多少,不过有一点可以肯定的是,如果把那些专门蒙大家的"砖家"也算上的话,我们的砖家比西方的要多得多。

     

    第6层 学者

    当"专家"们想继续往上一层楼爬时,他们几乎一眼就可以看到楼梯的入口,不过令他们吃惊的是,楼梯入口处竖了一道高高的门槛,上面写着"创新"二字。不幸的是,大多数人在爬到第5层楼时已经体能消耗过度,无力翻过这道门槛。

    有少数体能充足者,可以轻易翻越这道门槛,但是并不意味着体力消耗过度者就无法翻越,因为你只是暂时还没有掌握恢复体能的方法而已,当掌握了恢复体能的方法,将体能恢复后,你就可以轻易地翻越这道门槛了。

    怎么才能将体能恢复呢?我们的老祖宗"孔子"早就教导过我们"温故而知新",在英文里,研究的单词是"research",其前缀"re"和"search"分别是什么意思不用我解释吧。或许有些人觉得"温故而知新"和"research"有些抽象,不好理解,我再给打个简单的比方,比如你在爬一座高山,爬了半天,中途体力不支,怎么恢复体力呢?自然是休息一下,重新进食一些食物,体力很快就可以得到恢复。

    由此可知,对体能消耗过度者,休息+重新进食通常是恢复体能的最佳选择。可惜的是,国内的老板们并不懂得这点,他们的公司里不仅连正常国家规定的休息时间都不给足,有些公司甚至有员工"过劳死"出现。所以国内能翻越"创新"这道门槛的人是"少之又少",和西方比起来估计是数量级的差别。

    再说说重新进食的问题,这个重新进食是有讲究的,需要进食一些基础性易消化的简单食物,不能进食山珍海味级的复杂食物,否则很难快速吸收。以查找为例,并不是去天天盯着那些复杂的查找结构和算法进行研究,你需要做的是将二分查找、哈希查找、普通二叉树查找等基础性的知识好好地复习几遍。

    以哈希查找为例,首先你需要去将各种冲突解决方法如链式结构、二次哈希等编写一遍,再试试不同种类的哈希函数,然后还需要试试在硬盘中如何实现哈希查找,并考虑数据从硬盘读到内存后,如何组织硬盘中的数据才能快速地在内存中构建出哈希表来,...,这样你可能需要将一个哈希表写上十几个不同的版本,并比较各个版本的性能、功能方面的区别和适用范围。

    总之,对任何一种简单的东西,你需要考虑各种各样的需求,以需求来驱动研究。最后你将各种最基础性的查找结构和算法都了然于胸后,或许某天你再看其他更复杂的查找算法,或者你在散步时,脑袋里灵光一现,突然间就发现了更好的方法,也就从专家晋升为"学者"了。

    学者所做的事情,通常都是在前人的基础上,进行一些小的优化和改进,例如别人发明了链式基数排序的方法,你第1个发现使用一定的方法,可以用数组替代链表进行基数排序,性能还能得到进一步提高。

    由于学者需要的只是一些小的优化改进,因此中国还是有一定数量的学者。不过和国外的数量比起来,估计少了一个数量级而已。

    也许有人会觉得现在中国许多公司申请专利的数量达到甚至超过西方发达国家了,我们的学者数量应该不会比他们少多少。因此,有必要把专利和这里说的创新的区别解释一下。

    所谓专利者,只要是以前没有的,新的东西,都可以申请专利;甚至是以前有的东西,你把他用到了一个新的领域的产品里去,也可以申请专利。比如你在房子里造一个水泥柱子,只要以前没有人就这件事申请专利,那么你就可以申请专利,并且下次你把水泥柱子挪一个位置,又可以申请一个新的专利;或者你在一个柜子上打上几个孔,下次又把孔的位置改一改,...,均可申请专利。

    这层楼里所说的创新,是指学术层面的创新,是基础研究方面的创新,和专利的概念是完全不同的,难度也是完全不同的。你即使申请了一万个象那种打孔一类的专利,加起来也够不到这层楼里的一个创新。

    当你爬到第6层楼时,你也许会有一种突破极限的快感,因为你终于把那道高高的写着"创新"二字的门槛给翻过去了,实现了"0"的突破。这时,你也许有一种"独上高楼,欲望尽天涯路"的感觉,但是很快你会发现看到的都是比较近的路,远处的路根本看不清楚。如果你还有足够的体力的话,你会想爬到更高一层的楼层去。

    第7层 大师

    从第6层楼爬到第7层楼,并没有多少捷径可走,主要看你有没有足够的能量。你如果能象Hoare一样设计出一个快速排序的算法;或者象Eugene W. Myers一样设计出了一个用编辑图的最短路径模型来解决diff问题的算法;或者象M.J.D. Powell一样提出了一个能够处理非线性规划问题的SQP方法;或者你发现基于比较的排序算法,它的复杂度下界为O(NLogN);或者你发现用栈可以将递归的算法变成非递归的;或者你设计出一个红黑树或者AVL树之类的查找结构;或者你设计出一个象C++或Java一样的语言;或者你发明了UML;...,你就爬到了第7层,晋升为"大师"了。

    上面举的这些例子中,其中有些人站的楼层比这层高,这里只是为了形象说明而举例他们的某个成就。从上面列出的一些大师的贡献可以看出,成为大师必须要有较大的贡献。首先解决问题必须是比较重要的,其次你要比前辈们在某方面有一个较大的提高,或者你解决的是一个全新的以前没有解决过的问题;最重要的是,主要的思路和方法必须是你自己提供的,不再是在别人的思路基础上进行的优化和改进。

    看了上面这些要求,如果能量不够的话,你也许会觉得有些困难,所以不是每个人都能成为"大师"的。中国软件业里能称得上是"大师"的人,用屈指可数来形容,估计是绰绰有余。值得一提得是,国外的"大师"就象我们的"大牛"一样满天飞的多。

    我把我猜测本国有可能进到这层楼的大师列一下,以起个抛砖引玉的作用。汉王的"手写识别"技术由于是完全保密的,不知道它里面用了什么思想,原创思想占的比重有多少,因此不知道该把它划到这层楼还是更高一层楼去。原山东大学王小云教授破解DES和MD5算法时,用到的方法不知道是不是完全原创的,如果是的话也可进到这层楼来。

    陈景润虽然没有彻底解决哥德巴赫猜想,但他在解决问题时所用的方法是创新的,因此也可以进到这层楼来。当然,如果能彻底解决哥德巴赫猜想,那么可以算到更高的楼层去。

    求伯君和王志东等大牛们,他们在做WPS和表格处理之类的软件时,不知是否有较大的原创算法在里面,如果有的话就算我错把他们划到了大牛层。由于所学有限,不知道国内还有那些人能够得上"大师"的级别,或许有少量做研究的教授、院士们,可以达到这个级别,有知道的不妨回个帖子晾一晾。

    鉴于"大师"这个称号的光环效应,相信有不少人梦想着成为"大师"。或许你看了前面举的一些大师的例子,你会觉得要成为大师非常困难。不妨说一下,现在有一条通往"大师"之路的捷径打开了,那就是多核计算领域,有大量的处女地等待大家去挖掘。

    以前在单核时代开发的各种算法,现在都需要改写成并行的。数据结构与算法、图像处理、数值计算、操作系统、编译器、测试调试等各个领域,都存在大量的机会,可以让你进到这层楼来,甚至有可能让你进到更高一层楼去。

    第8层 科学家

    科学家向来都是一个神圣的称号,因此我把他放在了“大师”之上。要成为科学家,你的贡献必须超越大师,不妨随便举一些例子。

    如果你象Dijkstra一样设计了ALGOL语言,提出了程序设计的三种基本结构:顺序、选择、循环,那么你可以爬到第8层楼来。顺便说一下,即使抛开这个成果,Dijkstra凭他的PV操作和信号量概念的提出,同样可以进到这层楼。

    如果你象Don Knuth一样,是数据结构与算法这门学科的重要奠基者,你也可以进到这层楼来。当然,数据结构和算法这门学科不是某个人开创的,是许多大师和科学家集体开创的。

    如果你象巴科斯一样发明了Fortran语言,并提出了巴科斯范式,对高级程序语言的发展起了重要作用,你也可以进到这层楼来。

    或者你象Ken Thompson、Dennis Ritchie一样发明了Unix操作系统和功能强大、高效、灵活、表达力强的C语言,对操作系统理论和高级编程语言均作出重大贡献,那么你也可以进到这层楼来。

    或者你有Frederick P. Brooks一样机会,可以去领导开发IBM的大型计算机System/360和OS/360操作系统,并在失败后反思总结,写出《人月神话》,对软件工程作出里程碑式的贡献,你也可以进到这层来。

    或者你提出了面向对象设计的基本思想,或者你设计了互联网的TCP/IP协议,或者你象Steven A.Cook一样奠定NP完全性的理论基础,或者你象Frances Allen一样专注于并行计算来实现编译技术,在编译优化理论和技术取得基础性的成就,…,均可进入这层。

    当然,如果你发明了C++语言或者Java语言,你进不到这层来,因为你用到的主要思想都是这层楼中的科学家提出的,你自己并没有没有多少原创思想在里面。

    看了上面列出的科学家的成就,你会发现,要成为“科学家”,通常要开创一门分支学科,或者是这个分支学科的奠基者,或者在某个分支学科里作出里程碑式的重大贡献。如果做不到这些的话,那么你能象Andrew C. Yao(姚期智)一样在对计算理论的多个方向如伪随机数生成,密码学与通信复杂度等各个方向上作出重要贡献,成为集大成者,也可以进入这层楼。

    成为“科学家”后,如果你有幸象Dijkstra一样,出现在一个非常重视科学的国度。当你去世时,你家乡满城的人都会自动地去为你送葬。不过如果不幸生错地方的话,能不挨“板砖”估计就算万幸了。

    从上面随便举的一些例子中,你可能能猜到,西方科学家的数量是非常多的,于是你会想中国应该也有少量的科学家吧?我可以很负责任地告诉你一个不幸的结果,中国本土产生的科学家的数量为0。目前在国内,软件领域的唯一的科学家就是上面提过的姚期智,还是国外请回来的,并不是本土产生的。

    可能你不同意我说的本土科学家数量为0的结论,因为你经常看到有许多公司里都有所谓“首席XX科学家”的头衔。我想说的是,这些所谓的“首席XX科学家”都是远远够不到这层楼的级别的,有些人的水平估计也就是一个“牛人”或“大牛”的级别,好一点的最多也就一个“学者”的级别。尤其是那些被称作“首席经X学家”的,基本上可以把称号改为“首席坑大家”。

    虽然我国没有人能爬到这层楼上来,但是西方国家仍然有许多人爬到了比这层更高的楼上。如果要问我们比西方落后多少?那么可以简单地回答为:“落后了三层楼”。下面就来看看我们做梦都没有到过的更高一层楼的秘密。

    第9层 大科学家

    进入这层楼的门槛通常需要一些运气,比如某天有个苹果砸到你头上时,你碰巧发现了万有引力,那么你可以进到这层楼来。当然,万有引力几百年前就被人发现了,如果你现在到处嚷嚷着说你发现了万有引力,恐怕马上会有人打110,然后警察会把你送到不正常人类的聚集地去。因此,这里举万有引力的例子,只是说你要有类似的成就才能进到这层楼来。

    牛顿发现万有引力定律开创了经典物理运动力学这门学科,如果你也能开创一门大的学科,那么你就从科学家晋升为“大科学家”。比如爱因斯坦创建了相对论,从一个小职员变成了大科学家。当然大科学家可远不止这两人,数学界里比物理学界更是多得多,如欧几里得创建了平面几何,笛卡尔开创解析几何,还有欧拉、高斯、莱布尼茨等数不清的人物,跟计算相关的大科学家则有图灵等人。

    从上面列出的一些大科学家可以发现,他们的成就不仅是开创了一个大的学科,更重要的是他们的成就上升到了“公理”的层面。发现公理通常是需要一点运气的,如果你的运气不够好的话,另外还有一个笨办法也可以进到这层楼来,那就是成为集大成者。例如冯·诺伊曼,对数学的所有分支都非常了解,许多领域都有较大的贡献,即使撇开他对计算机的开创贡献,成为大科学家照样绰绰有余。

    当然,程序员们最关心的是自己有没有机会变成大科学家。既然计算机这门大学科的开创性成果早就被冯·诺伊曼、图灵等人摘走了,那么程序员们是不是没有机会变成大科学家了呢?我们的古人说得好:“江山代有才人出,各领风骚数百年”,现在在计算机这门学科下面诞生了许多非常重要的大的分支,所以你还是有足够的机会进到这层楼的。

    如果你能够彻底解决自然语言理解(机器翻译)这门学科中的核心问题, 或者你在人工智能或者机器视觉(图像识别)方面有突破性的发现,那么你同样可以轻易地晋升为“大科学家”。这样当某天你老了去世时,或许那天国人已经觉醒,你也能享受到如Dijkstra一样的待遇,有满城甚至全国的人去为你送葬。

    现在还剩下另外一个大家感兴趣的问题没有讨论,那就是这层中已经出现了牛顿、爱因斯坦、高斯等我们平常人都认为是顶级的科学家,是不是这层已经是楼顶了呢?相信还记得本文标题的人应该知道现在仅仅是第9层,还有第10层没有到达呢。可能不少人现在要感到困惑了,难道还有人站在比牛顿、爱因斯坦、高斯等人更高的楼层上?

    这个世界上确实存在可以用一只手的手指数得清的那么几个人,他们爬到了第10层楼上。因此,第10层楼不是虚构的,而是确实存在的。如果对此有疑惑或者认为我在胡诌一番的话,那么不妨继续往下看下去,窥一下第10层楼的秘密。

     

     

    第10层 大哲

    看了这层楼的名字“大哲”,可能不少人已经猜到了这层楼的秘密,那就是你的成果必须要上升到哲学的高度,你才有机会能进到这层来。

    当然,上升到哲学高度只是一个必要条件,牛顿的万有引力似乎也上升到了哲学的高度,因为不知道引力到底是怎么来的,但是牛顿没有被划到这一层,因为进到这层还有另外的条件,那就是你的成果必须引起了哲学上的深度思考,并能让人们的世界观向前跨进一大步。窃以为牛顿、爱因斯坦等人的成就还达不到让人们世界观向前跨进一大步的程度。

    所以,这层楼中的人的成就对我们普通人认识世界非常重要,你可以不学相对论,但是你不可以不对这层楼的人所作出的成就不了解,否则你的世界观就是极其不完整的,会犯许多认识上的错误。不幸的是,中国的科普知识普及还不够到位,知道这层楼成就的人好像并不多,程序员中恐怕更少。下面就来看看这些用一只手的手指数得清的大哲们,到底有什么成就,能比万有引力定律和相对论还重要。

    1、希尔伯特 (1862~1943)

    第1位进到此楼层是一位名叫“希尔伯特”的大数学家,如果你学过《泛函分析》,那么你在学习希尔伯特空间时可能已经对这位大数学家有所了解;如果你不是学数学出身的,又对数学史不感兴趣的话,恐怕你从来没有听说过这个名字。不过如果我问一下,知不知道二次世界大战前世界数学中心在那里,你肯定会有兴趣想知道。

    不妨说一下,二战前整个世界的数学中心就在德国的哥廷根,而我们这位大数学家希尔伯特便是它的统帅和灵魂人物。即使在二战期间,希特勒和丘吉尔也有协定,德国不轰炸牛津和剑桥,作为回报,英国不轰炸海德堡和哥廷根。

    整个二十世纪上半期的超一流数学家,几乎都出自其门下。这里不妨举几个我们熟悉的人物,例如冯·诺伊曼就曾受到他和他的学生施密特和外尔的思想影响,还到哥廷根大学任过希尔伯特的助手,钱学森的老师冯·卡门是在哥廷根取得博士学位的。顺便提一下,这位大数学家发现当时物理学上出了很多大的成果如相对论和量子力学,但是这些物理学家的数学功力明显不足,因此有一段时间带领他的学生们研究过物理学,并独立发现了广义相对论,只是不好意思和物理学家争功劳,将广义相对论的功劳全部让给了爱因斯坦。

    广义相对论相对于这位大数学家在数学上的贡献,其实是算不了什么的,只是由此可看出这位大数学家品格的高尚之处。如果再去看看牛顿之流的人物的品行,整天和莱布尼茨、虎克等人争功劳,利用自己的优势地位打压他人,甚至闹得上法庭,和这位希尔伯特先生比起来,简直就是个小丑。

    说到这里,你可能对这位大数学家“希尔伯特”有了一些初步映象,感觉到了他的重要性,不过他在数学上的主要成就可不是几句话说得清楚的。首先,他是一位集大成者,精通当时数学所有分支领域,在数学的各个领域都有较大的贡献,当然这些成就只能让他成为一个大科学家,不能带他进入这层楼。事实上这位“希尔伯特”解决的任何一个数学问题都够不到这层楼的高度,那么他怎么混到这层楼来了呢?

    话得从1900年说起,当时还很年轻的希尔伯特在当时的世界数学大会上做了一个报告,高屋建瓯地提出了著名的23个未解决的数学问题,然后整个二十世纪上半期,全世界的数学家们都在这23个问题的指导下展开研究,直到现在仍然有许多数学家受这23个问题的指导在进行研究。例如我们熟知的哥德巴赫猜想,就属于其中第8个问题素数分布的一个子问题。

    如果用“高瞻远瞩”来形容这位大数学家的话,那么这个世界上恐怕没有第二个人再配得上“高瞻远瞩”这四个字,不论是欧拉、高斯、牛顿、爱因斯坦还是被誉为最有才华的数学家伽罗华,概不例外。

    虽然那23个问题是归纳总结出来的,并不全是原创,但是其中有不少问题是可以上升到哲学的高度,引起深度思考的。可能大多数人都会觉得希尔伯特是进不到这层楼的,我们知道提出问题的人和解决问题的人是一样伟大的,何况他提出的问题是如此之多,基于这点,个人觉得应该让希尔伯特跨进这层楼的门槛里。

    看完这位希尔伯特的成就,你可能会觉得对你的世界观并没有产生任何影响。确实如此,他提出的问题不是用来影响你的,而是用来影响其他大科学家和大哲的,下面再来说说另一位对他提出的23个问题中的第2个问题有杰出贡献的大哲,你就会感觉到大哲们的成果的威力了。

    2、哥德尔 (1906~1978)

    这位大哲的名字叫“哥德尔 (G?del) ”,你可能从来也没有听说过这个名字,即使你读了一个数学系的博士学位,如果你的研究方向不和这位大哲对口的话,你也不一定了解这位大哲的成就,更不知道他的成果对我们这个世界有何意义。

    简单地说,这位大哲20多岁时就证明了两个定理,一个叫做“哥德尔完全性定理”,另一个更重要的叫做“哥德尔不完全性定理”。你也许会觉得奇怪,第9层楼的成就就已经上升到了公理的高度,这种证明定理的事情不是学者和大师们做的事情吗?怎么能比第9层楼的成就还高呢?下面就来简单说一下这两个定理的含义,你就会明白这属于系统级的定理,绝不是普通的定理和公理所能比拟的。

    “哥德尔完全性定理”证明了逻辑学的几条公理是完备的,即任何一个由这些公理所产生出的问题,在这个公理系统内可以判定它是真的还是假的,这个结论表明了我们人类所拥有的逻辑思维能力是完备的。这条定理并不能将其带入这层楼来,带其进入这层楼的是另一条定理。

    “哥德尔不完全性定理”是在1930年证明的,它证明了现有数学的几条公理(ZF公理系统)是不完备的,即由这些公理产生出的问题,无法由这几条公理判断它是真的还是假的。例如希尔伯特23个问题中的第1个问题,也就是著名的康托尔连续统假设,哥德尔在1938年证明了现有公理系统中不能证明它是“假”的,科恩(Cohen,或许也可以称得上是“半”个大哲)在1963年证明了现有公理系统不能证明它是“真”的。最有趣的是,即使你将某个不可判定的问题,作为一条新的公理加入进去,所组成的新的公理系统仍然是不完备的,即你无法构造一个有限条公理的系统,让这个公理系统是完备的。

    也许你仍然无法理解上面这段话的含义,不妨先说一下它对我们现实世界的影响。你可能知道1936年出现的图灵机是现代计算机的理论模型,如果没有哥德尔不完全性定理的思想,图灵机什么时候能出来是很难说的,所以这位哥德尔可以算作计算机理论的奠基者的奠基者。计算机对我们这个世界产生的影响比原子弹大了多少,我想不用我说大家也都清楚。当然,对现实世界的影响只能把哥德尔同图灵等人一样划到大科学家那一层去,能进入这层乃是另有原因。

    可能你看过《未来战士》、《黑客帝国》、《I,Robot》之类的科幻电影,于是你产生制造一个和人一样或者比人更高一级的智能机器人的想法,这就引入了一个达到哲学高度的问题,“人到底能不能制造出具有和人一样的思维能力的机器来?”。

    我只能告诉你,“你的愿望是良好的,但现实是残酷的”。如果你仔细思考一下不完全性定理的含义,并结合现代计算机所具有的能力分析一下,你会发现这个问题的答案暂时是否定的。如果你想造出和人一样思维能力的机器,那么你需要去好好学习这位大哲及其后续研究者的成果,并在他们的基础上有新的突破才行。

    为了说明这位大哲所研究领域的重要性,这里顺便再讨论一个我们日常争议不休的问题,那就是孔夫子的“人之初、性本善”以及西方认为“人之初、性本恶”的观点孰优孰劣的问题。可能有许多人发现西方社会现在领先我们,于是就认为“性本恶”是对的,“性本善”是错的,中国应该抛弃以前的旧思想,改用西方的思想。当然也有一些老学究们,认为中国的人文思想是领先于西方的,自然而然地认为“性本善”是对的,“性本恶”是错的。

    如果你学过大哲用过的公理化的分析方法,你就知道一套系统的多条公理间只要不会推导出矛盾的地方,即可以自圆其说,那么它可以看作是对的。这样你可以很轻易地给这个问题下一个结论,即“性本善”和“性本恶”是对等的,不存在孰优孰劣的问题,更不存在谁对谁错的问题。只要你不同时将“性本善”和“性本恶”放入一个系统内,那么是不会有问题的,甚至你也可以认为“人之初、既无善、亦无恶”,或者认为“人之初、部分善、部分恶”,都是可以自圆其说的,所以我们的老祖宗提出的思想并没有问题,之所以落后乃是其他原因造成的。这个问题其实在高斯所处的时代就有了结论,那时有人提出了非欧几何,即平行线公理问题,有人认为过一点可以作多条平行线,还有人认为平行线在无穷远点是相交的,和欧氏几何关于过一点只能作一条平行线的公理都是矛盾的,但是他们各自的系统内推导出的结论都是正确的。

    上面说的只是对哥德尔不完全性定理的一些粗浅解析,实际上如果深入思考一下它的含义的话,你会发现它对物理学等许多学科有重大影响,包含的道理实在是深刻,远非一般的思想所能比拟,有兴趣者不妨“google”或“百度”一下“哥德尔”。或许只有我们的老祖宗“老子”提出的哲学思想,深度可以有得一比。

    哥德尔不完全性定理也给那些认为科学是严谨的人当头一棒,原来连数学这样的纯理论学科都是不严谨的,其他学科就更不用说了。

    至此,已经说完数学上的大哲,下面不妨再看看物理学上的大哲,物理学上好像只出过一位叫“海森堡”的大哲(注:由于本人对物理学不甚了解,不知道“霍金”够不够得上大哲的称号)。

    3、海森堡 (1901~1976)

    海森堡这个名字相信没有几个人不知道的,大部分人在学习物理时都学过他的“测不准关系”,也就是因为这个“测不准关系”,海森堡爬到了第十层楼。

    如果你看过《时间简史》和《霍金讲演录-黑洞、婴儿宇宙及其他》,你也许已经了解测不准关系的威力,所以这里不想做过多的讨论,只谈一些和本土产生的哲学思想相关的东西。

    首先看看争论了几千年,并且现在仍然有人在争论不休的“宿命论”问题。霍金认为,只要这个宇宙有一个初始状态,粒子的运动是按照一定物理定律进行的(比如相对论、量子力学属于这些物理定律的一部分),那么所有的粒子运动轨迹将是确定的,然后只要你承认唯物论,即精神是由物质决定的,那么宿命论就是“对”的。当然由于测不准关系的存在,对人而言,又是无法准确预测的,因此也可以将其看作是“不对”的。简单的说,可以认为宿命论是“对”的是绝对的,宿命论是“不对”的是相对的。

    可能上面这段话你现在仍然难以理解,或许你又觉得你的命运并不是上天注定的,而是可以通过自己的努力可以改变的。我要告诉你的是,你在想什么也是事先已注定的,包括你在预测本身也是事先注定的,因为大脑思考问题最终是基本粒子运动的结果,而这些粒子的运动必然要遵循物理定律进行,所以你会不会努力,想不想努力,包括你在想你该不该努力这件事本身也是事先注定的。顺便说一下,你现在正在看这篇文章,可能正在想这个宿命论问题值得怀疑,或者觉得写得不够好,准备砸个板砖上来;或者你在想这篇问题写得有点意思,准备看完后转给朋友看一看;又或者你看到这里,觉得很累了,准备休息一下;…;这些都是上天事先就注定的。从你自身的相对角度看,因为你事先不知道后来会发生什么,也可以认为不是事先注定的,可能这句话有些不好理解,不妨好好理解前面说过的公理化思想。

    如果你没看过《霍金讲演录-黑洞、婴儿宇宙及其他》,你可能会觉得很惊讶,宿命论历来不都被认为是唯心论吗,怎么由唯物论推导出了宿命论呢?现实就是这样和你开了一个大的玩笑,不过这个玩笑也是事先注定的。如果你再仔细用公理化的方法思考一下唯物论和唯心论的矛盾性,就像前面分析性善论和性恶论一样,你会发现唯物论、唯心论不一定就是冲突的,矛盾的双方是可以统一的,只要你不要同时将唯物和唯心放进同一个系统中就行。

    当然也有聪明者仍然会怀疑宿命论问题的正确性,因为这里有一个前提条件,即宇宙要有一个初始状态。宇宙有没有初始状态,我们并不知道啊,虽然有大爆炸学说,但那也只是假说而已,并没有得到确证,有些人就认为宇宙是一直都存在的。这样看来似乎你又有合理的理由在怀疑宿命论了,不过我仍然要告诉你,你现在在怀疑宿命论仍然是事先注定的,不相信的话就来看看下面的分析。

    虽然宇宙的初始状态值得怀疑,但是这个宇宙至少已经存在了一段时间,这点我想是毋庸置疑的。我们可以在我们已知的宇宙存在的这段时间内,任意取一个时间点t0,那么在这个时间点t0上,所有的粒子都有一个运动状态。在时间点t0之后的时间里,由于粒子运动是按照物理定律进行的,因此粒子运动轨迹由时间点t0的状态决定。说白一点,如果取100年前的一个时间点作为t0,那么现在的所有粒子运动状态100年前就已经确定了,如果取10000年前一个时间点作为t0,那么最近10000年内所有粒子运动的轨迹在10000年前就确定了,当然,你可以取更早的时间,比如100亿年前的时间点。

    总之,现在你会发现宇宙有没有初始状态并不会影响宿命论的正确性,所以这个世界的一切都是注定的。只不过由于粒子间相互影响过于复杂,我们无法知道这些粒子的运动轨迹而已。当然,如果将测不准关系用上的话,那么就是这个运动轨迹对人来说是无法准确预测的,所以不妨开个玩笑:“算命先生经常算得不准大概是测不准关系的缘故吧”。

    如果你再深入思考一下测不准关系,你会发现这是一个测量系统的问题。由于宿命论的存在,这个世界本身实际上是确定的,是“准“的,之所以测不准乃是我们人类所具有的测量能力依赖于基本粒子造成的。所以我在前面说宿命论是“不对”的是相对的,它是相对于我们人类的测量能力而言的。根岑(Gentzen,曾任希尔伯特的助手)在一个更强的系统内证明了ZF系统内的问题都是可判定的,从一个侧面说明这个世界本身是确定的。(注:它和哥德尔不完全性定理并不矛盾,由于数学上的复杂性,这里就不详细解释了)

    不妨再想想我们老祖宗提出的“是庄周梦见了蝴蝶?还是蝴蝶梦见了庄周?”,“风动?幡动?还是心动?”之类的问题,当然以前你都认为这是纯粹的唯心主义,甚至认为是封建糟粕,但是如果结合测不准关系的内涵,再结合前面所说的公理化分析方法进行分析,估计你现在不敢轻易地下结论。

    也许到现在你仍然无法理解为什么把大哲们划在了大科学家的上一层,你可能仍然觉得万有引力、相对论等成果是最伟大的。下面就来谈谈为什么大哲比大科学家高一层。

    如果把人类在现有能力情况下,将来所能够拥有的知识总集看成是一个集合A,人类现在已有的知识总集看成是集合B,显然,集合B只是集合A的一个子集,并且是很小的一个子集。牛顿力学、相对论这些理论只能算作集合B里的一个子集,相对于集合A,只能算作是沧海一粟。 换句话说,在人类现有能力可做的事情集合中,牛顿力学和相对论等理论给出了详细的办法让你可以做其中的一些事情,当然剩下的更多的事情是牛顿力学和相对论所无法解决的。

    哥德尔不完全性定理和测不准关系的意义在于,它指出集合A的范围,即将人类现有能力发挥到极限的情况下,那些事情是你能做到的,那些是你不能做到的。当然,它并没有给出具体的方法让你去做你能做到的事情,它只是告诉我们我们人类现在发现的能力所能达到的极限。或许将来发现人类有其他新的未发现的能力,那么这个极限就被打破了。比如将来能发现不依赖于基本粒子的其他测量方法,并且测量过程中不会改变其他粒子的状态,那么测不准关系就被打破了。

    看到这里,估计你已经发现了一些秘密,科学兜了一大圈,最终还是回到了哲学,也就是我们所认为的玄学上。同时你也会发现,我们老祖宗提出的所谓玄学,原来和现代科学是相通的,并非象某些人想像的那样全是糟粕。如果有人认为西方现代暂时领先我们,进而就认为西方古代就已经超越我们,我们老祖宗就已经落后西方,他们的思想都是糟粕的话,那么我认为他可能犯了崇洋媚外的毛病。我不得不化用一句周杰伦在春晚上的歌词送给他:“你不妨抓一副我们祖传的中医良方,治一治你那崇洋媚外的内伤”。顺便告诉他一下,中医用的阴阳五行理论,它的前提假设就是宿命论。

    上面说的这几位大哲的成果,可能对你的世界观会有很大的影响,于是你可能会羡慕起这些大哲们的成果来。如果你有大志的话,你会希望有朝一日你也能变成大哲,但是你发现上面的大哲是研究数学和物理学的,而你是学计算机的程序员,那么是不是没有机会变成大哲呢?

    如果你能将NP难题给彻底解决掉,意味着计算机内的计算的奥秘基本被揭开,或许你可以进到这层楼来;或者你能发现另外一套计算机可以理解的数学公理系统,并且这个公理系统是完备的,那么计算机取代人类进行思维的一个必要条件就满足了,计算机将具有真正意义上的“逻辑思维和推理能力”,你可以轻松地进到这层楼来。如果你发现了新的方法可以打破测不准关系,同样你也可以轻松地进到这层楼来。

    如果你能彻底揭开人类抽象思维的奥妙,并让计算机懂得了如何创建抽象,具备抽象思维能力,那么也就具备了“设计能力”,可以取代人类进行各种设计了,你也可以轻松地进到这层楼来。顺便说一下,如果你对软件设计有真正深刻理解的话,就会明白这不是在写科幻小说。对此感兴趣者,不妨好好地研究一下程序切片方面的技术,会让你对软件设计和测试等方面的理解有质的提高,或许有一天你能打开这扇大门。

    当然,计算机要完全取代人还有其他必要条件,后面还会提及。

    值得一提的是,虽然第10层楼是本文中所写的最高层,但是大哲们并没有觉得他们到了顶层,他们通常都还会努力寻找通往更高一层的楼梯。如果你也有成为天下第一的想法,那么你或许会想要做什么事情才能超越大哲们的成就,当然,这都得依赖于找到更高一层楼的楼梯。

    个人认为,再往上一层楼的楼梯是通往天堂的道路,也就是说第11层楼的名字叫“天堂”,是“上帝”住的地方,而不是人住的地方。如果将来某天有人能爬到天堂的话,那么他已经不是人了,而是由人变成了“上帝”。

    你也许会怀疑这个世界到底有没有“天堂”,“上帝”是否根本就不存在,我也很有同感。因此有必要再写上一段文字,讨论一下“上帝”的问题。如果你想了解天堂的奥妙,有没有办法让你变成“上帝”,不妨看看继续往下看看第11层楼的玄妙。注意我这里用的是“玄妙”二字,因为上帝在大部分人眼里估计都是“玄之又玄”的东西。

    第11层 上帝

    看了上面的小标题,你可能会觉得奇怪,这篇文章不是讲“程序员的十层楼”吗?怎么冒出了第11层来了?

    其实这并不矛盾,程序员确实只有十层楼,因为爬到第11层时,已经变成上帝,不再是程序员了;所以超出10层楼本身并不重要,关键的问题是看你有没有能力变成上帝。

    1、谁是上帝?

    菜鸟们认为Linus Torvalds是程序员中的上帝,看完了前面各层楼的介绍,此时再看到这句话,相信你要忍不住在心里笑起来。当然,你会不会笑起来是事先注定的。Don Knuth也不是上帝,他离上帝还有三层楼的距离。即使是大哲们,他们离天堂也还差一层楼,因此这个世界上有史以来还没有任何一个人变成过上帝。

    我们感兴趣的是,将来会不会有人爬到比大哲们更高的楼层上,变成了上帝。

    要变成上帝,你得有上帝一样的能力,上帝会造人,你会吗?

    你也许会怯生生地问:“我可以和爱人生小孩,算不算造人?”,你可能还会理直气壮地说:“现在生物学上都可以克隆人了,早就有人掌握了造人的方法”。

    事实上克隆人需要有人的体细胞,必须要先有人才会有体细胞。上帝造人时,这个世界上并没有人,是从无生命的物质“尘土”中创造出的人。因此,用最原始的方法生人和克隆人都是从有生命信息的物质中生人,不能算作造人。

    这样看来,你根本不会造人,不过我可以告诉你一个“玄方”,让你有机会学会如何造人。

    如果你揭开了人类情感的奥秘,让计算机也可以拥有和人类一样的情感,那么计算机将可以理解人类的需求,具有了“情商”,将具有完整的和人一样的能力。此时,人类进化到了机器人,科幻小说将变成现实,也就是说你已经掌握了真正的造人能力,晋升为“上帝”了。

    未来到底有没有人能变成“上帝”,人能不能进化到机器人,这是宿命论中事先注定了的。说到这里,不妨再告诉你一个打破宿命论的方法,这个方法就是你要爬到比上帝还要高的楼层。

    “还有比上帝还高的楼层?”,你可能会第1时间内冒出这个问题,其实我也有同样的怀疑。因此在写第12层楼前,有必要弄清楚它到底存不存在,即你可不可以骑到上帝的头上的问题。

    2. 骑到上帝的头上?

    为了解决是否可以骑到上帝的头上这个问题,不妨先假设存在比上帝高的楼层,也就是存在打破宿命论的方法。

    宿命论的本质原因是因为时间是单向运行,不可逆转造成的。如果你找到一种可以使时间逆转的方法,那么你就打破了宿命论,爬到了比上帝还高的楼层。

    看到这里,你也许会摆脱刚才陷于宿命论的困惑情绪,变得充满希望般高兴起来。不过,如果你的逻辑思维能力足够好,仔细思考一下,会发现存在一个逻辑上的悖论。

    在你找到时间逆转的方法之前,显然这个世界仍然是需要服从宿命论的,也就是说你能不能找到打破宿命论的方法是事先注定的。假设你在某个时间点t0处找到了打破宿命论的方法,你在打破宿命论后,想利用时间逆转的方法回到某个时间点t2。下面来看看你到底能不能回到时间点t2。

    取位于t0和t2之间的任意一个时间点t1,你在回到时间点t2之前,必须先经过时间点t1,考虑你到达t1的那一时刻,由于t1比t0要早,这个时间点上你还没有找到时间逆转的方法,所以到了时间t1点后,你无法再使用时间逆转的能力回到时间点t2去,所以你永远也回不到时间点t2,由于时间点t2是任意取的,因此,你永远也无法使时间逆转,或者说你根本就没打破过宿命论,这与你在时间点t0打破了宿命论产生了矛盾。

    上面这段话看起来似乎有点像“人永远迈不出一步”的诡辩一样,你可能会想返回到时间点t1时,仍然可以拥有时间逆转能力啊。不过你又会发现一个新的问题,时间点t1本来是没有时间逆转能力的,现在又认为时间点t1又有时间逆转能力,那时间点t1到底是有还是没有时间逆转能力呢?或者说在时间点t0前,宿命论注定了时间点t1是没有时间逆转能力的,现在你又认为时间点t1具有时间逆转能力,那么这两个时间点t1究竟是不是同一个时间点?如果不是同一个时间点,说明你没有回到过去;如果是同一个时间点的话,岂不是自相矛盾吗?

    为了说得更形象一些,不妨假设你坐一艘超光速飞船,准备从时间点t0回到时间点t2去,假设你回到t2后,随着时间的流逝,又达到了时间点t0,如果这时你又再次坐超光速飞船返回时间点t2,那么一个值得思考的问题就出现了,“你在时间点t2能不能看到上次返回时间点t2的飞船?”

    如果回答不能看到飞船,那么上次返回的飞船那里去了呢?显然很难解释通。如果回答能看到飞船,那么你可以到达时间点t2后,下次时间到达t0时,你又坐飞船返回t2,这次你将可以看到上两次的两艘飞船。如果这样一直循环下去,最后你会发现你可以在时间点t2看到无穷多的飞船。用程序员的术语说,叫做“程序陷入了死循环”,最后系统必然会出现“Out of Memory”现象而崩溃。

    当然,你也可以认为有其他的方法,不需要飞船,可以一次性从时间点t0直接跳跃到时间点t2,并不需要经过时间点t1。下面不妨来分析一下这个方法是否可行。

    既然是直接跳跃到时间点t2,那么你必然是在一个无穷小的时间里出现在时间点t2的某个空间里,例如你要在时间点t2回到某个广场上。首先说明一下为什么是无穷小的时间里出现的,因为如果不是无穷小的时间里出现的话,那么必然可以取到一个时间点t1,会导致前面所说的时间点t1上出现悖论。

    你在广场上出现的时,广场上的空气必然要为你让开空间,而这是在无穷小的时间里完成的,那么很容易推导出你周围的空气获得的加速度和速度都是无穷大,因而它具有的动能也是无穷大,无穷大的能量和无穷大的速度意味着什么?一只鸟都可以将飞机撞下来,如果宇宙是有限大的话,它可以让这个宇宙炸毁无穷次;即使宇宙是无限大,它也足以让宇宙炸毁一次。宇宙都毁灭了,又何来的时间?还能说你回到了时间点t2吗?

    也许上面说的这些你仍然难以相信,不妨再说得更现实一些,假设你要回到100年前的一个时间点,这100年中,天上有多少流星湮灭了?有多少新星生成了?宇宙膨胀了多少?你有能力让湮灭的流星复原、生成的新星重新返回未生成前的状态,膨胀的宇宙收缩回去吗?如果这些东西的状态没有回复到100年前,又怎么能说明你回到的是100年前的时间点呢?

    根据上面的推导和分析,个人认为使时间逆转的方法是不存在的,所以第12层楼是不存在的,自然没有人可以骑到“上帝”的头上。

    宿命论将在有时间的时间里永远统治这个世界

     

    原文转自:http://developer.51cto.com/art/201011/233083.htm

    展开全文
  • 首先目的是在轴线的交点处创建柱子步:在Revit里面画上测试代码的图(几条相交的轴线) 由于没画过图,很懵逼,所以百度了怎么画轴线。我参考的是这个网址https://jingyan.baidu.com/article/3052f5a1e...
  • 自西方文艺复兴以来,中国在自然科学方面落后西方很多,软件领域也不例外。当然现在中国的许多程序员们对此可能有许多不同的意见,有些人认为中国的程序员水平远落后...要解决这个问题,必须先知道程序员有多少种技术
  • 个人项目之“二柱子四则运算升级版”(续) 首先,得跟王老师、跟助教老师说声抱歉。上篇博客没有按时发送的原因我必须在这里像您解释一下,希望您一定要相信我并尽可能的原谅我(╥╯^╰╥)。昨天(2016/03/12)...
  • 5对二层进行调整,冰冻图层,删除对称的其中一半,打开图层,删除一层的室外台阶,栏杆等,以及他们的标注,将楼梯改为中间层。 绘制露台:pl绘制参考线,“楼梯其他”“阳台” 在选择门窗...
  • 当"专家"们想继续往上一层楼爬时,他们几乎一眼就可以看到楼梯的入口,不过令他们吃惊的是,楼梯入口处竖了一道高高的门槛,上面写着"创新"字。不幸的是,大多数人在爬到第5层楼时已经体能消耗过度,无力翻过这道...
  • 、建筑物定位 房屋建筑工程开工后的第次放线,建筑物定位参加的人员是:城市规划部门(下属的测量队)及施工单位的测量人员,根据建筑规划定位图(总平面图)进行定位,最后在施工现场形成(至少)4个定位桩。...
  • 程序员的十个层次,你属于哪一层?欢迎使用Markdown编辑器第1层 菜鸟第2层 大虾第3层 牛人第4层 大牛第5层 专家第6层 学者第7层 大师第8层 科学家第9层 大科学家第10层 大哲总之第11层 上帝 欢迎使用Markdown编辑器 ...
  • 很久之前的看到的个文章(至少快有十年的历史了吧),然后收藏了下来,现在我在这里再宣传一下,我是认为这篇文章对于我们来说,不论是否认同他的观点,但是一定会带来更多的思考。有时候关于程序员的层次定位,...
  • 模板施工的方案.doc

    2021-04-22 16:11:45
    地下四层,地上二十二层。檐口高度87.65m。室内外高差-0.45m。±0.000=45.500m,为全现浇框架—剪力墙结构。 2、结构抗震等级为:地下三、四层框架—剪力墙,三级;地下二层以上框架—剪力墙,级。 3、地下三层...
  • 预世界末日的三个柱子 什么是Java开发人员最有用的监视工具? 监视是当今生产环境中的项基本功能。 错误和性能问题一直在弹出,而不仅仅是在工作时间内出现,因此良好的监视工具需要24/7全天候运行。 有很多...
  • 版做出来后,老大说,你这个柱状图把他变成每个柱子颜色不一样,再加一个图例,可是我这只有一层数据,一个横坐标一个纵坐标就可以解决了,为什么让我加图例,我去看了看echarts官方,一层数据确实没有办法加...
  • 这篇同上篇“【转】世界上最牛的程序员”一样都是收藏很久的东西了,现在也忍痛转载一下。 程序员的十楼 作者:周伟明 自西方文艺复兴以来,中国在自然科学方面落后西方很多,软件领域也不例外。当然现在中国的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,035
精华内容 2,014
关键字:

一层柱子二层板