fpu — C / C ++ NaN или логическое значение?

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

Одним из них является добавление логического флага, true когда кэшированное значение хорошо, когда оно используется, установите его в false, и когда флаг ложен, пересчитать и пополнить.

Второй вариант более интересен — я мог бы сохранить его как двойное значение и использовать NaN как недействительный / нужно повторно вычислить флаг.

double get() const {
if (!isnan(_value)) {
double t = _value;
_value = std::numeric_limits<double>::quiet_NaN;
return t;
}
}

Есть ли возражения против этого? Есть мысли по эффективности?

6

Решение

используйте логическое значение, в противном случае вы столкнетесь с некоторыми интересными проблемами / ошибками в будущем, когда ваш вычисленный дубль фактически окажется NaN (из-за расчета). Если вы полагаетесь на NaN в качестве сигнала «Я использовал это значение», то вы не сможете различить в случае «действительного» неиспользованного NaN.

Не говоря уже о том, что такая перегрузка семантики заставит будущего читателя вашего кода (даже самого себя через несколько месяцев) почесать голову в попытке расшифровать это умное использование. 😉

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

Так далеко как эффективность выходит — я бы порекомендовал вам сначала измерить и только потом беспокоиться об оптимизации. Держу пари, что после запуска тестов вы обнаружите, что разница в скорости значительно ниже шума производительности, вызванного колебаниями температуры процессора.

6

Другие решения

Я сомневаюсь, что будет разница с эффективностью, но код с логическим флагом будет более читабельным:

double get() const {
if (!_cached)
_value = recalculate();
_cached = !_cached;
return _value;
}
3

Я думаю, что стоит отметить, что nan может быть более эффективным решением, большое преимущество в том, что вы используете меньше памяти, чем с флагом (чья служебная нагрузка, вероятно, будет больше, чем 1 байт на двойной из-за выравнивания). Это означает, что, скорее всего, будет быстрее, если вам нужно будет читать много памяти.

Еще одна вещь, на которую следует обратить внимание, это то, что IEEE nans может иметь разные значения. Их показателями должны быть все единицы, но мантисса может быть чем угодно, кроме всех нулей. Это означает, что вы можете использовать «специальный» nan, чтобы отличать его от созданных в результате вычислений, или даже использовать различные виды nans, если вам нужен флаг с более чем двумя состояниями.

0
По вопросам рекламы [email protected]