Section 1.3 of Kernighan and Ritchie uses the following temperature conversion program to introduce For statements:
#include <stdio.h>
/* print Fahrenheit-Celsius table */
int main(){
int fahr;
for (fahr = 0; fahr <= 300; fahr = fahr + 20)
printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
}
What it doesn't explain is how this program can make use of an int variable to produce float values without an error. What makes this valid? Don't all the variables in an equation have to be of the same type? I'm hesitant to move forward without understanding this.
The conversion are implicit, but enabling warnings should give you a message explaining that int is being converted to double.
Here (5.0/9.0)*(fahr-32)), a double is being multiplied by an int, and the int is converted to double using usual arithmetic conversions.
The types in arithmetic don't necessarily have to match. C has a whole chapter dedicated to conversions: 6.3 Conversions, 6.3.1 Arithmetic operands.
Actually it doesn't: (5.0/9.0)*(fahr-32) is an expression of type double, not a float.
The reason being that 5.0 and 9.0 are double literals and the (fahr - 32) is promoted to that type before the multiplication takes place.
If you really want a float then use (5.0f/9.0f)*(fahr-32). Note the suffixed f on the numbers (and you will need to suffix both).
%f is an appropriate format specifier in printf for a double and a float, so there are no problems there.
In an arithmetic expression, if two operands are of different types (such as int and double), the operand with the lower precision will be converted to the same type as the operand with the higher precision. The exact rules can be found in section 6.3.1.8 of the online C 2011 standard.
Note that this only applies for arithmetic (integer and floating-point) types, not for pointer or aggregate types.
The reason an int can be promoted to a double without a problem -- assuming int represents a 32-bit integer and double represents a 64-bit IEEE floating point number, which is common -- is that a double has 53 bits of precision, so it has no trouble representing a 32-bit integer without loss. Any warning would just be informational and not a cause for concern, unlike when a 32-bit integer is coerced to a float, which only has 24 bits of precision and thus could lose up to eight bits (seven for a signed int) of precision in the cast.
Related
int main(){
int s=200;
printf("%.12f",s/3.0);
}
How this program is giving output 66.666666666667 even though float can support up to only 6-7 decimal places?
Meanwhile,
int main(){
float s=200;
printf("%.12f",s/3);
}
gives 66.666664123535.
please help?
There isn't any float in the first program. %f is double and 3.0 is also double. The double type has about 16 decimal digits precision. In the second program the float is promoted to double for the variadic function but does not magically gain more precision.
From C11 § 6.4.4.2
4 An unsuffixed floating constant has type double. If suffixed by the letter f or F, it has type float. If suffixed by the letter l or L, it has type long double.
and C11 § 6.5.2.2
6 If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double.
7 If the expression that denotes the called function has a type that does include a prototype, the arguments are implicitly converted, as if by assignment, to the types of the corresponding parameters, taking the type of each parameter to be the unqualified version of its declared type. The ellipsis notation in a function prototype declarator causes argument type conversion to stop after the last declared parameter. The default argument promotions are performed on trailing arguments.
Only if the precision was missing, it would have been taken as 6. Otherwise, if you specify the precision, it's going to honor that.
Quoting C11, chapter 7.21.6.1/P8, (emphasis mine)
f,F
A double argument representing a floating-point number is converted to decimal notation in the style [-]ddd.ddd, where the number of digits after the decimal-point character is equal to the precision specification. If the precision is missing, it is taken as 6; [...]
In most C implementations, float and double do not use decimal digits. They use binary.
In the first program, 3.0 is a double, so s/3.0 is computed with double arithmetic. In spite of f being the initial letter of float, %.12f takes a double argument, for reasons involving the history of C development. So the double value s/3.0 is converted to decimal with 12 digits after the decimal point and printed.
In the second program, s is a float, so s/3 is computed with float arithmetic. In the format you use, the result is a binary-based number, 8738133 • 2−17. The reason there are many decimal digits involved is that, while expressing 2−17 is simple using that base of 2, in decimal it is 0.00000762939453125. then 8738133 times that is 66.66666412353515625. Since you asked for only 12 digits, you see 66.6666641235. (Note: The float value is converted to double to be passed to printf, but this does not change the value.)
I am learning C.
I was wondering why you get a float, even if one of your variables is an int.
float x = 5.0;
int y = 2;
float result = x / y;
My guess would be that result would be 2.00000. But it does return a float (2.500000)
I think it would be 2.000000 because if you divide 2 ints that is the result. And I would think that if you use an int and a float it would pick the least precise value.
Because of C's Usual arithmetic conversions.
Quoting the ANSI C standard § 3.2.1.5 Usual arithmetic conversions:
Many binary operators that expect operands of arithmetic type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions: First, if either operand has type long double, the other operand is converted to long double . [...] Otherwise, if either operand has type float, the other operand is converted to float.
Emphasis mine.
The operator / only performs integer division if both operands are integers.
And I would think that if you use an int and a float it would pick the least precise value.
That's exactly the opposite; the general rule is that before performing any arithmetic operation both operands are promoted to the "most powerful" type of the two involved in the operation.
The "most powerful" type is determined according to the rules that the standard calls "Usual arithmetic conversions" (C99, §6.3.1.8), which essentially say that
long double > double > float > all integral types; if an expression involves only integral types, some other rules kick in that are a bit more lengthy to describe (at §6.3.1.1).
Now, in your case you have an int and a float, the "best" type is float and thus the int is promoted to float before performing the division.
If one of the operands in you division is a float and the other one is a whole number (int, long, etc), your result's gonna be floating-point.
This means, this will be a floating-point division: if you divide 5 by 2, you get 2.5 as expected.
First of all, result is a float, so it can hold decimal values.
Secondly, one of the operands x, and y is a float, so the returned value is a float. This holds for addition, multiplication and subtraction also.
The result of the code is a float and therefore it will produce a float. When you devide an int by anf int it will return 2.5 but the result being an int truncates the result to be 2
In below program, i didnt understand how float and int value are same.
int main()
{
int a=3;
float b=3.0;
if(a==b)
{
printf("A is equal to b");
}
else{
printf("A is not euql to b");
}
}
The output of the program is "A is equal to b"
if(a==b) does not compare types, it compares values.
As #Kerrek SB commented, the value(s) are converted to a common type.
Each a and b go though "usual arithmetic conversions" before the comparison.
... the values yielded by operators with floating operands and values subject to the usual arithmetic conversions and of floating constants are evaluated to a format whose range and precision may be greater than required by the type. The use of evaluation formats is characterized by the implementation-defined value of FLT_EVAL_METHOD: C11dr §5.2.4.2.2 9
Conversion to floating point is to float, double or long double depending on FLT_EVAL_METHOD.
Assuming conversion to float...:
Otherwise, if the corresponding real type of either operand is float, the other operand is converted, without change of type domain, to a type whose
corresponding real type is float. §6.3.1.8 1
So a converts to a float with the value of 3.0 before the comparison.
Since the values compare the same, they pass the if(a==b).
Note: Conversion can cause issues as not all int may covert exactly to a float.
Actually the int value will be typecasted to float and then the if condition is evaluated.
float + (short)long = ?
I am adding these types and based on my calculation I am getting a float as an answer but the right answer is double.
can anyone give me an example of how it becomes double or explanation..
Operators that take two arithmetic operands in C always require both operands to be of the same type. If they aren't, then one or both are converted according to the usual arithmetic conversions, which are fully described in section 6.3.1.8 of the C standard (the link is to a draft of the 2011 standard).
Briefly:
If either operand is of type long double, the other is converted to long double.
Otherwise, if either operand is of type double, the other is converted to `double.
Otherwise, if either operand is of type float, the other is converted to float.
This is followed by a set of rules for two operands of integer type, which don't apply in this case.
If you need a double result, you need to convert one or both operands to double. If you convert just one of them, it will cause the other to be converted as well. (You might want to convert both just to be explicit.)
For example, if you have:
float f;
long n;
double x = f + n;
then the result of the addition is float, which is converted to double only after the addition is performed. To do a double multiplication, change the last line to:
double x = (double)f + (double)n;
On the other hand, if you want a double result, it's very likely that your float operand should have been declared as a double in the first place. double is in some sense the "default" floating-point type in C (it's the type of unsuffixed literals like 1.0, for example). float is used mostly when it's important to save memory space, such as when you have very large arrays. On many systems, float arithmetic isn't even any faster than double arithmetic (though I'm not 100% sure on that last point).
try to do:
float F;
short L;
double res = (double)(F + L);
What are the implicit types for numbers in C? If, for example, I have a decimal number in a calculation, is the decimal always treated as a double? If I have a non-decimal number, is it always treated as an int? What if my non-decimal number is larger than an int value?
I'm curious because this affects type conversion and promotion. For instance, if I have the following calculation:
float a = 1.0 / 25;
Is 1.0 treated as a double and 25 treated as an int? Is 25 then promoted to a double, the calculation performed at double precision and then the result converted to a float?
What about:
double b = 1 + 2147483649; // note that the number is larger than an int value
If the number has neither a decimal point nor an exponent, it is an integer of some sort; by default, an int.
If the number has a decimal point or an exponent, it is a floating point number of some sort; by default, a double.
That's about it. You can append suffixes to numbers (such as ULL for unsigned long long) to specify the type more precisely. Otherwise (simplifying a little), integers are the smallest int type (of type int or longer) that will hold the value.
In your examples, the code is:
float a = 1.0 / 25;
double b = 1 + 2147483649;
The value of a is calculated by noting that 1.0 is a double and 25 is an integer. When processing the division, the int is converted to a double, the calculation is performed (producing a double), and the result is then coerced into a float for assignment to a. All of this can be done by the compiler, so the result will be pre-computed.
Similarly, on a system with 32-bit int, the value 214783649 is too big to be an int, so it will be treated as a signed type bigger than int (either long or long long); the 1 is added (yielding the same type), and then that value is converted to a double. Again, it is all done at compile time.
These computations are governed by the same rules as other computations in C.
The type rules for integer constants are detailed in §6.4.4.1 Integer constants of ISO/IEC 9899:1999. There's a table which details the types depending on the suffix (if any) and the type of constant (decimal vs octal or hexadecimal). For decimal constants, the value is always a signed integer; for octal or hexadecimal constants, the type can be signed or unsigned as required, and as soon as the value fits. Thanks to Daniel Fischer for pointing out my mistake.
http://en.wikipedia.org/wiki/Type_conversion
The standard has a general guideline for what you can expect but compilers have a superset of rules that encompass the standard as well as rules for optimizing. The above link discusses some of the the generalities you can expect. If you are concerned about the implicit coercion it is typically good practice to use explicit casting.
Keep in mind that the size of the primitive types is not guaranteed.
1.0 / 25
Evaluates to a double because one of the operands is a double. If you changed it to 1/25 the evaluation is performed as two integers and evaluates to 0.
double b = 1 + 2147483649;
The right side is evaluated as an integer and then coerced to a double during assignment.
actually. in your example you may get a compiler warning. You'd either write 1.0f to make it a float to start with, or explicitly cast your result before assigning it.