What Comes After The %? - c

I've searched for this a little but I have not gotten a particularly straight answer. In C (and I guess C++), how do you determine what comes after the % when using printf?. For example:
double radius = 1.0;
double area = 0.0;
area = calculateArea( radius );
printf( "%10.1f %10.2\n", radius, area );
I took this example straight from a book that I have on the C language. This does not make sense to me at all. Where do you come up with 10.1f and 10.2f? Could someone please explain this?

http://en.wikipedia.org/wiki/Printf#printf_format_placeholders is Wikipedia's reference for format placeholders in printf. http://www.cplusplus.com/reference/clibrary/cstdio/printf.html is also helpful
Basically in a simple form it's %[width].[precision][type]. Width allows you to make sure that the variable which is being printed is at least a certain length (useful for tables etc). Precision allows you to specify the precision a number is printed to (eg. decimal places etc) and the informs C/C++ what the variable you've given it is (character, integer, double etc).
Hope this helps
UPDATE:
To clarify using your examples:
printf( "%10.1f %10.2\n", radius, area );
%10.1f (referring to the first argument: radius) means make it 10 characters long (ie. pad with spaces), and print it as a float with one decimal place.
%10.2 (referring to the second argument: area) means make it 10 character long (as above) and print with two decimal places.

man 3 printf
on a Linux system will give you all the information you need. You can also find these manual pages online, for example at http://linux.die.net/man/3/printf

10.1f means floating point with 1 place after the decimal point and the 10 places before the decimal point. If the number has less than 10 digits, it's padded with spaces. 10.2f is the same, but with 2 places after the decimal point.
On every system I've seen, from Unix to Rails Migrations, this is not the case. #robintw expresses it best:
Basically in a simple form it's %[width].[precision][type].
That is, not "10 places before the decimal point," but "10 places, both before and after, and including the decimal point."

10.1f means floating point with 10 characters wide with 1 place after the decimal point.
If the number has less than 10 digits, it's padded with spaces.
10.2f is the same, but with 2 places after the decimal point.
You have these basic types:
%d - integer
%x - hex integer
%s - string
%c - char (only one)
%f - floating point (float)
%d - signed int (decimal)
%i - signed int (integer) (same as decimal).
%u - unsigned int
%ld - long (signed) int
%lu - long unsigned int
%lld - long long (signed) int
%llu - long long unsigned int
Edit: there are several others listed in #Eli's response (man 3 printf).

10.1f means you want to display a float with 1 decimal and the displayed number should be 10 characters long.

In short, those values after the % tell printf how to interpret (or output) all of the variables coming later. In your example, radius is interpreted as a float (this the 'f'), and the 10.1 gives information about how many decimal places to use when printing it out.
See this link for more details about all of the modifiers you can use with printf.

Man pages contain the information you want. To read what you have above:
printf( "%10.2f", 1.5 )
This will print:
1.50
Whereas:
printf("%.2f", 1.5 )
Prints:
1.50
Note the justification of both.
Similarly:
printf("%10.1f", 1.5 )
Would print:
1.5
Any number after the . is the precision you want printed. Any number before the . is the distance from the left margin.

One issue that hasn't been raised by others is whether double is the same as a float. On some systems a different format specifier was needed for a double compared to a float. Not least because the parameters passed could be of different sizes.
%f - float
%lf - double
%g - double

Related

Why double and %f don't want to print 10 decimals?

I am learning c programming language and am figuring out format specifiers, but it seems as if double and %f are not working corectly.
Here is my code
#include <stdio.h>
int main(void)
{
double a = 15.1234567899876;
printf("%13.10f", a);
}
In my textbook it's stated that in "%13.10f" 13 stands for total number of digits we want to be printed(including dot) and 10 is number of decimals. So i expected to get 15.1234567899 but didn't.
After running it I get 15.1234567900. It's not just not enough decimals, but decimals are not printed correctly. Variable a has 8 after 7 and before 9, but printed number does not.
Can someone please tell me where am I wrong.
Thank you. Lp
printf is supposed to round the result to the number of digits you asked for.
you asked: 15.1234567899876
you got: 15.1234567900
digit count: 1234567890
So printf is behaving correctly.
You should beware, though, that both types float and double have finite precision. Also their finite precision is as a number of binary bits, not decimal digits. So after about 7 digits for a float, and about 16 digits for a double, you'll start seeing results that can seem quite strange if you don't realize what's going on. You can see this if you start printing more digits:
printf("%18.15f\n", a);
you asked: 15.1234567899876
you got: 15.123456789987600
So that's okay. But:
printf("%23.20f\n", a);
you asked: 15.1234567899876
you got: 15.12345678998759979095
Here we see that, at the 15th digit, the number actually stored internally begins to differ slightly from the number you asked for. You can read more about this at Is floating point math broken?
Footnote: What was the number actually stored internally? It was the hexadecimal floating-point number 0xf.1f9add3b7744, or expressed in C's %a format, 0x1.e3f35ba76ee88p+3. Converted back to decimal, it's exactly 15.1234567899875997909475699998438358306884765625. All those other renditions (15.1234567900, 15.123456789987600, and 15.12345678998759979095) are rounded to some smaller number of digits. The internal value makes the most sense, perhaps, expressed in binary, where it's 0b1111.0001111110011010110111010011101101110111010001000, with exactly 53 significant bits, of which 52 are explicit and one implicit, per IEEE-754 double precision.

Get printf to print all float digits

I'm confused about the behavior of printf("%f", M_PI). It prints out 3.141593, but M_PI is 3.14159265358979323846264338327950288. Why does printf do this, and how can I get it to print out the whole float. I'm aware of the %1.2f format specifiers, but if I use them then I get a bunch of unused 0s and the output is ugly. I want the entire precision of the float, but not anything extra.
Why does printf do this, and how can I get it to print out the whole
float.
By default, the printf() function takes precision of 6 for %f and %F format specifiers. From C11 (N1570) §7.21.6.1/p8 The fprintf function (emphasis mine going forward):
If the precision is missing, it is taken as 6; if the precision is
zero and the # flag is not specified, no decimal-point character
appears. If a decimal-point character appears, at least one digit
appears before it. The value is rounded to the appropriate number
of digits.
Thus call is just equivalent to:
printf("%.6f", M_PI);
The is nothing like "whole float", at least not directly as you think. The double objects are likely to be stored in binary IEEE-754 double precision representation. You can see the exact representation using %a or %A format specifier, that prints it as hexadecimal float. For instance:
printf("%a", M_PI);
outputs it as:
0x1.921fb54442d18p+1
which you can think as "whole float".
If all what you need is "longest decimal approximation", that makes sense, then use DBL_DIG from <float.h> header. C11 5.2.4.2.2/p11 Characteristics of floating types :
number of decimal digits, q, such that any floating-point number with
q decimal digits can be rounded into a floating-point number with p
radix b digits and back again without change to the q decimal digits
For instance:
printf("%.*f", DBL_DIG-1, M_PI);
may print:
3.14159265358979
You can use sprintf to print a float to a string with an overkill display precision and then use a function to trim 0s before passing the string to printf using %s to display it. Proof of concept:
#include <math.h>
#include <string.h>
#include <stdio.h>
void trim_zeros(char *x){
int i;
i = strlen(x)-1;
while(i > 0 && x[i] == '0') x[i--] = '\0';
}
int main(void){
char s1[100];
char s2[100];
sprintf(s1,"%1.20f",23.01);
sprintf(s2,"%1.20f",M_PI);
trim_zeros(s1);
trim_zeros(s2);
printf("s1 = %s, s2 = %s\n",s1,s2);
//vs:
printf("s1 = %1.20f, s2 = %1.20f\n",23.01,M_PI);
return 0;
}
Output:
s1 = 23.010000000000002, s2 = 3.1415926535897931
s1 = 23.01000000000000200000, s2 = 3.14159265358979310000
This illustrates that this approach probably isn't quite what you want. Rather than simply trimming zeros you might want to truncate if the number of consecutive zeros in the decimal part exceeds a certain length (which could be passed as a parameter to trim_zeros. Also — you might want to make sure that 23.0 displays as 23.0 rather than 23. (so maybe keep one zero after a decimal place). This is mostly proof of concept — if you are unhappy with printf use sprintf then massage the result.
Once a piece of text is converted to a float or double, "all" the digits is no longer a meaningful concept. There's no way for the computer to know, for example, that it converted "3.14" or "3.14000000000000000275", and they both happened to produce the same float. You'll simply have to pick the number of digits appropriate to your task, based on what you know about the precision of the numbers involved.
If you want to print as many digits as are likely to be distinctly represented by the format, floats are about 7 digits and doubles are about 15, but that's an approximation.

double precision lost when parsing csv file in C

I'm trying to read in a file in c with the following format:
6.43706064058,4.15417249035
3.43706064058,1.15417249035
...
I'm able to parse out the two doubles, but when I print out what I've parsed, I notice that I only get up to 6 decimal places. Here is my code:
long double d1;
long double d2;
fscanf(file, "%Lf,%Lf", &d1, &d2);
printf("x:%Lf, y:%Lf", d1, d2);
Output:
x:6.437061, y:4.154172
...
Where am I losing the precision? Is it possible that its being read in correctly, but my printf statement isn't showing all the precision?
Is it possible that its being read in correctly, but my printf statement isn't showing all the precision?
That's exactly what's happening. From the printf(3) man page:
... 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 ...
Tell printf to show more precision by changing your format string:
printf("x:%.11Lf, y:%.11Lf", d1, d2);
The default %f format only prints 6 places after the decimal point, which gives you much less precision than the actual floating point value (unless the exponent is large) and possibly no precision at all (if the exponent is more than slightly negative). Unless you know all your values are bounded away from zero (e.g. all greater than 1), you really need to use the %g format (which can switch to exponential notation as needed) or the %e format (which always uses exponential notation) to print floating point values in a way that preserves their precision.
You also need to use sufficiently many decimal places. For IEEE double precision, 17 decimal places is sufficient, so %.17g would be the preferred format. For long double, it depends on the type used on your particular implementation. Thankfully, C offers a macro, DECIMAL_DIG, that gives you exactly the number of places you need. So you would use:
printf("%.*Lg", DECIMAL_DIG, x);
or similar. Note that this will print more places than were originally present in your input file. If you know your input always has a particular number of places, you could perhaps just hard-code that instead of using DECIMAL_DIG to get a more uniform output.
The reason you are not as far with the precision as you'd like to be is because the level of the spacing in the number is not enough. In the first number, 6.43706064058, you have 13 numbers, including the decimal, so you'd put
printf("x:%13Lf, y:%Lf", d1, d2);
allowing 13 spaces for the x:
for the second number, 4.15417249035, you have 13 also, so for that, you'd put
printf("x:%13Lf, y:13%Lf", d1, d2);
and that will print:
x:6.43706064058, y:4.15417249035
you must allow room for all of the spaces within the number when doing the printf function.
Hope that helped!

C: How long can a double be when printed through printf()

I need to specify the exact length of a string to be printed from a double value, but I don't want to restrict the output any more than is necessary.
What is the maximum length that a 6-digit precision double will have when formatted by printf()?
Specifically, what value should I give to X in printf("%X.6lg",doubleValue); to ensure that no value gets truncated?
The reason I need to be specific about the length is that I'm defining an MPI derived datatype made up of lots of string representations of double values and must know their exact length in order to divide regions of the file between MPI processes.
I hope that's clear. Thanks in advance for answering.
use printf("%.6g", doubleValue) or printf("%.6Lg", doubleValue)
Note that leaving off the leading digits (the "width") in the precision specifier makes no demands on the length of the integral portion of the value. Also note that the undercase "l" will specify that your value is a long int. The uppercase "L" specifies a long double value.Also note that if you don't want this to be potentially changed to scientific notation (if it is a shorter representation), then you would use "f" instead of "g".See a printf reference here.
The maximum exponent of an IEEE double is 1023, so largest double will be 1 + 1/2 + 1/4 + 1/8 + ... etc * 2^1023. Which will be about 318 characters long, in decimal notation.
Why not use the "e" format specifier?
There's < float.h > containing many useful values, among them DECIMAL_DIG, which is for a long double however.
The same file will most likely tell you that a double on your platform has more than 6 digits of precision...
PS: Also note Demi's answer above. He points out various flaws in your printf() that escaped me.

How to use "%f" to populate a double value into a string with the right precision

I am trying to populate a string with a double value using a sprintf like this:
sprintf(S, "%f", val);
But the precision is being cut off to six decimal places. I need about 10 decimal places for the precision.
How can that be achieved?
%[width].[precision]
Width should include the decimal point.
%8.2 means 8 characters wide; 5 digits before the point and 2 after. One character is reserved for the point.
5 + 1 + 2 = 8
What you want is a modifier:
sprintf(S, "%.10f", val);
man sprintf will have many more details on format specifiers.
For a more complete reference, see the Wikipedia printf article, section "printf format placeholders" and a good example on the same page.
Take care - the output of sprintf will vary via C locale. This may or may not be what you want. See LC_NUMERIC in the locale docs/man pages.
%f is for float values.
Try using %lf instead. It is designed for doubles (which used to be called long floats).
double x = 3.14159265;
printf("15.10lf\n", x);

Resources