计算机中
magic number 在计算机中可译为"幻数",或者"魔数",或者直接称其为magic number.中国*的叫法是魔术数字.它可以用来标记文件或者协议的格式.很多文件都有magic标志来表明该文件的格式. 例如win32可执行程序的开头标记一般为[MZ],这是一种源于DOS时代的格式. rar压缩档文件的开头有[Rar]三个字符,zip文档开头为[PK] ("pack")可以用记事本(或者Ultra Edit)直接打开以上文件类型的文件,查看开头的magic.
一般而言,硬盘数据恢复软件(如 EasyRecovery),就是靠分析磁盘上的原始数据,然后根据文件magic来试图匹配文件格式,从而尝试识别出磁盘中那些已经从文件系统登记表中删除的文件(真实的文件内容可能没有被覆盖).但是这种方法不是100%精确,因为磁盘中数据的随机性也很大,很多没有意义的字符串,可能被误认为是有效的File Magic,从而造成回复出无效/错误的文件.(p.s.你可以在EasyRecovery中自己定义文件的Magic然后让它帮你回复,不过常用的文件格式它都有记录)通常在应用开发中,文件读写也可能使用文件的magic.例如读取文件时,用它来判断文件的格式是否匹配.如果不匹配则报告错误不处理文件,或者尝试读取文件的magic标记来识别.
常见的例子.例如,把一个bmp图像文件的扩展名改名为png,可能有些图像浏览/编辑软件提示:类型错误,加载失败,但是有的软件却可以识别并读出,并提示格式跟扩展名不匹配.
程序设计
程式设计中所谓的魔术数字(magic number)是指直接写在程式码里的具体数值(如“10”“123”等以数字直接写出的值)。虽然程式作者写的时候自己能了解数值的意义,但对其他程式员而言,甚至制作者本人经过一段时间后,会难以了解这个数值的用途,只能苦笑讽刺“这个数值的意义虽然不懂,不过至少程式能够执行,真是个魔术般的数字”而得名。
因为下述理由,一般认为程式码中不应该含有魔术数字。
- 数值的意义难以了解
- 数值需要变动时,可能要改不只一个地方
例1:
price_tax = 1.05 * price
例1是对输入的价格(price)计算含税(price_tax)售价的程式。 但税率并不是万年不变,当*调整税率时,会有修改程式的必要。 这里“1.05”就是一种魔术数字,“为什么是1.05”会让人无法马上了解。 下面是去掉魔术数字的范例,程式容易了解也容易修正。
例1 (修正):
TAX = 0.05
price_tax = (1.0 + TAX) * price
例2:
setColor("text", 0xffffff)
例2是设定以白色显示程式码。 然而十六进制的色码0xffffff很难直觉看懂是“白色”,故也算是一种魔术数字。 下面是一种拿掉魔术数字的方式。
例2 (修正):
white = 0xffffff
setColor("text", white)
像这样,将魔术数字置换成常数或列举型别是经常用来解决魔术数字问题的手段。由于常数可以赋予易懂的名称,可使帮助阅读者了解数值的意义。 当然,在程式初始化部分定义的常数列表不称为魔术数字。
例3:
year = (new Date()).getYear() - 1911;
例3是用来取得今年之中华民国纪年的程式码。 然而将“1911”写死在程式码里并不尽理想,例如程式不易在其他国家使用等。 下面是一种拿掉魔术数字的方式。
function get*Year() { return (new Date()).getYear() - 1911; }
year = get*Year();
这个范例则使用函式来包装整段计算中华民国纪年的逻辑,函式内则直接保留数值1911。 这样做的好处是在程式中可借由get*Year()这个函式名称更容易了解程式意图,并对未来若需支援其他国家时保留弹性。 例如,需要使用日本历时,可只抽换函式部分而不动到程式所有参考年份运算的地方。
另外,在 一些编程语言中,1与0经常直接作为“真”、“假”的意义(布林值)使用,有时候也不被认为是魔术数字。 (但近年的语言多半建议使用true与false替代。)