2016-10-27 2 views
2

Что было бы правильным/рекомендуемым способом сообщить компилятору C++ «только предупредить меня о конверсиях с плавающей запятой, о которых я не знаю»?Корректное преобразование с плавающей запятой в C++

В C я бы включил предупреждения, связанные с преобразованиями с плавающей запятой, а затем я использовал бы явные приведения в стиле C, чтобы отключить предупреждения, связанные с контролируемыми преобразованиями.

Например, вычислительное a*a*a - b*b весьма склонны к переполнению в одинарной точности с плавающей точкой, так что вы могли бы пожелать, чтобы вычислить его в двойной точности и идти только с одинарной точностью позже:

double a = 443620.52; 
double b = 874003.01; 
float c = (float)(a*a*a - b*b); 

выше C-стиль явно cast заставляет замолчать предупреждение компилятора об конверсии от double до float.

Чтение C++ документация о слепков, я к выводу, что правильный способ сделать это в C++ будет выглядеть следующим образом:

double a = 443620.52; 
double b = 874003.01; 
float c = static_cast<float>(a*a*a - b*b); 

Но, действительно ли это правильный способ сделать это в C++?

Я понимаю обоснование синтаксиса static_castugly on purpose, так что вы избегаете отливок, если это возможно.

Да, я могу опустить явное приведение в поплавок. Но тогда мне нужно отключить предупреждения компилятора, которые говорят мне о прецизионной потере (или, иначе, я бы получил ряд неуместных предупреждений, которые затруднили бы уведомление действительно релевантных предупреждений). И если я отключу предупреждения компилятора, связанные с fp, я бы потерял возможность быть предупрежденным, когда я ошибочно теряю точность в других местах кода.

Итак, каков правильный подход для конверсий с плавающей запятой в C++?

ответ

1

Да

float c = static_cast<float>(a*a*a - b*b); 

правильный способ явного литья плавать в C++. Вы также можете сделать:

float c = (float)(a*a*a - b*b); 

, но с использованием «C-стиль» слепок, как это плохой стиль, потому что static_cast будет скрывать, а меньше ошибок, чем C-стиле.

С другой стороны, если вы делаете это много, вы можете определить функцию:

inline float flt(double d){return static_cast<float>(d);} 

, а затем вы можете написать:

float c = flt(a*a*a - b*b); 

который является еще более компактным, чем оригинальный C (и будет оптимизирован ни к чему).

+1

Но отливки от 'double' до' float' часто встречаются при программировании с плавающей запятой. «Static_cast» «уродство» было бы незаслуженным наказанием ИМХО, учитывая, что актерский состав не только законен, но и необходим, и невозможно избежать того, насколько хорош стиль кодирования. – cesss

+0

Большое спасибо, ваш совет относительно определения функции полностью удовлетворяет мои потребности, и это чистый стиль программирования на C++. – cesss

+0

Объяснение приза голосования будет приветствоваться. –

0

Насколько мне известно, существует три различных способа избежать предупреждения:

  1. C-стиль литья
  2. static_cast
  3. Конструктор стиле литой (например,float c = float(a*a*a-b*b))

В примере кода ниже, c1, c2 и c3 избежать предупреждения:

int main() 
{ 
    double a = 443620.52; 
    double b = 874003.01; 

    // These three versions avoid the conversion warnings: 
    float c1 = (float)(a*a*a - b*b); 
    float c2 = static_cast<float>(a*a*a - b*b); 
    float c3 = float(a*a*a - b*b); 

    // Only these two give conversion warnings: 
    float c4(a*a*a - b*b); 
    float c5 = a*a*a - b*b; 

    (void)c1; // Just to avoid unused-variable warnings 
    (void)c2; 
    (void)c3; 
    (void)c4; 
    (void)c5; 
} 

Только c4 и c5 триггерные предупреждение. Check the live demo для просмотра результатов.

Смежные вопросы