user2426500
user2426500

Reputation: 39

Are 0.0 and 1.0 considered magic numbers?

I know that -1, 0, 1, and 2 are exceptions to the magic number rule. However I was wondering if the same is true for when they are floats. Do I have to initialize a final variable for them or can I just use them directly in my program.

I am using it as a percentage in a class. If the input is less than 0.0 or greater than 1.0 then I want it set the percentage automatically to zero. So if (0.0 <= input && input <= 1.0).

Thank you

Upvotes: 2

Views: 4093

Answers (4)

supercat
supercat

Reputation: 81247

Attaching a name for something creates an identity. Given the definitions

const double Moe = 2.0;
const double Joe = 2.0;
...
double Larry = Moe;
double Harry = Moe;
double Garry = Joe;

the use of symbols for Moe and Joe suggests that the default value of Larry and Harry are related to each other in a way that the default value of Garry is not. The decision of whether or not to define a name for a particular constant shouldn't depend upon the value of that constant, but rather whether it will non-coincidentally appear multiple places in the code. If one is communicating with a remote device which requires that a particular byte value be sent to it to trigger a reset, I would consider:

void ResetDevice()
{
  // The 0xF9 command is described in the REMOTE_RESET section of the
  // Frobnitz 9000 manual
  transmitByte(0xF9);
}
... elsewhere
myDevice.ResetDevice();
...
otherDevice.ResetDevice();

to be in many cases superior to

// The 0xF9 command is described in the REMOTE_RESET section of the
// Frobnitz 9000 manual
const int FrobnitzResetCode = 0xF9;
... elsewhere
myDevice.transmitByte(FrobnitzResetCode );
...
otherDevice.transmitByte(FrobnitzResetCode );

The value 0xF9 has no real meaning outside the context of resetting the Frobnitz 9000 device. Unless there is some reason why outside code should prefer to send the necessary value itself rather than calling a ResetDevice method, the constant should have no value to any code outside the method. While one could perhaps use

void ResetDevice()
{
  // The 0xF9 command is described in the REMOTE_RESET section of the
  // Frobnitz 9000 manual
  int FrobnitzResetCode = 0xF9;
  transmitByte(FrobnitzResetCode);
}

there's really not much point to defining a name for something which is in such a narrow context.

The only thing "special" about values like 0 and 1 is that used significantly more often than other constants like e.g. 23 in cases where they have no domain-specific identity outside the context where they are used. If one is using a function which requires that the first parameter indicates the number of additional parameters (somewhat common in C) it's better to say:

output_multiple_strings(4, "Bob", Joe, Larry, "Fred"); // There are 4 arguments
...
output_multiple_strings(4, "George", Fred, "James", Lucy);  // There are 4 arguments

than #define NUMBER_OF_STRINGS 4 // There are 4 arguments

output_multiple_strings(NUMBER_OF_STRINGS, "Bob", Joe, Larry, "Fred");
...
output_multiple_strings(NUMBER_OF_STRINGS, "George", Fred, "James", Lucy);

The latter statement implies a stronger connection between the value passed to the first method and the value passed to the second, than exists between the value passed to the first method and anything else in that method call. Among other things, if one of the calls needs to be changed to pass 5 arguments, it would be unclear in the second code sample what should be changed to allow that. By contrast, in the former sample, the constant "4" should be changed to "5".

Upvotes: 0

Dan Bechard
Dan Bechard

Reputation: 5291

It really depends on the context. The whole point of avoiding magic numbers is to maintain the readability of your code. Use your best judgement, or provide us with some context so that we may use ours.

Magic numbers are [u]nique values with unexplained meaning or multiple occurrences which could (preferably) be replaced with named constants.

http://en.wikipedia.org/wiki/Magic_number_(programming)

Edit: When to document code with variables names vs. when to just use a number is a hotly debated topic. My opinion is that of the author of the Wiki article linked above: if the meaning is not immediately obvious and it occurs multiple times in your code, use a named constant. If it only occurs once, just comment the code.

If you are interested in other people's (strongly biased) opinions, read What is self-documenting code and can it replace well documented code?

Upvotes: 2

Sebastian Redl
Sebastian Redl

Reputation: 72054

Those numbers aren't really exceptions to the magic number rule. The common sense rule (as far as there is "one" rule), when it isn't simplified to the level of dogma, is basically, "Don't use numbers in a context that doesn't make their meaning obvious." It just so happens that these four numbers are very commonly used in obvious contexts. That doesn't mean they're the only numbers where this applies, e.g. if I have:

long kilometersToMeters(int km) { return km * 1000L; }

there is really no point in naming the number: it's obvious from the tiny context that it's a conversion factor. On the other hand, if I do this in some low-level code:

sendCommandToDevice(1);

it's still wrong, because that should be a constant kResetCommand = 1 or something like it.

So whether 0.0 and 1.0 should be replaced by a constant completely depends on the context.

Upvotes: 3

Sergey K.
Sergey K.

Reputation: 25396

Usually, every rule has exceptions (and this one too). It is a matter of style to use some mnemonic names for these constants.

For example:

int Rows = 2;
int Cols = 2;

Is a pretty valid example where usage of raw values will be misleading.

The meaning of the magic number should be obvious from the context. If it is not - give the thing a name.

Upvotes: 0

Related Questions