try this
f = 3 / 2; printf("%f\n",f); //1.000000
f = (float)(3 / 2); printf("%f\n",f); //1.000000
f = (float)3 / 2; printf("%f\n",f); //1.500000
f = 3 / (float)2; printf("%f\n",f); //1.500000
f = 3 / 2.0; printf("%f\n",f); //1.500000
f = 3.0 / 2; printf("%f\n",f); //1.500000
f = 3.0 / 2.0; printf("%f\n",f); //1.500000
Parse this like a compiler would. Yes f is declared as a float, but the number 3 without a decimal point is an integer. When there is a decimal point then C dictates that is a double. In order to perform an operation the operands are promoted to the highest/largest/most precise-ish, whatever, float is above int, double is above float.
f = 3 / 2; printf("%f\n",f); //1.000000
3 and 2 are integers the division happens first as an integer division result of 1
then the equals is done second the 1 needs to be promoted to a float.
f = (float)(3 / 2); printf("%f\n",f); //1.000000
same as above the division comes first it is isolated within the parenthesis so integer division, then it is promoted to float, the equals is next and the result is already promoted to float.
f = (float)3 / 2; printf("%f\n",f); //1.500000
3 is promoted to float first so in order to perform the division 2 has to be promoted to float, the division is done as a float and then the storage to f it is already float.
f = 3 / (float)2; printf("%f\n",f); //1.500000
same as above 2 is promoted from an int to float then the division has to be float so 3 is promoted.
f = 3 / 2.0; printf("%f\n",f); //1.500000
2.0 is a double as written like this in C so 3 is promoted to a double, the division is double. that result has to be converted from double to float then stored to f as a float.
f = 3.0 / 2; printf("%f\n",f); //1.500000
same as above 3.0 is a double, 2 is promoted, division is double, then converted to float.
f = 3.0 / 2.0; printf("%f\n",f); //1.500000
both are double.
Now I just added this one:
f = 3.0F / 2; printf("%f\n",f); //1.500000
adding the F makes 3 a single float, 2 is promoted to float, division is float then the answer is stored in f.
Unless you do no optimization, most of these "conversions" are optimized out where possible, if you compiled the above or your program with optimizations on the compiler is going to simply generate a list of printfs of 1.0f or 1.5F. The comments describe how to read/interpret the code, how the compiler is going to read that code and functionally implement it.