Сделать C плавающей запятой букв плавать (а не удваивать)
Хорошо известно, что в C литералы с плавающей запятой (например, 1.23
) имеют тип double
. Как следствие, любой расчет, который их включает, увеличивается до двух.
Я работаю над встроенной системой реального времени, которая имеет модуль с плавающей запятой, который поддерживает только одинарные значения точности (float
). Все мои переменные float
, и этой точности достаточно. Мне не нужно (и не могу позволить себе) double
вообще. Но каждый раз что-то вроде
if (x < 2.5) ...
происходит бедствие: замедление может быть до двух порядков. Конечно, прямой ответ - написать
if (x < 2.5f) ...
но это так легко пропустить (и его трудно обнаружить до слишком позднего времени), особенно когда значение "конфигурации" #define
'd в отдельном файле менее дисциплинированным (или только новым) разработчиком.
Итак, есть ли способ заставить компилятор обрабатывать все (с плавающей запятой) литералы как float, как будто с суффиксом f
? Даже если это противоречит спецификациям, мне все равно. Или любые другие решения? Кстати, компилятор gcc.
Ответы
Ответ 1
-fsingle-precision-constant
может использоваться флаг. Это приводит к тому, что константы с плавающей запятой загружаются с одной точностью, даже если это неточно.
Примечание. Это также будет использовать константы одиночной точности в операциях с переменными с двойной точностью.
Ответ 2
Вместо этого используйте предупреждения: -Wdouble-promotion
предупреждает о неявной поплавке для двойной рекламы, как в вашем примере. -Wfloat-conversion
будет предупреждать о случаях, когда вы все равно можете назначать удвоения для плавания.
Это лучшее решение, чем просто принудительное двойное значение до ближайшего значения float. Ваш код с плавающей точкой по-прежнему совместим, и вы не получите никаких неприятных сюрпризов, если двойное значение имеет положительное значение, скажем, меньше FLT_DENORM_MIN
(при условии IEEE-754) или больше, чем FLT_MAX
.
Ответ 3
Вы можете использовать определенные константы в (float)
везде, где они используются, оптимизатор должен выполнять свою работу. Это портативное решение.
#define LIMIT 2.5
if (x < (float)LIMIT) ...
Ответ 4
Можно также использовать -Wunsuffixed-float-constants
, возможно, в сочетании с некоторыми другими параметрами в принятом ответе выше. Тем не менее, это, вероятно, не поймает нефиксированные константы в системных заголовках. Нужно было бы использовать -Wsystem-headers
чтобы поймать их тоже. Может генерировать много предупреждений...