В случае преобразования с плавающей точкой в целое, я думаю, что лучше писать и использовать функции, а не типы; сами функции могут использовать типы типов, но я бы посчитал, что вызов такой функции, как int_round_mid_up(x)
, лучше, чем (int)(x+0.5)
, тем более что функцию можно легко написать один раз для правильной обработки положительных и отрицательных чисел, включая предательский 0,499999999999999944 [который при добавлении к 0,5 дает 1,0], в то время как выражение на основе типов (int)(x+0.5)
будет неправильно округлять -2,4 до -1. ИМХО, для языка не существует хорошего способа определения типов типов с плавающей точкой в целое (некоторые используют различные формы округления, некоторые усечения, а некоторые могут использовать полы; так как нет ясного «лучшего» способа сделать преобразование, было бы лучше, если бы программист определил, что нужно, а не язык выбирал метод), и поэтому программисты должны избегать их вне очень узкого контекста.
Что касается преобразований между целочисленными типами, предупреждения о сужающихся преобразованиях, как правило, являются хорошими и должны быть разрешены глобально, но локально подавлены с помощью явных типов типов. Для большинства видов числовой работы преобразования из double
в float
обычно не должны генерировать предупреждения (или, что еще хуже, ошибки), хотя, к сожалению, не все языки или компиляторы позволяют подавлять эти предупреждения независимо от предупреждений для других типов.
Категория преобразований, которая должна быть настроена на генерацию предупреждений для компиляторов, которые ее поддерживают (хотя, увы, многие этого не делают), - это преобразование из узкого выражения, которое может привести к усеченному результату, к типу, который мог бы содержать результат если не усечено, например
uint64_t ul = ui1 - ui2; // With ui1 and ui2 being uint32_t
double d1 = f1 / f2; // With f1 and f2 being float
Если бы я хотел, чтобы поведение, полученное из вышеприведенных выражений, я записал бы их как:
uint64_t ul = (uint32_t)(ui1 - ui2);
double d1 = (float)(f1 / f2);
, поскольку в противном случае программист, увидевший вышеизложенное без типов, может быть склонен переписать их как:
uint64_t ul = (uint64_t)ui1 - ui2;
double d1 = (double)f1 / f2;
, который может привести к поведению, которое, хотя и более желательно, может противоречить тому, что на самом деле нужно программе.