0.0 и 1.0 считаются магическими числами?
Я знаю это -1
, 0
, 1
, а также 2
являются исключениями из правила магического числа. Однако мне было интересно, верно ли то же самое для случаев, когда они являются поплавками. Должен ли я инициализировать конечную переменную для них или я могу просто использовать их непосредственно в моей программе.
Я использую это как процент в классе. Если входное значение меньше 0,0 или больше 1,0, я хочу, чтобы процент автоматически устанавливался на ноль. Так что, если (0,0 <= вход && вход <= 1,0).
Спасибо
4 ответа
Это действительно зависит от контекста. Весь смысл избегать магических чисел состоит в том, чтобы поддерживать читабельность вашего кода. Прислушайтесь к своему усмотрению или предоставьте нам какой-то контекст, чтобы мы могли использовать наш.
Магические числа [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)
Редактировать: когда задокументировать код с именами переменных, а когда просто использовать число, это горячо обсуждаемая тема. Мое мнение таково, как и у автора статьи Wiki, ссылки на которую приведены выше: если значение не сразу очевидно и оно встречается в вашем коде несколько раз, используйте именованную константу. Если это происходит только один раз, просто закомментируйте код.
Если вас интересуют мнения других (сильно предвзятых), прочитайте Что такое самодокументированный код и может ли он заменить хорошо документированный код?
Эти цифры не являются исключениями из правила магического числа. Правило здравого смысла (поскольку существует правило "одного"), когда оно не упрощено до уровня догмы, в основном гласит: "Не используйте числа в контексте, который не делает их значение очевидным". Просто так получилось, что эти четыре числа очень часто используются в очевидных контекстах. Это не значит, что это единственные цифры, к которым это относится, например, если у меня есть:
long kilometersToMeters(int km) { return km * 1000L; }
на самом деле нет никакого смысла называть число: из крошечного контекста очевидно, что это коэффициент пересчета. С другой стороны, если я сделаю это в каком-то низкоуровневом коде:
sendCommandToDevice(1);
это все равно неправильно, потому что это должно быть постоянным kResetCommand = 1
или что-то вроде этого.
Так ли 0.0
а также 1.0
должен быть заменен константой полностью зависит от контекста.
Прикрепление имени для чего-либо создает идентичность. Учитывая определения
const double Moe = 2.0;
const double Joe = 2.0;
...
double Larry = Moe;
double Harry = Moe;
double Garry = Joe;
использование символов для Мо и Джо предполагает, что значения по умолчанию Ларри и Гарри связаны друг с другом так, как это не имеет значение по умолчанию Гарри. Решение о том, следует ли определять имя для конкретной константы, должно зависеть не от значения этой константы, а от того, будет ли оно случайно совпадать с несколькими местами в коде. Если кто-то связывается с удаленным устройством, которое требует, чтобы ему было отправлено определенное значение байта для запуска сброса, я бы рассмотрел:
void ResetDevice()
{
// The 0xF9 command is described in the REMOTE_RESET section of the
// Frobnitz 9000 manual
transmitByte(0xF9);
}
... elsewhere
myDevice.ResetDevice();
...
otherDevice.ResetDevice();
во многих случаях превосходить
// 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 );
Значение 0xF9 не имеет реального значения вне контекста сброса устройства Frobnitz 9000. Если не существует какой-либо причины, по которой внешний код должен предпочитать отправлять необходимое значение самостоятельно, а не вызывать метод ResetDevice, константа не должна иметь значения для любого кода вне метода. Хотя можно было бы использовать
void ResetDevice()
{
// The 0xF9 command is described in the REMOTE_RESET section of the
// Frobnitz 9000 manual
int FrobnitzResetCode = 0xF9;
transmitByte(FrobnitzResetCode);
}
на самом деле нет особого смысла определять имя для чего-то, что находится в таком узком контексте.
Единственное, что "особенное" в значениях, таких как 0 и 1, это то, что они используются значительно чаще, чем другие константы, например, 23, в тех случаях, когда они не имеют доменных имен вне контекста, в котором они используются. Если кто-то использует функцию, которая требует, чтобы первый параметр указывал количество дополнительных параметров (что довольно часто встречается в C), лучше сказать:
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 // Есть 4 аргумента
output_multiple_strings(NUMBER_OF_STRINGS, "Bob", Joe, Larry, "Fred");
...
output_multiple_strings(NUMBER_OF_STRINGS, "George", Fred, "James", Lucy);
Последнее утверждение подразумевает более сильную связь между значением, переданным первому методу, и значением, переданным второму, чем существует между значением, переданным первому методу, и всем остальным в этом вызове метода. Среди прочего, если один из вызовов нужно изменить, чтобы передать 5 аргументов, во втором примере кода неясно, что следует изменить, чтобы это разрешить. Напротив, в первом примере константа "4" должна быть изменена на "5".
Обычно каждое правило имеет исключения (и это тоже). Это вопрос стиля - использовать несколько мнемонических имен для этих констант.
Например:
int Rows = 2;
int Cols = 2;
Это довольно правильный пример, где использование необработанных значений будет вводить в заблуждение.
Значение магического числа должно быть очевидно из контекста. Если это не так - назовите вещь.