Каково значение 0,0f при инициализации (в C)? - PullRequest
29 голосов
/ 05 марта 2011

Я видел код, где люди инициализируют переменные с плавающей запятой, как это:

float num = 0.0f;

Есть ли существенная разница между этим и выполнением следующих действий ниже?

float num = 0; 

Спасибо..:)

Ответы [ 7 ]

47 голосов
/ 05 марта 2011

float x = 0 имеет неявное преобразование типов от int до float.
float x = 0.0f не имеет такого типа.
floatx = 0.0 имеет неявный тип-тип от double до float.

В зависимости от компилятора неявное преобразование типов может потребовать от компилятора создания дополнительного кода.

8 голосов
/ 05 марта 2011

Хорошей практикой считается инициализация переменной литеральной константой того же типа. В этом случае у вас есть переменная типа float, и вы должны инициализировать ее литеральной константой типа float, то есть 0.0f, а не int (0), которая затем неявно преобразуется в число с плавающей точкой.

7 голосов
/ 05 марта 2011

Вероятно, причина в том, что они когда-то написали что-то вроде:

float f = 1 / i; // i an integer

После отладки они поклялись всегда украшать литералы в достаточной степени, чтобы получить правильный тип:

float f = 1.0f / i;

Вв этом случае .0 должен обеспечить деление с плавающей точкой, а не целочисленное деление.f объясняется тем, что нет необходимости выполнять операцию в double - я ожидаю, что есть больше шансов на реализацию, где 1.0/i будет значительно медленнее без пользы (эмуляция поплавка программного обеспечения, безразличная оптимизация), чемтот, где 1.0f значительно медленнее и бесполезен (если double быстрее, чем float, потому что у вас аппаратное обеспечение fp, поэтому преобразование между ними будет очень быстрым, поэтому не вводите значительное замедление).

Если у вас есть привычка украшать литералы, вы можете написать:

float f = 0.0f;

, хотя он имеет тот же эффект, что и float f = 0.0; или float f = 0;.

Конечно, автор, возможно, не прошел через это откровение лично, он мог просто унаследовать стиль кого-то другого, кто это сделал.

Я бы просто написал 0.

R .. указывает в комментарии еще один ответ, что написание 0 также имеет то преимущество, что при изменении типа f в будущем вам не нужно обновлять литерал для соответствия.И если присвоение отделено от определения, то изменение:

float f = something
// some time later
f = 0.1f;

на:

double f = something;
// some time later
f = 0.1f;

, вероятно, является ошибкой.Лучше использовать 0.1 и позволить усечению компилятора плавать при необходимости.Вы, вероятно, могли бы утверждать, что использование float вообще является оптимизацией для пространства, если не для времени, и бремя устранения любых различий между float и double должно учитываться как затраты разработчика на выполнение этой оптимизации.

3 голосов
/ 05 марта 2011

Пол Р. написал ответ.Ваш второй пример имеет целочисленное значение инициализации.

Вы всегда должны использовать инициализатор того же типа, что и инициализируемая переменная.Это позволяет избежать любого преобразования во время компиляции (в идеале) или во время выполнения (ленивые компиляторы: правда, это все-таки ленивый?).И, возможно, что еще более важно, преобразование может привести к некоторым странным вещам в общем случае.

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

3 голосов
/ 05 марта 2011

Ну, строго говоря, 0 - это целое число, поэтому float num = 0 требует преобразования целого числа в число с плавающей точкой. Но я полагаю, что компилятор сделает это за вас в любом случае. Я предполагаю, что люди используют 0.0f, чтобы подчеркнуть, что это число с плавающей точкой, поэтому никто не принимает его за целое число.

1 голос
/ 19 апреля 2018

'f' означает, что вы хотите плавать:

0 - это int

0f - это число с плавающей точкой

0,0 - двойной

0.0f - это число с плавающей точкой

0 голосов
/ 05 марта 2011

Я не вижу причин использовать это для процесса инициализации.Но для операций с литералами с плавающей запятой это было бы полезно.Например;

float a=0.43, b;
b = 0.5*a + 2.56*a*a;

Литералы с плавающей точкой без суффикса считаются двойными.Таким образом, для этого вычисления «a» будет приведено к двойному типу, а окончательный ответ оценки RHS будет двойным.Во время присвоения двойное значение RHS приводится к плавающей и присваивается «b».Это ухудшило бы производительность, если машина не имеет FPU двойной точности.Чтобы избежать этого и использовать float для всего вычисления.суффиксы используются.Например,

float a=0.43, b;
b = 0.5f*a + 2.56f*a*a;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...