Formatting floating point numbers in C [duplicate] - c

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/

Related

Is there a way to automatically printf a float to the number of decimal places it has?

I've written a program to display floats to the appropriate number of decimal places:
#include <stdio.h>
int main() {
printf("%.2f, %.10f, %.5f, %.5f\n", 1.27, 345.1415926535, 1.22013, 0.00008);
}
Is there any kind of conversion character that is like %.(however many decimal places the number has)f or do they always have to be set manually?
Is there a way to automatically printf a float to the number of decimal places it has?
Use "%g". "%g" lops off trailing zero digits.
... unless the # flag is used, any trailing zeros are removed from the fractional portion of the result and the decimal-point character is removed if there is no fractional portion remaining. C17dr § 7.21.6.1 8.
All finite floating point values are exactly representable in decimal - some need many digits to print exactly. Up to DBL_DECIMAL_DIG from <float.h> (typically 17) significant digits is sufficient - rarely a need for more.
Pass in a precision to encourage enough output, but not too much.
Remember values like 0.00008 are not exactly encoded in the typical binary floating point double, but a nearby value is used like 8.00000000000000065442...e-05
printf("%.*g\n", DBL_DECIMAL_DIG, some_double);
printf("%.17g, %.17g, %.17g, %.17g\n", 1.27, 345.1415926535, 1.22013, 0.00008);
// 1.27, 345.14159265350003, 1.2201299999999999, 8.0000000000000007e-05
DBL_DIG (e.g. 15) may better meet OP's goal.
printf("%.15g, %.15g, %.15g, %.15g\n", 1.27, 345.1415926535, 1.22013, 0.00008);
// 1.27, 345.1415926535, 1.22013, 8e-05
Function to print a double - exactly may take 100s of digits.
sprintf() could help you
There is no direct way to do this in my experience
here is a simple algorithm to help you with this function
munber = float/double input
n = number of decimal places in float/double
char format[999];
sprintf(format ,"%%.%df" ,n);
printf(format, number);
sprintf is like printf but instead of writing to stdout, sprintf writes to a string.
Now you are left with finding number of digits after the precision.

in c, asking to scanf 1 digit after point and getting gybrish [duplicate]

This question already has answers here:
How to only accept a certain precision (so many decimals places) in scanf?
(4 answers)
Closed 5 years ago.
i am wishing to scan a float with 1 digit accuration after FP.
this is the test code:
#include <stdio.h>
void main()
{
float f;
scanf("%.1f",&f);
printf("%f",f);
}
i have entered 1.234, expecting to see 1.2 but instead
i was seeing this weird result :
-107374176.000000
running VS2010, any ideas how to fix please?
It prints random numbers because the call to scanf failed and you are printing an uninitialized variable.
The floating point precision specification only applies in calls to printf, not to scanf. The format specifier you gave is simply invalid.
You would have known the call failed, had you checked the return value of scanf, which is equal to the number of format specifiers that were successfully converted.
If you want a specific accuracy for the number, you'd need to read it in full and then preform the truncation/rounding operation.
You can't do that, you can make scanf() read a specific number of characters if you want like
float value;
scanf("%4f", &value);
and suppose the input is
43.23
it will read
43.2
but you can't specify precision.
what you can do is
float value;
if (scanf("%f", &value) == 1)
printf("%.2f\n", value);
after all, the precision is limited by the binary representation, so making it have only two decimal places is pointless since in arithmetic operations it might be rounded.
scanf("%.1f",&f);
Your format specifier in the scanf() function is incorrect; you cannot specify the number of decimal places you want in as input for scanf(), you can only do that when you want to output the floating point number using printf().
You need to accept the input in full with scanf():
scanf("%f",&f);
And then print out the number you want to the desired number of decimal places:
printf("%.1f", f);
This will print out 1.234 as 1.2.
Also, main() needs to have a return type of int by default; void main() is not legal in C or C++. Even if you do not want to return anything from main(), define it as:
int main(void)

How can variable field width be implemented with printf()?

The question is :
How can variable field width be implemented using printf()? That is, instead of %8d, the width should be specified at run time.
I came across some C code on the Internet based on the question above but as I am new to C programming I haven't been able to make heads or tails of the code.
I am posting the code below:
#include <stdio.h>
int main()
{
const char text[] = "Hello world";
int i;
for ( i = 1; i < 12; ++i )
{
printf("\"%.*s\"\n", i, text);
}
return 0;
}
First of all, let me tell you, the code you have shown is about controlling the precision, not the field width. For a shortened form**
%A.B<format specifier>
A denotes the field width and B makes the precision.
Now, quoting the C11 standard, chapter §7.21.6.1, fprintf() (emphasis mine)
Each conversion specification is introduced by the character %. After the %, the following
appear in sequence:
[..]
An optional precision that gives the minimum number of digits to appear for the d, i,
o, u, x, and X conversions, the number of digits to appear after the decimal-point
character for a, A, e, E, f, and F conversions, the maximum number of significant
digits for the g and G conversions, or the maximum number of bytes to be written for s conversions. 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. If a precision appears with any other
conversion specifier, the behavior is undefined.
and
As noted above, a field width, or precision, or both, may be indicated by an asterisk. In
this case, an int argument supplies the field width or precision. [...]
So, in your case,
printf("\"%.*s\"\n", i, text);
the precision will be supplied by i which can hold different values at run-time.
The complete format (broken down in separate lines for ease of readability)
%
<Zero or more flags>
<optional minimum field width>
<optional precision>
<optional length modifier>
<A conversion specifier character>

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.

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