Are MAGIC numbers always bad?

Y

youpak2000

Are MAGIC numbers always bad?

Using magic numbers (constant numbers) in programs are generally
considered a bad programming practice, and it's recommended that to
define constants in single, visible place in a header file. My question
is that is there any situation where using magic numbers is not
necessarily a bad thing? lets say that we want to initialize some
private variables in a class using some constant default numbers, can
we initialize them directly using magic numbers? should we still define
those constants in a header file? If we define them in a header file,
they become available to the clients of our class, which we may not
want; can we put them in the cpp file?

I'd appreciate your comments.

John
 
D

davidrubin

You can always define them in the implementation file as enumerated
values, or in an unnamed namespace.
 
I

Ian Collins

Are MAGIC numbers always bad?

Using magic numbers (constant numbers) in programs are generally
considered a bad programming practice, and it's recommended that to
define constants in single, visible place in a header file. My question
is that is there any situation where using magic numbers is not
necessarily a bad thing? lets say that we want to initialize some
private variables in a class using some constant default numbers, can
we initialize them directly using magic numbers?

Well you have to assign a value to a constant somewhere, so that
constant replaces the magic number.

should we still define
those constants in a header file?

You could.

If we define them in a header file,
they become available to the clients of our class, which we may not
want; can we put them in the cpp file?
If you are referring to static member variables, yes. But you could
also make them private.
 
C

Clem.Dickey

Header files need not be published; you can use private header files.

Magic numbers are always bad. But sometimes the alternatives are worse.
It is generally better to use "static const" to members of an "enum,"
except where you are really designing an enumeration. Any data type can
be a static const, but only integral types can be used in an enum.

Someday I will design my own programming language. The only constants
will be zero, one, e, and two pi. :)
 
G

Gabriel

Are MAGIC numbers always bad?

Using magic numbers (constant numbers) in programs are generally
considered a bad programming practice, and it's recommended that to
define constants in single, visible place in a header file. My question
is that is there any situation where using magic numbers is not
necessarily a bad thing? lets say that we want to initialize some
private variables in a class using some constant default numbers, can
we initialize them directly using magic numbers? should we still define
those constants in a header file? If we define them in a header file,
they become available to the clients of our class, which we may not
want; can we put them in the cpp file?

I'd appreciate your comments.

John
In the end, they need to go somewhere. Think about where it would make
sense. I often get headaches about this. If the user need to see/change
them, they might be well placed in a config file. If the client of a
class/API needs to see them, they might be well placed in a header file.
They might be well placed as static const class members. Put them
somewhere where you will find them again. E.g. if they are an
implementation detail of a function, put them in a visible place: Do not
bury them somewhere in some line of code. Rather, put a local const
variable at the beginning of the function. That shall remind you that a
magic number exists and shall allow you to find it again.

There is something that needs to be avoided, because it can desintegrate
your hardware, steal your lunch and can cause spontaneous human
combustion: Do never make magic numbers depend on one another. Do never
put them in several times. If you have a fixed blocksize in image
processing of 8, thats fine. Put the 8 somewhere. But only one 8. If two
(or more) 8s appear throughout your code, your doomed. If someday your
student assistant changes your code for your, he will miss exactly one
8. This will produce a bug that will not reveal itself until your are in
the last weeks of writing your PhD thesis and suddenly find out that all
your data is incorrect. I have seen such things.

Do never do arithmetics in your head. If
const long blocksize = 8;
then say
const long pixels_per_block = blocksize * blocksize;
.. Never say
const long pixels_per_block = 64.
unless your do freeclimbing without safety for a hobby.

As for default values of function parameters, put them in the header.
The client needs to know the default behaviour.

Hope I could help you,
Gabriel
 
D

Daniel T.

Are MAGIC numbers always bad?

That depends... Let's say you use the number '5' to represent some
logical concept and use it in several different places... Then later you
use the number '5' to represent a different logical concept... Then
later one of the logical concept's need to be changed to a different
value. How long is it going to take for you to determine which '5's
belong to which concept? Chances are, longer than it would have taken
for you to make a const int, and name the concept.

Using magic numbers (constant numbers) in programs are generally
considered a bad programming practice, and it's recommended that to
define constants in single, visible place in a header file.

I don't think that is quite correct. It is recommended to define a
constant in a single place, but it doesn't have to go in the header, it
should be put in the most logical place.
lets say that we want to initialize some
private variables in a class using some constant default numbers, can
we initialize them directly using magic numbers? should we still define
those constants in a header file? If we define them in a header file,
they become available to the clients of our class, which we may not
want; can we put them in the cpp file?

In that case, you should define the number inside the class. I'm sure
you have seen something like this before:

class Foo {
enum { a, b, c };
//...
};

Now 'a', 'b', and 'c' exist inside Foo and can only be accessed by Foo
objects.

Another idea (a better one IMO) is to define the magic numbers in the
Foo.cpp file, that way if they do change, you won't have to recompile
all of Foo's dependents.
 
B

Bob Hairgrove

Are MAGIC numbers always bad?

Yes, I think they are always bad.
Using magic numbers (constant numbers) in programs are generally
considered a bad programming practice, and it's recommended that to
define constants in single, visible place in a header file. My question
is that is there any situation where using magic numbers is not
necessarily a bad thing? lets say that we want to initialize some
private variables in a class using some constant default numbers, can
we initialize them directly using magic numbers? should we still define
those constants in a header file? If we define them in a header file,
they become available to the clients of our class, which we may not
want; can we put them in the cpp file?

I'd appreciate your comments.

John

In addition to all the other good remarks given by others in this
thread, using named constants, even within a source file to initialize
static variables, helps make your code self-documenting. It also helps
speed up the coding process with modern IDE's which let you pick a
constant or variable name out of a list. Anything that helps make your
code self-documenting is a GOOD THING.
 
I

icanoop

Are MAGIC numbers always bad?
Yes, I think they are always bad.

I am skeptical of most absolute rules like that. They aren't always
bad, but when you can make a reasonable argument against using a magic
number, don't use one. In the end you have to use your best judgment as
a programmer.

Initialization lists for constructors are one place where I often just
use literals instead of defining a const variable for each default
value.
 
J

JustBoo

Are MAGIC numbers always bad?

From Dr. Stroustrup's Website
http://public.research.att.com/~bs/bs_faq2.html

<quote>
How do I define an in-class constant?

If you want a constant that you can use in a constant expression, say
as an array bound, you have two choices:

class X {
static const int c1 = 7;
enum { c2 = 19 };

char v1[c1];
char v2[c2];

// ...
};

At first glance, the declaration of c1 seems cleaner, but note that to
use that in-class initialization syntax, the constant must be a static
const of integral or enumeration type initialized by a constant
expression. That's quite restrictive:

class Y {
const int c3 = 7; // error: not static
static int c4 = 7; // error: not const
static const float c5 = 7; // error not integral
};

//////////////////////
I tend to use the "enum trick" because it's portable and doesn't tempt
me to use non-standard extensions of the in-class initialization
syntax.
////////////////////
</quote>

Once I read that the good Doctor use's the same "enum trick" that I
use, I now sleep very well at night without headaches. :)
 
P

Phlip

youpak2000 said:
Are MAGIC numbers always bad?

In a test case (such as a unit test or developer test) you typically write
things like...

CHECK_EQUAL(42, getAnswerToTheGreatQuestionOfLife());

When such magic constants get used in one small place, naming them adds no
value. (The name here would be 'int answerToTheGreatQuestionOfLife = 42',
which is redundant.)

If such a constant appears in more than one place, with the same meaning,
Using magic numbers (constant numbers) in programs are generally
considered a bad programming practice, and it's recommended that to
define constants in single, visible place in a header file.

Why a header file? As much as possible should be private to .cpp files.
My question
is that is there any situation where using magic numbers is not
necessarily a bad thing?

Test cases follow style guidelines subtly different from production code.
lets say that we want to initialize some
private variables in a class using some constant default numbers, can
we initialize them directly using magic numbers? should we still define
those constants in a header file? If we define them in a header file,
they become available to the clients of our class, which we may not
want; can we put them in the cpp file?

Those situations must self-document.
 
O

osmium

I am skeptical of most absolute rules like that. They aren't always
bad, but when you can make a reasonable argument against using a magic
number, don't use one. In the end you have to use your best judgment as
a programmer.

I am so glad, since I started working on my Soduku solver, that I repaced 9
with this:

const int number_of_non_zero_digits_in_the_arabic_number_system = 9;

Things are so much clearer now. Thanks for the tip, guys.
 
R

Richard Herring

osmium said:
I am so glad, since I started working on my Soduku solver, that I repaced 9
with this:

const int number_of_non_zero_digits_in_the_arabic_number_system = 9;

Things are so much clearer now. Thanks for the tip, guys.
Thanks for a neat illustration of two serious programming errors:
premature specialisation and thinking at the wrong level of abstraction.

Hint: some Sudoku variants use 12 numbers or various numbers of letters.

If you'd called it something like number_of_tokens you wouldn't be so
confused.
 
O

osmium

Richard Herring said:
Thanks for a neat illustration of two serious programming errors:
premature specialisation and thinking at the wrong level of abstraction.

Hint: some Sudoku variants use 12 numbers or various numbers of letters.

So what's your point? Bingo is different from tic-tac-toe. Is the proper
"level of abstraction" games that have something to do with paper? Or what?
The properties of the number 9 are built into the thought processes behind
the program. Is a person who writes a chess program supposed to be keeping
"go" in the back of his mind so he can "enhance" his primitive little
program?
 
W

W Marsh

So what's your point? Bingo is different from tic-tac-toe. Is the proper
"level of abstraction" games that have something to do with paper? Or what?
The properties of the number 9 are built into the thought processes behind
the program. Is a person who writes a chess program supposed to be keeping
"go" in the back of his mind so he can "enhance" his primitive little
program?

Are you broken? 12 number Sudoku isn't to 9 number Sudoku what chess
is to "go".
 
B

Bob Hairgrove

Are you broken? 12 number Sudoku isn't to 9 number Sudoku what chess
is to "go".

And what about hexadecimal Sudoku? This should be possible to
implement using the same solver algorithm. Why hard-wire the number 9
into the program?
 
R

roberts.noah

osmium said:
So what's your point? Bingo is different from tic-tac-toe. Is the proper
"level of abstraction" games that have something to do with paper? Or what?
The properties of the number 9 are built into the thought processes behind
the program. Is a person who writes a chess program supposed to be keeping
"go" in the back of his mind so he can "enhance" his primitive little
program?

Interesting question. Go is a very different game from chess so there
probably isn't much that could be shared. On the other hand perhapse
you could be using the same board abstraction in both. Yet again you
could have variants of chess, such as xiangqi, to which the size of the
board is different, some of the pieces are different, but the semantics
of the game are quite similar.

So, depending on a person's goals they may very well want to keep magic
numbers out of something even as "obviously specialized" as a
particular board size.
 
B

BigBrian

Why hard-wire the number 9 into the program?

This may or may not be a vaild reason, but...

One reason is that it can make debugging easier. Lets say you install
a debug version of your executable on your target system and you're
stepping through the code with your debugger. And lets say in the
debugger you determine that x=5, but everywhere in the code you use
constants you have to go back to your source and find which constant is
5 so you can study what's going on in the debugger. That is, if you
use magic numbers, everything is visible at run time in the debugger (
assuming that you build a debug version, at least this is true on my
platform ). But if you use a bunch of constants ( or #define's ) then
I find myself constantly having to go back to my development system and
grep through the source to find which constant is defined as 5 ( for
example ).
 
W

W Marsh

And what about hexadecimal Sudoku? This should be possible to
implement using the same solver algorithm. Why hard-wire the number 9
into the program?

And that, osmium, is a prime reason for using named constants over
magic numbers.As well as saving the effort of having to change all
occurrences of the number 9 (making sure you're changing the correct
9s), improving readability and "debuggability", it encourages the
programmer to design in a way that encourages extensibility and
sensible abstraction.
 
P

Phlip

W said:
And that, osmium, is a prime reason for using named constants over
magic numbers.As well as saving the effort of having to change all
occurrences of the number 9 (making sure you're changing the correct
9s), improving readability and "debuggability", it encourages the
programmer to design in a way that encourages extensibility and
sensible abstraction.

When refactoring a Roman Numeral formatter, I discovered a principle. Let's
call it "make the right number magic".

In my formatter, the numbers 4 and 6 represented premature generalization.
They were really 5-1 and 5+1.

In Ruby, they eventually factored out into this table:

Symbols = { 1=>'I', 5=>'V', 10=>'X' }

The point is not that I said One=1 somewhere, triumphantly naming
everything. The point is I carefully deconstructed the arithmetic to locate
the narrowest set of symbols, and then put them in a table. So 1, 5, 10 etc.
appear in the program once and only once.

http://www.xpsd.org/cgi-bin/wiki?TestDrivenDevelopmentTutorialRomanNumerals
 
R

Richard Herring

osmium said:
So what's your point? Bingo is different from tic-tac-toe.

Yes. What's _your_ point? That's hardly analogous to the difference
between 9x9 and 25x25 Sudoku.
Is the proper
"level of abstraction" games that have something to do with paper? Or what?

<sigh> The description at the correct level of abstraction would be, as
my post suggested, the number of tokens to be used, or better still the
numbers describing the grid layout. The fact that the number of tokens
happens to be one less than the base of a certain positional number
system is coincidental.
The properties of the number 9 are built into the thought processes behind
the program.

Except that they are not, as witness the variants that have other
numbers:
http://en.wikipedia.org/wiki/Sudoku

That's your premature specialisation.
Is a person who writes a chess program supposed to be keeping
"go" in the back of his mind so he can "enhance" his primitive little
program?
No, but he might want to be aware that there are Oriental chess variants
where, for example, the pawns start in the third rank.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top