第一次作业 读《数学之美》有感+代码规范

                            读《数学之美》有感

  刚开始老师让我们看《数学之美》这本书我是表示很不理解的,因为我想又不是语文课,为什么要写读后感,又不是数学课为什么要看数学之美,但是看了之后,我才发现这本书真的很有用。

  其实我还没有读几章节,但是前面讲统计语言模型不仅引起了我很大的兴趣,而且给了我很大的启发。书中提到,如果想知道一个S序列在文中出现的概率,就是将该序列中每个词出现的概率相乘,如P(S)=P(w1)P(w2|w1)P(w3|w1 w2)......P(wn | w1 w2.....wn-1),其中P(w2 | w1)是在已知第一个词出现的情况下,第二个词出现的概率。但是如果要推算一个词出现的概率,要与前面n-1个词都有关,计算量过于庞大且计算难度高因此,有了马尔可夫假设,即任意一个词wi出现的概率只同它在前面的词wi-1有关。公式也简化如下:P(S)=P(w1)P(w2 |w1)P(w3 | w2).....P(wi |wi-1) 。

  这让我联想到了我大一在实验室装的Moses基于统计的机器翻译系统,在每个机器翻译系统装完后,我们都需要测试BLEU值。BLEU值是用来判断两个句子的相似程度的,举一个简单的栗子:两个句子S1=I learn C++;S2:I learn Java;这两个句子的相似度就是2/3,分子是一个候选翻译的单词有多少出现在参考翻译中(不管是不是在同一句参考翻译中),分母是这个候选翻译的词汇数。为什么说不管是不是在同一句参考翻译中,这是因为BLEU是将一句机器翻译的话语相对应的几个参考翻译作比较,算出一个综合分数,因此不是与一句话相比较,而是与多句参考翻译相比较。为了避免常用词干扰,我们还用了改进的多元精度比较句中某词在每个参考翻译中出现的次数,在将比较得到的结果去最大的,得到最后的BLEU。

  除此之外还利用了统计模型解决了中文的分词二义性问题,利用统计语言模型算出每种分词后的句子出现的概率,找出其中概率最大的就是最好的分词方法。这又让我联想到了,Moses的安装在Corpus Preparation的过程中。

Tokenize:在单词和标点符号之间插入空格。
Truecasing:每个句子中的单词都被转换为最可能的原型,这有助于减少数据的稀疏性。
 cleaning:长句和空语句可引起训练过程中的问题,因此将其删除,同时删除显不对齐句子删除。

而在语料的预处理过程中,需要先将中文语料进行分词,便于之后利用GIZA++对平行语料进行对齐。

 我相信《数学之美》中提到的统计语言模型对统计机器翻译的帮助是很大的。

   慢慢看下去《数学之美》我发现能够学到很多东西,数学和计算机还是分不开的,很多算法,训练模型都与数学有关,之后我还会继续看《数学之美》,相信我会有更深的体会。 

以C++的代码规范为标准:

参考:(1条消息)11条最全面的C/C++编码规范总结 - oada的博客 - CSDN博客  https://blog.csdn.net/p942005405/article/details/80282572

一、文件排版方面


1. 包含头文件

 • 先系统头文件,后用户头文件。
 • 系统头文件,稳定的目录结构,应采用包含子路径方式。
 • 自定义头文件,不稳定目录结构,应在dsp中指定包含路径。
 • 系统头文件应用:#include <xxx.h>
 • 自定义同文件应用:#include "xxx.h"
 • 只引用需要的头文件。

2. h和cpp文件

 • 头文件命名为.h,内联文件命名为.inl;C++文件命名为*.cpp
 • 文件名用大小写混合,或者小写混合。例如DiyMainview.cppinfoview.cpp。不要用无意义的名称:例如XImage.cppSView.cppxlog.cpp
 • 头文件除了特殊情况,应使用#ifdef控制块。
 • 头文件#endif应采用行尾注释。
 • 头文件,首先是包含代码块,其次是宏定义代码块,然后是全局变量,全局常量,类型定义,类定义,内联部分。
 • CPP文件,包含指令,宏定义,全局变量,函数定义。

3. 文件结构

 • 文件应包含文件头注释和内容。
 • 函数体类体之间原则上用2个空行,特殊情况下可用一个或者不需要空行。

4. 空行

 • 文件头、控制块,#include部分、宏定义部分、class部分、全局常量部分、全局变量部分、函数和函数之间,用两个空行。

二、注释方面


1. 文件头注释

 • 作者,文件名称,文件说明,生成日期(可选)

2. 函数注释

 • 关键函数必须写上注释,说明函数的用途。
 • 特别函数参数,需要说明参数的目的,由谁负责释放等等。
 • 除了特别情况,注释写在代码之前,不要放到代码行之后。
 • 对每个#else#endif给出行末注释。
 • 关键代码注释,包括但不限于:赋值,函数调用,表达式,分支等等。
 • 善未实现完整的代码,或者需要进一步优化的代码,应加上 // TODO …
 • 调试的代码,加上注释 // only for DEBUG
 • 需要引起关注的代码,加上注释 // NOTE …
 • 对于较大的代码块结尾,如for,while,do等,可加上 // end for|while|do

三、命名方面


1. 原则

 • 同一性:在编写一个子模块或派生类的时候,要遵循其基类或整体模块的命名风格,保持命名风格在整个模块中的同一性。
 • 标识符组成:标识符采用英文单词或其组合,应当直观且可以拼读,可望文知意,用词应当准确,避免用拼音命名。
 • 最小化长度 && 最大化信息量原则:在保持一个标识符意思明确的同时,应当尽量缩短其长度。
 • 避免过于相似:不要出现仅靠大小写区分的相似的标识符,例如"i"与"I""function""Function"等等。
 • 避免在不同级别的作用域中重名:程序中不要出现名字完全相同的局部变量和全局变量,尽管两者的作用域不同而不会发生语法错误,但容易使人误解。
 • 正确命名具有互斥意义的标识符:用正确的反义词组命名具有互斥意义的标识符,如:"nMinValue" 和"nMaxValue""GetName()" 和"SetName()" ….
 • 避免名字中出现数字编号:尽量避免名字中出现数字编号,如Value1,Value2等,除非逻辑上的确需要编号。这是为了防止程序员偷懒,不肯为命名动脑筋而导致产生无意义的名字(因为用数字编号最省事)。

2. T,C,M,R类

 • T类表示简单数据类型,不对资源拥有控制权,在析构过程中没有释放资源动作。
 • C表示从CBase继承的类。该类不能从栈上定义变量,只能从堆上创建。
 • M表示接口类。
 • R是资源类,通常是系统固有类型。除了特殊情况,不应在开发代码中出现R类型。

3. 函数名

 • M类的函数名称应采用HandleXXX命名,例如:HandleTimerEvent;不推荐采用java风格,例如handleTimerEvent;除了标准c风格代码,不推荐用下划线,例如,handle_event
 • Leave函数,用后缀L。
 • Leave函数,且进清除栈,用后缀LC。
 • Leave函数,且删除对象,用后缀LD。

4. 函数参数

 • 函数参数用a作为前缀。
 • 避免出现和匈牙利混合的命名规则如apBuffer名称。用aBuffer即可。
 • 函数参数比较多时,应考虑用结构代替。
 • 如果不能避免函数参数比较多,应在排版上可考虑每个参数占用一行,参数名竖向对齐。

5. 成员变量

 • 成员变量用m最为前缀。
 • 避免出现和匈牙利混合的命名规则如mpBuffer名称。用mBuffer即可。

6. 局部变量

 • 循环变量和简单变量采用简单小写字符串即可。例如,int i;
 • 指针变量用p打头,例如void* pBuffer;

7. 全局变量

 • 全局变量用g_最为前缀。

8. 类名

 • 类和对象名应是名词。
 • 实现行为的类成员函数名应是动词。
 • 类的存取和查询成员函数名应是名词或形容词。

9. 风格兼容性

 • 对于移植的或者开源的代码,可以沿用原有风格,不用C++的命名规范。

四、代码风格方面

1. Tab和空格

 • 每一行开始处的缩进只能用Tab,不能用空格,输入内容之后统一用空格。除了最开始的缩进控制用Tab,其他部分为了对齐,需要使用空格进行缩进。这样可以避免在不同的编辑器下显示不对齐的情况。
 • 在代码行的结尾部分不能出现多余的空格。
 • 不要在"::","->","."前后加空格。
 • 不要在",",";"之前加空格。

2. 类型定义和{

 • 类,结构,枚举,联合:大括号另起一行

3. 函数

 • 函数体的{需要新起一行,在{之前不能有缩进。
 • 除了特别情况,函数体内不能出现两个空行。
 • 除了特别情况,函数体内不能宏定义指令。
 • 在一个函数体内,逻揖上密切相关的语句之间不加空行,其它地方应加空行分隔。
 • 在头文件定义的inline函数,函数之间可以不用空行,推荐用一个空行。

4. 代码块

 • "if"、"for"、"while"、"do"、"try"、"catch" 等语句自占一行,执行语句不得紧跟其后。不论执行语句有多少都要加 “{ }” 。这样可以防止书写和修改代码时出现失误。
 • "if"、"for"、"while"、"do"、"try"、"catch" 的括号和表达式,括号可紧挨关键字,这样强调的是表达式。

5. else

• if语句如果有else语句,用 } else { 编写为一行,不推荐用 3 行代码的方式。

6. 代码行

 • 一行代码只做一件事情,如只定义一个变量,或只写一条语句。这样的代码容易阅读,并且方便于写注释。
 • 多行变量定义,为了追求代码排版美观,可将变量竖向对齐。
 • 代码行最大长度宜控制在一定个字符以内,能在当前屏幕内全部可见为宜。

7. switch语句

 • case关键字应和switch对齐。
 • case子语句如果有变量,应用{}包含起来。
 • 如果有并列的类似的简单case语句,可考虑将case代码块写为一行代码。
 • 简单的case之间可不用空行,复杂的case之间应考虑用空行分割开。
 • case字语句的大括号另起一行,不要和case写到一行。
 • 为所有switch语句提供default分支。
 • 若某个case不需要break一定要加注释声明。

8. 循环

 • 空循环可用 for( ;; ) 或者 while( 1 ) 或者 while( true )

五、类型


• 定义指针和引用时*和&紧跟类型。
• 尽量避免使用浮点数,除非必须。
• 用typedef简化程序中的复杂语法。
• 避免定义无名称的类型。例如:typedef enum { EIdle, EActive } TState;
• 少用union,如果一定要用,则采用简单数据类型成员。
• 用enum取代(一组相关的)常量。
• 不要使用魔鬼数字。
• 尽量用引用取代指针。
• 定义变量完成后立即初始化,勿等到使用时才进行。
• 如果有更优雅的解决方案,不要使用强制类型转换。

六、表达式


• 避免在表达式中用赋值语句。
• 避免对浮点类型做等于或不等于判断。
• 不能将枚举类型进行运算后再赋给枚举变量。
• 在循环过程中不要修改循环计数器。
• 检测空指针,用 if( p )
• 检测非空指针,用 if( ! p )

以java的代码规范为例:

参考:解读阿里官方代码规范 - 上尤流苏 - 博客园  https://www.cnblogs.com/renyuanwei/p/9169452.html

命名规约:

1.代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束

2.代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式

3.类名以UpperCameCase的风格(前缀大写多字嵌合文字转换法),必须遵循驼峰的形式(某些情况诸如领域模型相关的命名除外,如:DO/BO/DTO/VO);

4.方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase(驼峰式字体),必须遵从驼峰形式

5.常量命名全部大写(很容易忘),单词间用下划线隔开

6.包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词

 命名原则:

1.力求语义表达完整清楚,不要嫌名字长

2.杜绝完全不规范的缩写,避免望文不知意

(最好不要用缩写)

类的命名:

1.抽象类命名使用Abstract或Base开头;异常类命名使用Expetion结尾;测试类命名以它要测试的类名称开始,以Test结尾

2.对于Service和DAO类,基于SOA的理念,暴露出来的服务一定是接口,内部的实现类用Impl的后缀与接口区别

3.如果形容能力的接口名称,取对应的形容词做接口名

4.枚举类名建议带上Enum后缀,枚举成名名称需要全大写,单词间用下划线隔开

5.如果使用到了设计模式,建议在类名中体现出具体模式

6.包名统一使用单数形式;类名如果有复数含义,类名可以使用复数形式

常量规约:

1.不允许出现任何魔法值(即未经定义的常量)直接出现在代码中

2.不要使用一个常量类维护所有常量,应该按常量功能进行归类,分开维护

3.常量的复用层次有五层:跨应用共享常量,应用内共享常量,子工程内共享常量,包内共享常量,类内共享常量

4.如果变量值仅在一个范围内变化用Enum类,如果还带有名称之外的延伸属性,必须使用Enum类

5.尽量不要在接口里定义变量,如果一定要定义变量,肯定与接口方法相关,并且是整个应用的基础常量

(核心:1.别使用常量;2.让常量可控)

语法:

1.long 或者Long初始赋值时,必须使用大写的L,不能是小写的l,小写容易跟数字1混淆,造成误解

2.接口类中的方法和属性不要加任何修饰符号(public 也不要加),保持代码的简洁性,并加上有效的Javadoc注释

3.所有的覆写方法,必须加@Override注释

4.可变参数必须放置在参数列表的最后

5.final课提高程序响应效率

格式约束:

1.缩进采用4个空格,禁止使用tab字符

2.单行字符数限不超过120个

3.IDE的text file encoding设置为UTF-8

IDE中文件的换行符使用Unix格式,不要使用windows格式

4.方法体内的执行语句组、变量的定义语句组,不同业务逻辑之间或者不同语义之间插入一个空行

注释规约:

1.所有枚举类型字段必须要有注释,说明每个数据项的用途

2.如果英文注释解释的不清楚,用中文注释吧问题说清楚。专有名词与关键字保持英文原文即可

3.注释掉的代码尽量要配合说明,而不是简单的注释掉(除非很短时间内可恢复不然建议直接删除)

4.好的命名,代码结构是自解释的,注释力求精简准确,表达到位

代码风格:

1.在一个switch快中,每个case要么通过break/return等来终止,要么注释说明程序将继续执行到哪一个case为止

2.在if/else/for/while/do语句中必须使用大括号,即使只有一行代码,避免使用下面的形式:

if (condition)statements;

3.推荐尽量少用else,if-else的方式可以改写成

if(condition){

...

return obj;

}

//接着写else的业务逻辑代码

(因为else不仅会带来大段的代码缩进的困扰,同时也会降低代码的可读性)

4.如果非得使用if ()...else if() ...else...方式表达逻辑,【强制】请勿超过3层,超过请使用状态设计模式

5.除常用方法(如getXXX/isXX)等外,不要在条件判断中执行其他复杂语句,将复杂逻辑判断的结果赋值给一个有意义的布尔变量名,以提高可读性

boolean existed = (file.open(fileName,"w")!=null)&&(...)||(...);

if (existed) {

...

}

方法命名:

Service/DAO 层方法命名规约:

1.获取单个对象的方法用get做前缀

2.获取多个对象的方法用list做前缀

3.获取统计值的方法用count做前缀

4.插入的方法用save(推荐)或insert做前缀

5.删除的方法用remove(推荐)或delete做前缀

6.修改的方法用update做前缀

在接下来的学习中我将会以这两篇为我的代码规范。

 

posted on 2019-09-01 17:41  流星雨lxy  阅读(392)  评论(1编辑  收藏  举报

导航