What are “magic numbers” in computer programming?
当人们谈论在计算机编程中使用"魔术数字"时,他们的意思是什么?
魔术数字是代码中的任何数字,对于知之甚少的人来说并不是很明显。
例如,以下代码:
1 | sz = sz + 729; |
有一个神奇的数字,并将更好地写为:
1 | sz = sz + CAPACITY_INCREMENT; |
一些极端的观点表明你的代码中除了-1,0和1之外你不应该有任何数字,但我更喜欢一种不那么教条的观点,因为我会立刻认出24,1440,86400,3.1415,2.71828和1.414--这一切都取决于你的知识。
然而,即使我知道一天有1440分钟,我可能仍会使用
使用标识符意味着您不必浏览所有700个源文件,并在容量增量更改时将
1 | #define CAPACITY_INCREMENT 729 |
至:
1 | #define CAPACITY_INCREMENT 730 |
并重新编译该批次。
将此与魔术常数进行对比,这是因为天真的人认为只是因为他们从代码中删除了实际的数字,他们可以改变:
1 | x = x + 4; |
至:
1 2 | #define FOUR 4 x = x + FOUR; |
这为您的代码增加了绝对零的额外信息,完全浪费时间。
"幻数"是出现在语句中的数字
1 | if days == 365 |
假设你不知道一年中有365天,你会发现这个说法毫无意义。因此,将所有"魔法"数字(在程序中具有某种重要性的数字)分配给常量是一种很好的做法,
1 | DAYS_IN_A_YEAR = 365 |
从那以后,与之相比。它更容易阅读,如果地球被淘汰不对齐,我们获得额外的一天......你可以很容易地改变它(其他数字可能更有可能改变)。
这不仅仅是一个含义。大多数答案已经给出的答案(任意未命名的数字)是一个非常常见的答案,我唯一要说的就是有些人走极端定义......
1 2 | #define ZERO 0 #define ONE 1 |
如果你这样做,我会追捕你并且毫不留情。
但是,另一种幻数用于文件格式。它只是一个值,通常是文件中的第一件事,它有助于识别文件格式,文件格式的版本和/或特定文件的字节序。
例如,您可能有一个幻数0x12345678。如果你看到这个神奇的数字,那么你可以看到一个正确格式的文件。另一方面,如果你看到0x78563412,那么你可以看到你正在看到相同文件格式的字节序交换版本。
然而,术语"幻数"被滥用了一些,指的是几乎任何标识文件格式的东西 - 包括标题中相当长的ASCII字符串。
http://en.wikipedia.org/wiki/File_format#Magic_number
维基百科是你的朋友(Magic Number文章)
到目前为止,大多数答案都将幻数描述为一个不能自我描述的常数。作为一个"老派"程序员自己,回到那一天我们将魔术数字描述为任何常量,这些常量被分配了一些影响代码行为的特殊目的。例如,数字999999或MAX_INT或其他完全任意的。
魔术数字的一个大问题是它们的目的很容易被遗忘,或者在另一个完全合理的语境中使用的价值。
作为一个原始而极其人为的例子:
1 2 3 4 5 6 7 8 9 | while (int i != 99999) { DoSomeCleverCalculationBasedOnTheValueOf(i); if (escapeConditionReached) { i = 99999; } } |
使用或不命名常量的事实并不是真正的问题。在我可怕的例子中,值会影响行为,但是如果我们需要在循环时更改"i"的值呢?
显然,在上面的例子中,你不需要一个幻数来退出循环。你可以用break语句替换它,这是魔术数字的真正问题,它们是一种懒惰的编码方法,并且总是可以被不太容易失败的东西所取代,或者随着时间的推移失去意义。
幻数是某些变量的特殊值,它使程序以特殊方式运行。
例如,通信库可能会采用Timeout参数,它可以定义幻数"-1"以指示无限超时。
除了应用程序本身之外,任何对任何人都没有明显意义的东西。
1 2 3 4 5 | if (foo == 3) { // do something } else if (foo == 4) { // delete all users } |
术语幻数通常用于描述代码中的一些数字常量。出现的数字没有任何进一步的描述,因此其含义是深奥的。
使用命名常量可以避免使用幻数。
它可能看起来有点平庸,但每种编程语言至少有一个真正的神奇数字。
0
我认为,在几乎所有程序员的魔杖颤抖中统治它们都是神奇的魔杖。
FALSE不可避免地为0
TRUE不是(FALSE),但不一定是1!可以是-1(0xFFFF)
NULL不可避免地为0(指针)
并且大多数编译器允许它,除非他们的类型检查是彻头彻尾的狂热。
0是数组元素的基本索引,除了语法如此过时,基本索引为'1'。然后可以方便地编码(i = 0; i <32; i ++),并期望'i'将从基数(0)开始,并且增加到,并且停止在32-1 ...第32个成员一个数组,或者其他什么。
0是许多编程语言字符串的结尾。"停在这里"的价值。
0同样内置于X86指令中以"有效地移动字符串"。节省许多微秒。
程序员经常使用0来表示例程执行中"没有出错"。它是"非例外"代码值。可以使用它来表示缺少抛出异常。
零是程序员最经常给出的做一些完全无关紧要的工作量的答案,比如将活动单元格的颜色改为紫色而不是亮粉色。"零,男人,就像零!"
0是我们希望实现的程序中的错误计数。 0个未解释的例外,0个未终止的循环,0个无法实际获取的递归路径。 0是我们试图在编程劳动,女朋友(或男朋友)"问题",糟糕的餐厅体验和一个人的汽车的一般特质方面实现的渐近线。
是的,0确实是一个神奇的数字。远比任何其他价值更具魔力。没什么......唉,接近了。
在简单和真实的单词中,幻数是三位数,其前两位的平方和等于第三位。
EX-202,
as,2 * 2 + 0 * 0 = 2 * 2。
现在,java中的WAP接受一个整数并打印是否是一个幻数。
使用0或1以外的计算中的数字,这些数字不是由某个标识符或变量定义的(这不仅可以通过在一个地方更改数字而在几个地方轻松更改数字,还可以使读者清楚地了解数字是为了)。