魔数也称为魔法数字,在编程领域指的是莫名其妙出现的数字。数字的意义必须通过详细阅读才能推断出来,虽然不知道这个数字是个什么用的,究竟代表什么,但是编译后的程序可以正常运行,像是“魔术般的数字”。
一、魔数的来源
在源代码编写中,有这么一种情况:编码者在写源代码的时候,使用了一个数字,比如0x2123,0.021f等,他当时是明白这个数字的意思的,但是别的程序员看他的代码,可能很难理解,甚至,过了一段时间,代码的作者自己再看代码的时候也忘记了这个数字代表的含义。于是感叹,虽然不知道这个数字是干什么用的,究竟代表什么,但是编译后的程序可以正常运行,真是“魔术般的数字”,魔数即源于此。
二、魔数的用法
“魔数”有贬义词、中性词、褒义词三种用法,默认为贬义词。
1、贬义词“魔数”
指的是代码中出现的没有说明的数字。代码中突然出现一个没说明用途的数字会让其它阅读代码、维护代码的的人非常难受。例如:const int N = 2073600;
for (int i=0; i { …… 看代码的人需要猜2073600是什么意思,而且特别难猜。改成这样就清楚多了: const int WIDTH = 1920; const int HEIGHT = 1080; int totalPixels = WIDTH * HEIGHT; 这里的“魔数”就是指代码中直接出现的数字。现代编程规范比较忌讳这样写代码,一方面看不懂意思,另一方面如果2073600这个数字多次出现,一旦需要修改的时候就需要全部找出来改掉,一旦少改一处就会产生BUG,非常麻烦。我们在编程中要尽可能避免使用“魔数”,例如写3.1416这种数字,也应该改为数学库中的π常数,例如Unity中的Mathf.PI。 最典型的例子就是现代3D游戏之父约翰·卡马克在雷神之锤中的那个魔数: i = 0x5f3759df – ( i >> 1 ); 配合前后的代码,这句代码可以快速计算一个数字的平方根的倒数。具体推导过程比较复杂,涉及到浮点数的原理。 某些具有特定格式的文件,喜欢在文件开头写几个特殊的字符以表明自己的身份,以便验明正身。例如常见的几种图片格式的文件: JPEG (jpg),文件头:FFD8FF PNG (png),文件头:89504E47 GIF (gif),文件头:47494638 Windows Bitmap (bmp),文件头:424D 如果你用16进制编辑器打开一个文件,它的开头不是FFD8FF,那就不是jpg文件。这个魔数一般会在相关文件标准中进行规定,所有人都要遵守。 例如float time=1.0f;//小数类型时间=1.0f float speed=time*2.13f;//小数类型速度=时间*2.13f 如果没有说明,很难猜到那个2.13f的含义,假如它代表加速度,那么修改如下: #define ACCELERATION (2.13f); float speed=time*ACCELERATION;//小数类型速度=时间*加速 这样对于代码阅读者来说更好理解。 例如setfontcolor(string,0xFFFFFFFF); setbackcolor(widget,0xFFFFFFFF);暂且不说0xFFFFFFFF代表的含义,如果程序中很多地方使用了统一的一个常量,如果要修改值的时候很麻烦,也容易出错。可能有遗漏等等诸多问题。 同样可以改为如下: static const int WHITE=0xFFFFFFFF; setfontcolor(string,WHITE); setbackcolor(widget,WHITE);//设置背景色(小部件、WHITE); 这样程序代码不仅便于阅读,而且要替换他的值,只需要替换一次就好了。 解决魔术数字的方法主要是将这些数字定义为常量,或者枚举类型,或者使用编译器的宏定义(如C/C++的#define)2、褒义词“魔数”
3、中性词“魔数”
三、魔数的弊端
1、代码可读性差
2、修改不方便
一个工具满足团队所需:任务、项目、文档、IM、目标、 日历、
甘特图、工时、审批以及更多,让工作更简单

