pcmC%iD%ip parameter in sprintf - c

What does this line of code will do.
pcm->card->number, pcm->device both are int.
char str[16];
sprintf(str, "pcmC%iD%ip", pcm->card->number, pcm->device);
it is taken form android/kernel/sound/core/pcm.c.

As of the description of sprintf() and fprintf(), %i is
The int argument is converted to a signed decimal in the style [-]dddd. The precision
specifies the minimum number of digits to appear; if the value being converted can be
represented in fewer digits, it will be expanded with leading zeros. The default precision
is 1. The result of converting 0 with an explicit precision of 0 is no characters.
So the result is e.g. pcmC12D23p if pcm->card->number == 12 and pcm->device == 23.

My guess: this line is forming device's file name. Like ones which you can find in /dev

Related

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.

Is there an implied word size for printing negative numbers in hexadecimal?

All the following produce the same output of ffffffef:
printf("%x\n", -17);
printf("%2x\n", -17);
printf("%8x\n", -17);
Why?
%x in printf() expects an unsigned int argument. Assuming int is 32-bit, in your example, -17 is converted to 4294967279u (0xffffffef). This means the formated output is at least 8 characters, even if you are using %x or %2x.
You'll get a different result if using:
printf("%hx\n", -17); // ffef
In this example, %hx expects an unsigned short, therefore different result.
In %2x, %4x and %8x, here the numbers represent the minimum character width that will be printed. Now since ffffffef is 8 character wide, it was printed same for all three case, because the character width is >= the number specified. If the number while specifying format would be >= 8, then you will see an extra space at the beginning (this depends on how you have specified the print format).

Extra precision values seen for float values

Below is the solution code for an excercise from KN King's Modern Programming approach.
#include<stdio.h>
int main(void)
{
int i;
float j,x;
scanf("%f%d%f",&x,&i,&j);
printf("i = %d",i);
printf("x = %f",x);
printf("j = %f",j);
}
Input:
12.3 45.6 789
Expected Result :
i = 45
x = 12.3
j = 0.6
Actual Result:
i = 45
x = 12.300000
j = 0.600000
Question:
Why are there extra decimal values seen for floats? Is there any default precision set for float and how can I change it (Only default - I know I can use formatting strings to control precision values in printf). I am using gcc (Mingw) on windows7.
The floating-point formats record only a mathematical value. They do not record how much precision the value had when scanned (or otherwise obtained). (For that matter, this is true of the integer formats too.)
When you display a floating-point value, you must specify how many digits to display. The C standard defines a default of six digits for the %f specifier:1
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; 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.
You specify the precision by writing the number of digits after a period in the format specifications, such as %.2f:2
The precision takes the form of a period (.) followed either by an asterisk * (described later) or by an optional decimal integer; if only the period is specified, the precision is taken as zero.
(The asterisk is used to specify the number of digits in a int parameter passed to printf.)
Notes
1 C 2011 (N1570) 7.21.6.1 8.
2 C 2011 (N1570) 7.21.6.1 4.
You can't change the precision of a float, but (as it sounds like you know) you can change the precision of the display of a float.
Why are there extra decimal values seen for floats?
That's why floats are floats.By default %f lets you display 6 digits after decimal.
That's nothing do do with the precision of the number stored.Numbers are stored according to the IEEE 754 FLOATING POINT representation in most systems.And numbers are not stored with decimal points. So, since you do not control how you store numbers, you can't change the precision.Precision is fixed.
Is there any default precision set for float and how can I change it.
Again , precision is not default its not how it is stored. Check its representation for 32 bit or 64 bit.Youwould like to print more/less digits after decimal.You can do this :
float i=2.89674534423;
printf("%.10f",i); Prints 10 digits after decimal.
A double is not infinitely accurate, and it does not store numbers in decimal, so it cannot precisely store 0.085. If you want to print a number to two significant figures, use the precision format specifier - see http://www.cprogramming.com/tutorial/printf-format-strings.html for examples.
double value = 0.085;
NSLog(#"%.2g", value);
This will print "0.085"
Be aware that using the precision specifier normally controls the number of digits displayed after the decimal point - but in the case of a double, it controls significant figures.
float value = 0.085;
NSLog(#"%.2f", value);
Will print "0.09"

Formatting floating point numbers in C [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Avoid trailing zeroes in printf()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
FILE *file;
double n;
file = fopen("fp.source", "r");
while(!feof(file)) {
fscanf(file, "%lf", &n);
printf("Next double:\"%lf\"\n", n);
}
fclose(file);
return 0;
}
Hi I am trying to scan for floating point numbers and I have gotten it to work, but I get trailing zeroes that I don't want. Is there a way to avoid this? For example, the current output I get is:
Next double:"11.540000"
When in reality I would like:
Next double:"11.54"
That's not a problem with scanning. That is a problem with printf formatting.
From the documentation (emphasis mine):
f, F
The double argument shall be converted to decimal notation in the style "[-]ddd.ddd", where the number of digits after the radix character is equal to the precision specification. If the precision is missing, it shall be taken as 6; if the precision is explicitly zero and no '#' flag is present, no radix character shall appear. If a radix character appears, at least one digit appears before it. The low-order digit shall be rounded in an implementation-defined manner.
You probably want %g (again, emphasis mine):
g, G
The double argument shall be converted in the style f or e (or in the style F or E in the case of a G conversion specifier), with the precision specifying the number of significant digits. If an explicit precision is zero, it shall be taken as 1. The style used depends on the value converted; style e (or E ) shall be used only if the exponent resulting from such a conversion is less than -4 or greater than or equal to the precision. Trailing zeros shall be removed from the fractional portion of the result; a radix character shall appear only if it is followed by a digit or a '#' flag is present.
Is there a way to avoid this?
Yes, just format the output correctly:
printf("Next double:\"%.0lf\"\n", n);
The .0 in the printf format string indicates that you don't want to print any digits after the decimal point. You can change the 0 to some other value if you want one, two, three or more digits after the decimal.
Try this.
printf("Next double:\"%l.0f\"\n", n);
Here's a good reference for string format specifiers.
http://www.cplusplus.com/reference/cstdio/printf/

Wrong output from printf of a number

int main()
{
double i=4;
printf("%d",i);
return 0;
}
Can anybody tell me why this program gives output of 0?
When you create a double initialised with the value 4, its 64 bits are filled according to the IEEE-754 standard for double-precision floating-point numbers. A float is divided into three parts: a sign, an exponent, and a fraction (also known as a significand, coefficient, or mantissa). The sign is one bit and denotes whether the number is positive or negative. The sizes of the other fields depend on the size of the number. To decode the number, the following formula is used:
1.Fraction × 2Exponent - 1023
In your example, the sign bit is 0 because the number is positive, the fractional part is 0 because the number is initialised as an integer, and the exponent part contains the value 1025 (2 with an offset of 1023). The result is:
1.0 × 22
Or, as you would expect, 4. The binary representation of the number (divided into sections) looks like this:
0 10000000001 0000000000000000000000000000000000000000000000000000
Or, in hexadecimal, 0x4010000000000000. When passing a value to printf using the %d specifier, it attempts to read sizeof(int) bytes from the parameters you passed to it. In your case, sizeof(int) is 4, or 32 bits. Since the first (rightmost) 32 bits of the 64-bit floating-point number you supply are all 0, it stands to reason that printf produces 0 as its integer output. If you were to write:
printf("%d %d", i);
Then you might get 0 1074790400, where the second number is equivalent to 0x40100000. I hope you see why this happens. Other answers have already given the fix for this: use the %f format specifier and printf will correctly accept your double.
Jon Purdy gave you a wonderful explanation of why you were seeing this particular result. However, bear in mind that the behavior is explicitly undefined by the language standard:
7.19.6.1.9: If a conversion specification is invalid, the behavior is undefined.248) If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.
(emphasis mine) where "undefined behavior" means
3.4.3.1: behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements
IOW, the compiler is under no obligation to produce a meaningful or correct result. Most importantly, you cannot rely on the result being repeatable. There's no guarantee that this program would output 0 on other platforms, or even on the same platform with different compiler settings (it probably will, but you don't want to rely on it).
%d is for integers:
int main()
{
int i=4;
double f = 4;
printf("%d",i); // prints 4
printf("%0.f",f); // prints 4
return 0;
}
Because the language allows you to screw up and you happily do it.
More specifically, '%d' is the formatting for an int and therefore printf("%d") consumes as many bytes from the arguments as an int takes. But a double is much larger, so printf only gets a bunch of zeros. Use '%lf'.
Because "%d" specifies that you want to print an int, but i is a double. Try printf("%f\n"); instead (the \n specifies a new-line character).
The simple answer to your question is, as others have said, that you're telling printf to print a integer number (for example a variable of the type int) whilst passing it a double-precision number (as your variable is of the type double), which is wrong.
Here's a snippet from the printf(3) linux programmer's manual explaining the %d and %f conversion specifiers:
d, i The int argument is converted to signed decimal notation. The
precision, if any, gives the minimum number of digits that must
appear; if the converted value requires fewer digits, it is
padded on the left with zeros. The default precision is 1.
When 0 is printed with an explicit precision 0, the output is
empty.
f, F The double argument is rounded and 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; if the precision
is explicitly zero, no decimal-point character appears. If a
decimal point appears, at least one digit appears before it.
To make your current code work, you can do two things. The first alternative has already been suggested - substitute %d with %f.
The other thing you can do is to cast your double to an int, like this:
printf("%d", (int) i);
The more complex answer(addressing why printf acts like it does) was just answered briefly by Jon Purdy. For a more in-depth explanation, have a look at the wikipedia article relating to floating point arithmetic and double precision.
Because i is a double and you tell printf to use it as if it were an int (%d).
#jagan, regarding the sub-question:
What is Left most third byte. Why it is 00000001? Can somebody explain?"
10000000001 is for 1025 in binary format.

Resources