Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
Magic number (programming)
(section)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
== Unnamed numerical constants == The term '''''magic number''''' or '''''magic constant''''' refers to the [[anti-pattern]] of using numbers directly in source code. This breaks one of the oldest rules of programming, dating back to the [[COBOL]], [[FORTRAN]] and [[PL/1]] manuals of the 1960s.<ref name="MartinG25">{{cite book |title=Clean Code - A handbook of agile software craftsmanship |url=https://archive.org/details/cleancodehandboo00mart_843 |url-access=limited |last=Martin |first=Robert C. |date=2009 |publisher=Prentice Hall |location=Boston |isbn=978-0-13-235088-4 |page=[https://archive.org/details/cleancodehandboo00mart_843/page/n330 300] |chapter= Chapter 17: Smells and Heuristics - G25 Replace Magic Numbers with Named Constants }}</ref> In the following example that computes the price after tax, <code>1.05</code> is considered a magic number: price_tax = 1.05 * price The use of unnamed magic numbers in code obscures the developers' intent in choosing that number,<ref name="MartinG16">{{cite book |title=Clean Code - A handbook of agile software craftsmanship |url=https://archive.org/details/cleancodehandboo00mart_843 |url-access=limited |last=Martin |first=Robert C. |year=2009 |publisher=Prentice Hall |location=Boston |isbn=978-0-13-235088-4 |page=[https://archive.org/details/cleancodehandboo00mart_843/page/n325 295] |chapter= Chapter 17: Smells and Heuristics - G16 Obscured Intent}}</ref> increases opportunities for subtle errors, and makes it more difficult for the program to be adapted and extended in the future.<ref>{{cite web |url=http://www.datamation.com/columns/article.php/3789981/Bjarne-Stroustrup-on-Educating-Software-Developers.htm |title=Bjarne Stroustrup on Educating Software Developers |first=James |last=Maguire |date=9 December 2008 |website=Datamation.com |url-status=dead |archive-url=https://web.archive.org/web/20180623112852/http://www.datamation.com/columns/article.php/3789981/Bjarne-Stroustrup-on-Educating-Software-Developers.htm |archive-date=23 June 2018}}</ref> As an example, it is difficult to tell whether every digit in <code>[[Pi|3.14159265358979323846]]</code> is correctly typed, or if the constant can be truncated to <code>3.14159</code> without affecting the functionality of the program with its reduced precision. Replacing all significant magic numbers with named [[constant (programming)|constant]]s (also called explanatory variables) makes programs easier to read, understand and maintain.<ref>{{cite web |url=http://www.ibm.com/developerworks/linux/library/l-clear-code/?ca=dgr-FClnxw01linuxcodetips |title=Six ways to write more comprehensible code |first=Jeff |last=Vogel |date=29 May 2007 |website=IBM Developer |archive-url=https://web.archive.org/web/20180926205449/https://www.ibm.com/developerworks/linux/library/l-clear-code/?ca=dgr-FClnxw01linuxcodetips |archive-date=26 September 2018 |url-status=dead }}</ref> The example above can be improved by adding a descriptively named variable: TAX = 0.05 price_tax = (1.0 + TAX) * price Names chosen to be meaningful in the context of the program can result in code that is more easily understood by a maintainer who is not the original author (or even by the original author after a period of time).<ref name="Paul_2002_SYMBOLS"/> An example of an uninformatively named constant is <code>int SIXTEEN = 16</code>, while <code>int NUMBER_OF_BITS = 16</code> is more descriptive. The problems associated with magic 'numbers' described above are not limited to numerical types and the term is also applied to other data types where declaring a named constant would be more flexible and communicative.<ref name="MartinG25"/> Thus, declaring <code>const string testUserName = "John"</code> is better than several occurrences of the 'magic value' <code>"John"</code> in a [[Test-driven development|test suite]]. === Random shuffle example === For example, if it is required to randomly shuffle the values in an array representing a standard pack of [[playing cards]], this [[pseudocode]] does the job using the [[Fisher–Yates shuffle]] algorithm: '''for''' i '''from''' 1 '''to''' 52 j := i + randomInt(53 - i) - 1 a.swapEntries(i, j) where <code>a</code> is an array object, the function <code>randomInt(x)</code> chooses a random integer between 1 and ''x'', inclusive, and <code>swapEntries(i, j)</code> swaps the ''i''th and ''j''th entries in the array. In the preceding example, <code>52</code> and <code>53</code> are magic numbers, also not clearly related to each other. It is considered better programming style to write the following: ''int'' deckSize:= 52 '''for''' i '''from''' 1 '''to''' deckSize j := i + randomInt(deckSize + 1 - i) - 1 a.swapEntries(i, j) This is preferable for several reasons: * '''Better readability'''. A programmer reading the first example might wonder, ''What does the number 52 mean here? Why 52?'' The programmer might infer the meaning after reading the code carefully, but it is not obvious.<ref name="Paul_2002_SYMBOLS"/> Magic numbers become particularly confusing when the same number is used for different purposes in one section of code. * '''Easier to maintain'''. It is easier to alter the value of the number, as it is not duplicated. Changing the value of a magic number is error-prone, because the same value is often used several times in different places within a program.<ref name="Paul_2002_SYMBOLS"/> Also, when two semantically distinct variables or numbers have the same value they may be accidentally both edited together.<ref name="Paul_2002_SYMBOLS"/> To modify the first example to shuffle a [[Tarot]] deck, which has 78 cards, a programmer might naively replace every instance of 52 in the program with 78. This would cause two problems. First, it would miss the value 53 on the second line of the example, which would cause the algorithm to fail in a subtle way. Second, it would likely replace the characters "52" everywhere, regardless of whether they refer to the deck size or to something else entirely, such as the number of weeks in a Gregorian calendar year, or more insidiously, are part of a number like "1523", all of which would introduce bugs. By contrast, changing the value of the <code>deckSize</code> variable in the second example would be a simple, one-line change. * '''Encourages documentation'''.<ref name="Paul_2002_SYMBOLS"/> The single place where the named variable is declared makes a good place to document what the value means and why it has the value it does. Having the same value in a plethora of places either leads to duplicate comments (and attendant problems when updating some but missing some) or leaves no ''one'' place where it's both natural for the author to explain the value and likely the reader shall look for an explanation. * '''Coalesces information'''. The declarations of "magic number" variables can be placed together, usually at the top of a function or file, facilitating their review and change.<ref name="Paul_2002_SYMBOLS"/> * '''Detects [[typo]]s'''. Using a variable (instead of a literal) takes advantage of a compiler's checking. Accidentally typing "62" instead of "52" would go undetected, whereas typing "<code>dekSize</code>" instead of "<code>deckSize</code>" would result in the compiler's warning that <code>dekSize</code> is undeclared. * '''Reduces typings'''. If a [[Integrated development environment|IDE]] supports [[code completion]], it will fill in most of the variable's name from the first few letters. * '''Facilitates parameterization'''. For example, to generalize the above example into a procedure that shuffles a deck of any number of cards, it would be sufficient to turn <code>deckSize</code> into a parameter of that procedure, whereas the first example would require several changes. '''function''' shuffle ('''int''' deckSize) '''for''' i '''from''' 1 '''to''' deckSize j := i + randomInt(deckSize + 1 - i) - 1 a.swapEntries(i, j) Disadvantages are: * '''Breaks locality'''. When the named constant is not defined near its use, it hurts the locality, and thus comprehensibility, of the code. Putting the 52 in a possibly distant place means that, to understand the workings of the "for" loop completely (for example to estimate the run-time of the loop), one must track down the definition and verify that it is the expected number. This is easy to avoid (by relocating the declaration) when the constant is only used in one portion of the code. When the named constant is used in disparate portions, on the other hand, the remote location is a clue to the reader that the same value appears in other places in the code, which may also be worth looking into. * '''Causes verbosity'''. The declaration of the constant adds a line. When the constant's name is longer than the value's, particularly if several such constants appear in one line, it may make it necessary to split one logical statement of the code across several lines. An increase in verbosity may be justified when there is some likelihood of confusion about the constant, or when there is a likelihood the constant may need to be changed, such as [[code reuse|reuse]] of a shuffling routine for other card games. It may equally be justified as an increase in expressiveness. * '''Performance considerations'''. It may be slower to process the expression <code>deckSize + 1</code> at run-time than the value "53". That being said, most modern compilers will use techniques like [[constant folding]] and [[loop optimization]] to resolve the addition during compilation, so there is usually no or negligible speed penalty compared to using magic numbers in code. Especially the cost of debugging and the time needed trying to understand non-explanatory code must be held against the tiny calculation cost. === Accepted uses {{anchor|Accepted limited use of magic numbers}} === {{More citations needed section|date=March 2010}} In some contexts, the use of unnamed numerical constants is generally accepted (and arguably "not magic"). While such acceptance is subjective, and often depends on individual coding habits, the following are common examples: * the use of 0 and 1 as initial or incremental values in a [[for loop]], such as {{code|2=cpp|1=for (int i = 0; i < max; i += 1)}} * the use of 2 to check whether a number is even or odd, as in <code>isEven = (x % 2 == 0)</code>, where <code>%</code> is the [[modulo]] operator * the use of simple arithmetic constants, e.g., in expressions such as <code>circumference = 2 * Math.PI * radius</code>,<ref name="MartinG25"/> or for calculating the [[discriminant]] of a [[quadratic equation]] as <code>d = b^2 − 4*a*c</code> * the use of powers of 10 to convert metric values (e.g. between grams and kilograms) or to calculate percentage and [[per mille]] values * exponents in expressions such as <code>(f(x) ** 2 + f(y) ** 2) ** 0.5</code> for <math>\sqrt{f(x)^2 + f(y)^2}</math> The constants 1 and 0 are sometimes used to represent the [[Boolean data type|Boolean]] values true and false in programming languages without a Boolean type, such as older versions of [[C (programming language)|C]]. Most modern programming languages provide a <code>boolean</code> or <code>bool</code> [[primitive type]] and so the use of 0 and 1 is ill-advised. This can be more confusing since 0 sometimes means programmatic success (when -1 means failure) and failure in other cases (when 1 means success). In C and C++, 0 represents the [[null pointer]]. As with Boolean values, the C standard library includes a macro definition <code>NULL</code> whose use is encouraged. Other languages provide a specific <code>null</code> or <code>nil</code> value and when this is the case no alternative should be used. The typed pointer constant <code>nullptr</code> has been introduced with C++11.
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)