"F" dopo il numero


102

Cosa findicano i numeri dopo? È da C o Objective-C? C'è qualche differenza nel non aggiungere questo a un numero costante?

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

Puoi spiegare perché non scriverei semplicemente:

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

Risposte:


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

usa costanti float. (La costante 0.0 di solito dichiara un double in Objective-C; mettere una f alla fine - 0.0f - dichiara la costante come un float (32 bit).)

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

usa int che verranno automaticamente convertiti in float.

In questo caso, non c'è differenza (pratica) tra i due.


24
Teoricamente, il compilatore potrebbe non essere abbastanza intelligente da convertirli in float in fase di compilazione e rallenterebbe l'esecuzione con quattro conversioni int-> float (che sono tra i cast più lenti). Anche se in questo caso è quasi irrilevante, è sempre meglio specificare correttamente f se necessario: in un'espressione una costante senza l'identificatore giusto può forzare l'intera espressione a essere convertita in double, e se è in un ciclo stretto la prestazione potrebbe essere evidente.
Matteo Italia

60

In caso di dubbio, controllare l'output dell'assembler. Ad esempio, scrivi un piccolo frammento minimo, ad esempio come questo

#import <Cocoa/Cocoa.h>

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

Quindi compilarlo in assembler con l' -Sopzione.

gcc -S test.m

Salvare l'output dell'assembler nel test.sfile e rimuoverlo .0fdalle costanti e ripetere il comando di compilazione. Quindi fai uno diffdei nuovi test.se precedenti. Pensa che dovrebbe mostrare se ci sono differenze reali. Penso che troppi abbiano una visione di ciò che pensano che faccia il compilatore, ma alla fine della giornata si dovrebbe sapere come verificare eventuali teorie.


11
L'output si è rivelato identico per me, anche senza -O. Sono su i686-apple-darwin10-gcc-4.2.1 (GCC)
kizzx2

2
Ho provato l'esempio sopra con LLVM versione 7.0.0 (clang-700.0.65) x86_64-apple-darwin15.0.0 e anche i file .out erano identici.
Nick

43

A volte c'è una differenza.

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. */

26

Indica al computer che questo è un numero in virgola mobile (presumo che tu stia parlando di c / c ++ qui). Se non c'è una f dopo il numero, è considerato un doppio o un numero intero (a seconda che sia presente un decimale o meno).

3.0f -> float
3.0 -> double
3 -> integer

questa convenzione fa parte dello standard C ++ o si trova nel compilatore?
jxramos

1
Per quanto ne so, fa parte dello standard (qualcuno mi corregge se sbaglio). Il riferimento più rapido che sono riuscito a trovare è open-std.org/jtc1/sc22/open/n2356/lex.html#lex.fcon , ma probabilmente ci sono riferimenti più aggiornati se ti interessa cercarli.
NickLH

5

Un valore letterale a virgola mobile nel codice sorgente viene analizzato come double. Assegnarlo a una variabile di tipo float perderà precisione. Molta precisione, stai buttando via 7 cifre significative. Il suffisso "f" ti permette di dire al compilatore: "So cosa sto facendo, questo è intenzionale. Non disturbarmi".

Le probabilità di produrre un bug non sono così piccole. Molti programmi si sono concentrati su un confronto in virgola mobile mal concepito o assumendo che 0.1 sia esattamente rappresentabile.


4

Ciò di fcui stai parlando probabilmente ha lo scopo di dire al compilatore che sta lavorando con un float. Quando ometti il f, di solito viene tradotto in un doppio.

Entrambi sono numeri in virgola mobile, ma a floatutilizza meno bit (quindi più piccoli e meno precisi) di a double.


3

È una cosa C: i letterali in virgola mobile sono a doppia precisione (doppia) per impostazione predefinita. L'aggiunta di un suffisso f li rende a precisione singola (float).

Puoi usare gli int per specificare i valori qui e in questo caso non farà differenza, ma usare il tipo corretto è una buona abitudine per entrare - la coerenza è una buona cosa in generale, e se hai bisogno di cambiare questi valori in seguito devi Saprò a prima vista di che tipo sono.


2

Da C. Significa float letterale costante. Puoi omettere sia "f" che ".0" e usare int nel tuo esempio a causa della conversione implicita di int in float.


1

È quasi certamente da C e riflette il desiderio di utilizzare un tipo "float" piuttosto che "double". È simile a suffissi come L sui numeri per indicare che sono interi lunghi. Puoi semplicemente usare numeri interi e il compilatore convertirà automaticamente come appropriato (per questo scenario specifico).


0

Di solito dice al compilatore che il valore è a float, cioè un numero intero in virgola mobile. Questo significa che può memorizzare numeri interi, valori decimali e esponenziali, ad esempio 1, 0.4o 1.2e+22.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.