Videos
How do you use double for scientific notation in C?
Can double be used to store large numbers in C?
How do I round a double value to the nearest integer in C?
I was wondering why you wouldn't just use a double all the time instead of a float. I googled and found this as an explanation:
Double is more precise than float and can store 64 bits; double the number of bits float can store. We prefer double over float if we need to do precision up to 15 or 16 decimal points; otherwise, we can stick to float in most applications, as double is more expensive.
Difference between float and double in C/C++ | Coding Ninjas Blog
Can anyone clarify what being "more expensive" means in this context?
To quote the C++ standard, §3.9.1 ¶8:
There are three floating point types: float, double, and long double. The type double provides at least as much precision as float, and the type long double provides at least as much precision as double. The set of values of the type float is a subset of the set of values of the type double; the set of values of the type double is a subset of the set of values of the type long double. The value representation of floating-point types is implementation-defined. Integral and floating types are collectively called arithmetic types. Specializations of the standard template std::numeric_limits (18.3) shall specify the maximum and minimum values of each arithmetic type for an implementation.
That is to say that double takes at least as much memory for its representation as float and long double at least as much as double. That extra memory is used for more precise representation of a number.
On x86 systems, float is typically 4 bytes long and can store numbers as large as about 3×10³⁸ and about as small as 1.4×10⁻⁴⁵. It is an IEEE 754 single-precision number that stores about 7 decimal digits of a fractional number.
Also on x86 systems, double is 8 bytes long and can store numbers in the IEEE 754 double-precision format, which has a much larger range and stores numbers with more precision, about 15 decimal digits. On some other platforms, double may not be 8 bytes long and may indeed be the same as a single-precision float.
The standard only requires that long double is at least as precise as double, so some compilers will simply treat long double as if it is the same as double. But, on most x86 chips, the 10-byte extended precision format 80-bit number is available through the CPU's floating-point unit, which provides even more precision than 64-bit double, with about 21 decimal digits of precision.
Some compilers instead support a 16-byte (128-bit) IEEE 754 quadruple precision number format with yet more precise representations and a larger range.
It depends on your compiler but the following code can show you the number of bytes that each type requires:
int main() {
printf("%d\n", sizeof(double)); // some compilers print 8
printf("%d\n", sizeof(long double)); // some compilers print 16
return 0;
}
You're using the wrong format specifier to printf.
The %d format specifier expects an int argument, but you're passing a double. Using the wrong format specifier invokes undefined behavior.
To print a double, use %f.
printf("average: %f\n", average);
No need to modify the statement average=(double)(num1+num2)/2; to get expected result inside printf use %f instead of %d
- 1st
(num1+num2)is performed, result of this is ofintegraltype. lets say15. Next when you do(double)15/2result is offloatingtype which is7.500000. - from previous step
average = (double)7.500000average holds7.500000but since you printed in%dyou are getting0as its undefined behavior. instead use%f
Here is the working one
int main() {
int num1 = 7, num2 = 8;
double average;
average = (double)(num1 + num2)/2;
printf("average: %f\n", average);
return 0;
}
For variable argument functions like printf and scanf, the arguments are promoted, for example, any smaller integer types are promoted to int, float is promoted to double.
scanf takes parameters of pointers, so the promotion rule takes no effect. It must use %f for float* and %lf for double*.
printf will never see a float argument, float is always promoted to double. The format specifier is %f. But C99 also says %lf is the same as %f in printf:
C99 §7.19.6.1 The
fprintffunction
l(ell) Specifies that a followingd,i,o,u,x, orXconversion specifier applies to along intorunsigned long intargument; that a followingnconversion specifier applies to a pointer to along intargument; that a followingcconversion specifier applies to awint_targument; that a followingsconversion specifier applies to a pointer to awchar_targument; or has no effect on a followinga,A,e,E,f,F,g, orGconversion specifier.
When a float is passed to printf, it is automatically converted to a double. This is part of the default argument promotions, which apply to functions that have a variable parameter list (containing ...), largely for historical reasons. Therefore, the “natural” specifier for a float, %f, must work with a double argument. So the %f and %lf specifiers for printf are the same; they both take a double value.
When scanf is called, pointers are passed, not direct values. A pointer to float is not converted to a pointer to double (this could not work since the pointed-to object cannot change when you change the pointer type). So, for scanf, the argument for %f must be a pointer to float, and the argument for %lf must be a pointer to double.
Use the %lf format specifier to read a double:
double a;
scanf("%lf",&a);
Wikipedia has a decent reference for available format specifiers.
You'll need to use the %lf format specifier to print out the results as well:
printf("%lf %lf",a,b);
As far as i know %d means decadic which is number without decimal point. if you want to load double value, use %lf conversion (long float). for printf your values are wrong for same reason, %d is used only for integer (and possibly chars if you know what you are doing) numbers.
Example:
double a,b;
printf("--------\n"); //seperate lines
scanf("%lf",&a);
printf("--------\n");
scanf("%lf",&b);
printf("%lf %lf",a,b);
"%f" is the (or at least one) correct format for a double. There is no format for a float, because if you attempt to pass a float to printf, it'll be promoted to double before printf receives it1. "%lf" is also acceptable under the current standard -- the l is specified as having no effect if followed by the f conversion specifier (among others).
Note that this is one place that printf format strings differ substantially from scanf (and fscanf, etc.) format strings. For output, you're passing a value, which will be promoted from float to double when passed as a variadic parameter. For input you're passing a pointer, which is not promoted, so you have to tell scanf whether you want to read a float or a double, so for scanf, %f means you want to read a float and %lf means you want to read a double (and, for what it's worth, for a long double, you use %Lf for either printf or scanf).
1. C99, §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. These are called the default argument promotions." In C++ the wording is somewhat different (e.g., it doesn't use the word "prototype") but the effect is the same: all the variadic parameters undergo default promotions before they're received by the function.
Given the C99 standard (namely, the N1256 draft), the rules depend on the function kind: fprintf (printf, sprintf, ...) or scanf.
Here are relevant parts extracted:
Foreword
This second edition cancels and replaces the first edition, ISO/IEC 9899:1990, as amended and corrected by ISO/IEC 9899/COR1:1994, ISO/IEC 9899/AMD1:1995, and ISO/IEC 9899/COR2:1996. Major changes from the previous edition include:
%lfconversion specifier allowed inprintf7.19.6.1 The
fprintffunction7 The length modifiers and their meanings are:
l (ell) Specifies that (...) has no effect on a following a, A, e, E, f, F, g, or G conversion specifier.
L Specifies that a following a, A, e, E, f, F, g, or G conversion specifier applies to a long double argument.
The same rules specified for fprintf apply for printf, sprintf and similar functions.
7.19.6.2 The
fscanffunction11 The length modifiers and their meanings are:
l (ell) Specifies that (...) that a following a, A, e, E, f, F, g, or G conversion specifier applies to an argument with type pointer to double;
L Specifies that a following a, A, e, E, f, F, g, or G conversion specifier applies to an argument with type pointer to long double.
12 The conversion specifiers and their meanings are: a,e,f,g Matches an optionally signed floating-point number, (...)
14 The conversion specifiers A, E, F, G, and X are also valid and behave the same as, respectively, a, e, f, g, and x.
The long story short, for fprintf the following specifiers and corresponding types are specified:
%f-> double%Lf-> long double.
and for fscanf it is:
%f-> float%lf-> double%Lf-> long double.