Magic Number(魔数)是什么

“魔数”有贬义词、中性词、褒义词三种用法,默认为贬义词。

1、贬义词“魔数”

指的是代码中出现的没有说明的数字。代码中突然出现一个没说明用途的数字会让其它阅读代码、维护代码的的人非常难受。例如:

const int N = 2073600;
for (int i=0; i<N; i++)
 { ......

看代码的人需要猜2073600是什么意思,而且特别难猜。改成这样就清楚多了:

const int WIDTH = 1920;
const int HEIGHT = 1080;
int totalPixels = WIDTH * HEIGHT;

这里的“魔数”就是指代码中直接出现的数字。现代编程规范比较忌讳这样写代码,一方面看不懂意思,另一方面如果2073600这个数字多次出现,一旦需要修改的时候就需要全部找出来改掉,一旦少改一处就会产生BUG,非常麻烦。

我们在编程中要尽可能避免使用“魔数”,例如写3.1416这种数字,也应该改为数学库中的π常数,例如Unity中的Mathf.PI

2、褒义词“魔数”

最典型的例子就是现代3D游戏之父约翰·卡马克在雷神之锤中的那个魔数:

i = 0x5f3759df - ( i >> 1 );

配合前后的代码,这句代码可以快速计算一个数字的平方根的倒数。具体推导过程比较复杂,涉及到浮点数的原理。

这个靓丽的骚操作给了其它人非常大的震撼,是那个年代的大神级编程技术的缩影,所以被人们怀着敬仰之情称之为“魔数”,全称为“如魔法一样神奇的数字”。

3、中性词“魔数”

某些具有特定格式的文件,喜欢在文件开头写几个特殊的字符以表明自己的身份,以便验明正身。例如常见的几种图片格式的文件:

  1. JPEG (jpg),文件头:FFD8FF
  2. PNG (png),文件头:89504E47
  3. GIF (gif),文件头:47494638
  4. Windows Bitmap (bmp),文件头:424D

如果你用16进制编辑器打开一个文件,它的开头不是FFD8FF,那就不是jpg文件。这个魔数一般会在相关文件标准中进行规定,所有人都要遵守。

其它答主也列举了多种“魔数”,我再补充一个常用的魔数——Unicode的BOM魔数。由于它在Windows记事本中也会出现,所以我们会经常接触到它,虽然没有感觉。

打开一个记事本,随便输入一些内容,然后另存为。另存的时候可以选择编码

  1. 如果保存为Unicode,文件开头就会出现FF FE。
  2. 如果保存为Unicode big endian,文件开头就会出现FE FF。
  3. 如果保存为UTF-8,文件开头会出现EB BB BF。

这些数字不仅能代表它是什么编码,还能指定读取编码的顺序。细节就不谈了。

说这个例子是因为Windows记事本曾经出现过一个非常神奇的bug——你无法以ANSI编码保存一个内容为“联通”的文本文件。

这个问题是因为ANSI编码保存时,开头没有“魔数”,导致记事本识别不出文件是什么编码。而且“联通”两个字的GBK编码容易被错误识别为UTF-8编码,所以出了问题。

这个小BUG曾被作为微软和电信私通打击联通的证据 。

这其中有:
1. 一些图像文件中存在的魔数。比如,bmp文件中的’BM’,JPEG/JFIF中的’JFIF’,等等。
2. 某些格式的声音、视频文件中存在中的魔数。
3. PE文件、ELF文件中存在的魔数。
4. 各种文本编码中的BOM也可以看做魔数。比如UTF-8、UTF-16、UTF-32的BOM。
……
可以看到,很多文件类型都定义了自己的magic number来刷存在感。

说到魔数,不得不提Linux下的file命令。
file命令是一个很神奇的命令。它能够根据文件中魔数来判断文件类型。这比根据后缀来判断文件类型要靠谱一点。比如,即使把一张位图文件后缀名改为.jpg,file命令依然大公无私地告诉你它是一张bmp图片。
对于文本文件,file能够猜测文件是用什么编码存储的(但是并不总正确。要知道字符编码是一个很复杂的事情。所以,有一次,我在自己一个用Python写的小工具中使用了libmagic + chardet + 人工判断来判断文本文件的编码)。
file命令其实是依赖于libmagic的(C版本:libmagic | SourceForge.net,Python版本:ahupp/python-magic · GitHub),而libmagic则是从一个配套的“魔数数据库”(暂且这么叫吧)magic.mgc中来获取不同文件的标志性魔数,进而实现文件类型的判断。有兴趣的代码猴子可以探究一下magic.mgc文件中有哪些魔数(我没探究过)。
这里给出一些相关链接:
Magic editing and creation: a primer
Linux file utility magic.mgc database get content

此外,Python中附带两个根据文件中魔数来简单地判断一下文件类型的库:
21.8. imghdr
21.9. sndhdr
第一个根据图像文件中的魔数来判断图像文件的格式,第二个则判断声音文件的格式。用IDLE打开这两个库,看一看它们都用了哪些魔数吧。

最后,我想说一下的是,医学影像设备产生的DICOM图像文件中的魔数才多得丧心病狂。发两张以前分析DICOM图像时截的图片吧。

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值