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;

Это довольно правильный пример, где использование необработанных значений будет вводить в заблуждение.

Значение магического числа должно быть очевидно из контекста. Если это не так - назовите вещь.

Другие вопросы по тегам