关于语言不可知:计算机编程中的“神奇数字”是什么?

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分钟,我可能仍会使用MINS_PER_DAY标识符,因为它使得搜索它们变得更容易。谁说上面提到的容量增量也不会是1440而你最终改变了错误的值?对于低数字尤其如此:双重使用37197的机会相对较低,将5用于多个事物的几率非常高。

使用标识符意味着您不必浏览所有700个源文件,并在容量增量更改时将729更改为730。你可以改变一行:

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确实是一个神奇的数字。远比任何其他价值更具魔力。没什么......唉,接近了。

[email protected]


在简单和真实的单词中,幻数是三位数,其前两位的平方和等于第三位。
EX-202,
as,2 * 2 + 0 * 0 = 2 * 2。
现在,java中的WAP接受一个整数并打印是否是一个幻数。


使用0或1以外的计算中的数字,这些数字不是由某个标识符或变量定义的(这不仅可以通过在一个地方更改数字而在几个地方轻松更改数字,还可以使读者清楚地了解数字是为了)。