Действительно ли это - хорошая идея использовать NaN с плавающей точкой IEEE754 для значений, которые не установлены?

Дело не в том, что сами синглеты плохие, а в шаблоне GoF. Единственным действительным аргументом, который является действительным, является то, что шаблон проектирования GoF не подходит для тестирования, особенно если тесты выполняются параллельно.

Использование одного экземпляра класса является допустимой конструкцией, если в коде применяются следующие средства:

  1. Убедитесь, что класс, который будет использоваться в качестве одиночного, реализует интерфейс. Это позволяет реализовать заглушки или макеты с использованием одного и того же интерфейса

  2. Убедитесь, что Singleton является поточно-ориентированным. Это данность.

  3. Синглтон должен быть простым по своей природе и не слишком сложным.

  4. Во время выполнения приложения, в котором необходимо передать синглеты данному объекту, используйте фабрику классов, которая создает этот объект, и фабрика классов передает экземпляр синглтона нужному классу.

  5. Во время тестирования и для обеспечения детерминированного поведения создайте одноэлементный класс в качестве отдельного экземпляра в качестве самого фактического класса или заглушки / макета, который реализует его поведение, и передайте его как есть классу, который требует его. Не используйте фактор класса, который создает тестируемый объект, который нуждается во синглтоне во время теста, так как он пройдет единственный глобальный экземпляр этого объекта, что противоречит цели.

Мы использовали Singletons в наших решениях с большим успехом, которые можно тестировать, обеспечивая детерминированное поведение в параллельных потоках тестовых прогонов.

13
задан AakashM 24 June 2009 в 07:57
поделиться

9 ответов

Только что заметил этот вопрос.

Это одно из вариантов использования NaN, которое имеет в виду комитет IEEE 754 (я был членом комитета). Правила распространения NaN в арифметике делают это очень привлекательным, потому что, если у вас есть результат в результате длинной последовательности вычислений, включающих некоторые инициализированные данные, вы не ошибетесь, приняв его за действительный результат. Это также может значительно упростить отслеживание ваших вычислений, чтобы найти, где вы используете инициализированные данные.

Тем не менее, есть несколько подводных камней, которые находятся вне контроля комитета 754: как отмечали другие, не все оборудование поддерживает значения NaN на скорости, что может привести к снижению производительности. К счастью, нечасто выполняется много операций с инициализированными данными в условиях, критичных к производительности.

11
ответ дан 1 December 2019 в 21:53
поделиться

NaN - разумный выбор для предложения «без значения» (например, язык программирования D использует их для неинициализированных значений), но поскольку любые сравнения с их участием будут ложными, вы можете получить несколько сюрпризов:

  • if (result == DEFAULT_VALUE) не будет работать должным образом, если DEFAULT_VALUE равно NaN, как упоминал Джон.

  • Они также могут вызвать проблемы с проверкой диапазона если вы не будете осторожны. Рассмотрим функцию:

bool isOutsideRange(double x, double minValue, double maxValue)
{
    return x < minValue || x > maxValue;
}

Если x равен NaN, эта функция неправильно сообщит, что x находится между minValue и maxValue.

Если вы просто хотите, чтобы пользователи проверяли магическое значение, я бы рекомендовал вместо этого положительную или отрицательную бесконечность NaN, поскольку он не имеет таких ловушек. Используйте NaN, если хотите, чтобы его свойство, что любые операции с NaN приводят к NaN: it '

[Edit: мне сначала удалось ввести выше «любые сравнения, в которых они участвуют, будут верными», что не то, что я имел в виду, и это неверно, они все ложны, кроме NaN! = NaN, что верно]

4
ответ дан 1 December 2019 в 21:53
поделиться

Я думаю, что это вообще плохая идея. Следует иметь в виду, что большинство процессоров обрабатывают Nan намного медленнее, чем "обычный" float. И трудно гарантировать, что у вас никогда не будет Nan в обычных настройках. Мой опыт работы с числовыми вычислениями показывает, что они часто доставляют больше проблем, чем они того стоят.

Правильное решение - избегать кодирования «отсутствия значения» в float, а сигнализировать об этом другим способом. Однако это не всегда практично, в зависимости от вашей кодовой базы.

3
ответ дан 1 December 2019 в 21:53
поделиться

Я использовал NaN в подобных ситуациях только потому, что из этого: обычное значение инициализации по умолчанию 0 также является допустимым значением. NaN пока работают нормально.

Кстати, хороший вопрос, почему значение инициализации по умолчанию обычно (например, в примитивных типах Java) 0, а не NaN. Разве это не может быть 42 или что-то в этом роде? Интересно, в чем смысл нулей.

3
ответ дан 1 December 2019 в 21:53
поделиться

Будьте осторожны с NaN ... они могут распространяться как лесной пожар, если вы не будете осторожны.

Они являются вполне допустимым значением для чисел с плавающей запятой, но любые присваивания с их участием также будут равны NaN, поэтому они распространяются через ваш код. Это неплохо в качестве инструмента отладки, если вы его поймаете, однако это также может быть настоящей неприятностью, если вы собираетесь что-то выпустить, и где-то есть крайний случай.

D использует это как обоснование для назначения числа с плавающей запятой NaN по умолчанию . (С чем я не уверен, что согласен.)

2
ответ дан 1 December 2019 в 21:53
поделиться

Мне кажется, что это немного взломано, но по крайней мере все остальные числа, которые вы выполняете с этим значением NaN, дают NaN как результат - когда вы видите NaN в отчете об ошибке, по крайней мере, вы знаете, за какой ошибкой вы охотитесь.

1
ответ дан 1 December 2019 в 21:53
поделиться

Если ваша основная потребность состоит в том, чтобы иметь значение с плавающей запятой, которое не представляет никакого числа, которое могло бы быть получено от устройства, и , если устройство гарантирует это никогда не вернет NaN, тогда это кажется мне разумным.

Просто помните, что в зависимости от вашей среды вам, вероятно, понадобится особый способ определения NaN (не используйте просто if (x == float.NaN) или другой аналог.)

0
ответ дан 1 December 2019 в 21:53
поделиться

Using NaN as a default value is reasonable.

Note that some expressions, such as (0.0 / 0.0), return NaN.

0
ответ дан 1 December 2019 в 21:53
поделиться

Мне кажется, это хорошее применение для nans. Хотел бы я подумать об этом ...

Конечно, они должны распространяться как вирус, в этом суть.

Думаю, я бы использовал nan вместо одной из бесконечностей. Было бы неплохо использовать сигнальный nan и заставить его вызывать событие при первом использовании, но к тому времени уже слишком поздно, он должен замолчать при первом использовании.

0
ответ дан 1 December 2019 в 21:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: