Правильно ли мое понимание законности sc = s?
blockquote>Да, только некоторые детали последней части нужны.
... но любое присвоение (или ссылка?) на
blockquote>*s
илиsc
было бы незаконным.(я подозреваю, что OP означает «... или
*sc
было бы незаконно.»)Ссылка на то, на что указывает
s
илиsc
, в порядке, как вchar ch = *sc;
Попытка изменить значение
*s
или*sc
представляет собой неопределенное поведение (UB), а не «недопустимо», как в*sc = 'x';
(См. хорошую дополнительную информацию по @rici )С UB назначение может работать, оно может не работать по вторникам, код может аварийно завершиться и т. Д. C не определяет, что происходит. Код достоверности не должен пытаться это сделать.
В Вашем вопросе Вы заявили то использование volatile
будет работать, но что будет огромный хит производительности. Что относительно того, чтобы использовать volatile
переменная только во время сравнения, позволяя x
быть сохраненным в регистре?
double x; /* might have excess precision */
volatile double x_dbl; /* guaranteed to be double precision */
do {
x = /* some computation */;
x_dbl = x;
} while (x_dbl <= 0.0);
Необходимо также проверить, можно ли ускорить сравнение с самым маленьким субнормальным значением при помощи long double
явно и кэш это значение, т.е.
const long double dbl_denorm_min = static_cast<long double>(std::numeric_limits<double>::denorm_min());
и затем сравните
x < dbl_denorm_min
Я предположил бы, что достойный компилятор сделает это автоматически, но каждый никогда не знает...
Поскольку Arkadiy заявил в комментариях, явном броске ((double)x) <= 0.0
должен работать - по крайней мере, согласно стандарту.
C99:TC3, 5.2.4.2.2 §8:
За исключением присвоения и броска (которые удаляют весь дополнительный диапазон и точность), значения операций с плавающими операндами и значения, подвергающиеся обычным арифметическим преобразованиям и плавающих констант, оценены к формату, диапазон которого и точность могут быть больше, чем необходимый типом. [...]
При использовании GCC на x86 можно использовать флаги -mpc32
, -mpc64
и -mpc80
для установки точности операций с плавающей точкой к единственному, удваиваются и расширенная двойная точность.
Обязательно осуществите ту проверку абсолютное значение. Это должен быть эпсилон вокруг нуля, выше и ниже.
Ну, GCC имеет флаг, - fexcess-точность, которая вызывает проблему, которую Вы обсуждаете. Это также имеет флаг, - ffloat-хранилище, которое решает проблему, которую Вы обсуждаете.
"Не храните переменные с плавающей точкой в регистрах. Это предотвращает нежелательную избыточную точность на машинах, таких как 68000, где плавающие регистры (68881) сохраняют больше точности, чем двойное, как предполагается, имеет".
Я сомневаюсь, что решение не оказывает влияния производительности, но влияние является, вероятно, не чрезмерно дорогим. Случайный поиск с помощью Google предполагает, что стоит приблизительно 20%. На самом деле я не думаю, что существует решение, которое является и портативным и не оказывает влияния производительности, начиная с того, чтобы вынуждать микросхему не использовать избыточную точность часто собирается включить некоторую небесплатную операцию. Однако это - вероятно, решение, которое Вы хотите.
Интересно, есть ли у Вас правильный критерий остановки. Это кажется, что x <= 0 является условием исключений, но не завершающимся условием и что завершающееся условие легче удовлетворить. Возможно, должен быть оператор завершения в Вашем цикле с условием продолжения, который останавливает повторение, когда некоторый допуск встречен. Например, много алгоритма завершается, когда два последовательных повторения достаточно друг близко к другу.