“F” após o número

102

O que o fdepois dos números indica? É de C ou Objective-C? Existe alguma diferença em não adicionar isso a um número constante?

CGRect frame = CGRectMake(0.0f, 0.0f, 320.0f, 50.0f);

Você pode explicar por que eu não apenas escreveria:

CGRect frame = CGRectMake(0, 0, 320, 50);
typeoneerror
fonte

Respostas:

88
CGRect frame = CGRectMake(0.0f, 0.0f, 320.0f, 50.0f);

usa constantes flutuantes. (A constante 0.0 geralmente declara um duplo em Objective-C; colocar um f no final - 0.0f - declara a constante como um flutuante (32 bits).)

CGRect frame = CGRectMake(0, 0, 320, 50);

usa ints que serão automaticamente convertidos em flutuadores.

Nesse caso, não há diferença (prática) entre os dois.

Frank Shearar
fonte
24
Teoricamente, o compilador pode não ser inteligente o suficiente para convertê-los em float em tempo de compilação, e tornaria a execução mais lenta com quatro conversões int-> float (que estão entre as conversões mais lentas). Embora neste caso seja quase sem importância, é sempre melhor especificar corretamente f se necessário: em uma expressão, uma constante sem o especificador correto pode forçar toda a expressão a ser convertida para o dobro e, se estiver em um loop fechado, o desempenho pode ser perceptível.
Matteo Italia
60

Em caso de dúvida, verifique a saída do montador. Por exemplo, escreva um pequeno trecho mínimo, ou seja, como este

#import <Cocoa/Cocoa.h>

void test() {
  CGRect r = CGRectMake(0.0f, 0.0f, 320.0f, 50.0f);
  NSLog(@"%f", r.size.width);
}

Em seguida, compile-o no montador com a -Sopção.

gcc -S test.m

Salve a saída do assembler no test.sarquivo, remova .0f-a das constantes e repita o comando de compilação. Em seguida, faça uma diffdo novo test.se do anterior. Acho que isso deve mostrar se existem diferenças reais. Acho que muitos têm uma visão do que acham que o compilador faz, mas no final do dia, deve-se saber como verificar quaisquer teorias.

epatel
fonte
11
A saída acabou sendo idêntica para mim, mesmo sem nenhum -O. Estou em i686-apple-darwin10-gcc-4.2.1 (GCC)
kizzx2
2
Tentei o exemplo acima com o LLVM versão 7.0.0 (clang-700.0.65) x86_64-apple-darwin15.0.0 e os arquivos .out eram idênticos também.
Nick de
43

Às vezes, há uma diferença.

float f = 0.3; /* OK, throw away bits to convert 0.3 from double to float */
assert ( f == 0.3 ); /* not OK, f is converted from float to double
   and the value of 0.3 depends on how many bits you use to represent it. */
assert ( f == 0.3f ); /* OK, comparing two floats, although == is finicky. */
Potatoswatter
fonte
26

Ele informa ao computador que este é um número de ponto flutuante (presumo que você esteja falando sobre c / c ++ aqui). Se não houver f após o número, ele é considerado um duplo ou um inteiro (dependendo se existe um decimal ou não).

3.0f -> float
3.0 -> double
3 -> integer
NickLH
fonte
esta convenção é parte do padrão C ++ ou é encontrada no compilador?
jxramos de
1
Pelo que eu posso dizer, faz parte do padrão (alguém me corrija se eu estiver errado). A referência mais rápida que consegui encontrar é open-std.org/jtc1/sc22/open/n2356/lex.html#lex.fcon , mas provavelmente há referências mais atualizadas se você quiser procurá-las.
NickLH
5

Um literal de ponto flutuante em seu código-fonte é analisado como um duplo. Atribuí-lo a uma variável do tipo float perderá a precisão. Muita precisão, você está jogando fora 7 dígitos significativos. O postfix "f" permite que você diga ao compilador: "Eu sei o que estou fazendo, isso é intencional. Não me incomode com isso".

As chances de produzir um bug não são tão pequenas assim. Muitos programas caíram em uma comparação mal concebida de ponto flutuante ou assumindo que 0,1 é exatamente representável.

Hans Passant
fonte
4

O fque você está falando provavelmente pretende dizer ao compilador que ele está trabalhando com um float. Quando você omite o f, geralmente é traduzido como um duplo.

Ambos são números de ponto flutuante, mas a floatusa menos bits (portanto, menores e menos precisos) do que a double.

Yuri
fonte
3

É uma coisa em C - literais de ponto flutuante são de precisão dupla (double) por padrão. Adicionar um sufixo f torna-os uma precisão única (float).

Você pode usar ints para especificar os valores aqui e, neste caso, não fará diferença, mas usar o tipo correto é um bom hábito de se adquirir - consistência é uma coisa boa em geral, e se você precisar alterar esses valores mais tarde, saberei à primeira vista de que tipo eles são.

Paul R
fonte
2

De C. Significa constante literal flutuante. Você pode omitir "f" e ".0" e usar ints em seu exemplo por causa da conversão implícita de ints em flutuantes.

Gato selvagem
fonte
1

É quase certo de C e reflete o desejo de usar um tipo 'flutuante' em vez de um 'duplo'. É semelhante a sufixos como L em números para indicar que são inteiros longos. Você pode apenas usar inteiros e o compilador irá converter automaticamente conforme apropriado (para este cenário específico).

tiranida
fonte
0

Geralmente informa ao compilador que o valor é a float, ou seja, um inteiro de ponto flutuante. Isso significa que ele pode armazenar inteiros, valores decimais e exponenciais, por exemplo 1, 0.4ou 1.2e+22.

Polinomial
fonte