Setting the digits after decimal point - c

So with float when I enter some number it prints with 6 decimal digits. I know I can adjust number of digits with something like "%.2f" (then number has only two). But my question is; is there any command that prints exact number of digits that are inputed.
Example if I input number 2.5
With only printf ("%f", number); it will print 2.500000
Or with printf ("%.2f", number); it will print 2.50
So is there any way that it could print 2.5 (with one decimal point) and in the same time if I input number like 2.51 it will print that number with 2 decimal points (2.51)

Yes. To do so, you would have to write some code to determine how many places after the decimal point you need to print.
I'll leave converting the pseudo-code below to actual code to you:
value = 2.51
places = 1
while(testDigitsAfterDecimal(value, places) { places ++ }
sprintf(format_string, "%%.%df", places)
printf(format_string, value)
In summary, if you write code to mathematically test for places following the decimal and keep count of how many places you need, you can then use that number in a sprintf to create a format string that specifies the desired number of places. With that done, you can pass that string to printf as the format to print your number.

Related

Can the precision of a floating point number be dynamically changed in C?

Is there a way to get the users input and then use that to decide what the precision of the outputted number should be?
What I mean is that I have a function to get the precision that the user wants and then I would want to be able to use that inputted number to decide how many decimal places should be shown. Normally when you are creating the program, you can decide it like this: printf("The number is: %0.2f", number);, but can that %0.2f also be dynamically changed so the user can decide if it should be 0.2, 0.3, 0.4, etc?
can that %0.2f also be dynamically changed so the user can decide if it should be 0.2, 0.3, 0.4, etc?
Yes.
int prec = 2;
printf("The number is: %0.*f", prec, number);
Change prec to be what you want at runtime.
Read the user’s input as characters. Test whether the user’s input is in an acceptable form. Count the number of digits the user entered. (You might count either the total number of digits or just the number after the decimal point, if any, as you choose.) Then convert the recorded characters to floating-point (e.g., use the strtod function).
When printing, using %.*f to fix the number of digits after the decimal point or %#.*g to fix the number of significant digits (total digits in the number from the first non-zero digit to the last non-zero digit). For either of these options, pass two arguments to printf: first the number of digits and second the number to be printed.

Decimal precision vs. number of digits in printf(), fprintf() in format %g vs. %f

After surfing for a while I could not find a clear explanation for this issue. Maybe anyone could clarify me why it works so.
In some code I am saving some double numbers to file by fprintf (after properly initializing the file stream). Because, a priori, I don't know what number is passed to my program, and in particular, what its format is, e.g. 0.00011 vs. 1.1e-4, I thought to use the format specifier %.5g instead of %.5f, where, I want to save my data with a 5-digit decimal precision.
However, it turns out that in %g the decimal precision of my saved numbers is correct if the numbers have a integer part equal to 0, otherwise is not, like for example:
FILE *fp;
fp = fopen("mydata.dat","w+"); //Neglecting error check for brevity
double value[2] = {0.00011,1.00011};
printf("\ng-format\n");
for(int i=0;i<2;i++){
frintf(fp,"%.5g\n",value[i]);
printf("%.5g\n",value[i]);
}
printf("\n\nf-format\n");
for(int i=0;i<2;i++){
frintf(fp,"%.5f\n",value[i]);
printf"%.5f\n",value[i]);
}
fclose(fp);
This produces the following output to file (and on the std stream):
g-format
0.00011
1.0001
f-format
0.00011
1.00011
So, why the choice of %g is 'eating' decimal digits as soon as the integer part is not zero?
The %g print x digits from the first digit which is not 0.
So if the x + 1 digit is not in the integer part, it will round it. And if the x + 1 digit is in the integer part it will display your number as scientific notation (rounded too)
The %f just display integer part plus x digit after.
It's not eating decimal digits. With %g the field width specifies the number of significant digits; 1.0001 has 5 significant digits, which is what "%.5g" calls for. That's different from %f, where the field width specifies the number of digits to the right of the decimal point.
To answer what appears to be OP's higher problem:
I want to save my data with a 5-digit decimal precision.
If code needs to save values with 6 total significant figures, use .5e which will print all values* with a non-zero leading digit and 5 places after a decimal point in exponential notation. Do not bother with "%g".
*Of course a value of 0.0 does not print with a leading non-zero digit.

Using printf to align doubles by decimal not working

I want to print doubles so that the decimals line up. For example:
1.2345
12.3456
should result in
1.2345
12.3456
I have looked everywhere, and the top recommendation is to use the following method (the 5s can be anything):
printf(%5.5f\n");
I have tried this with the following (very) simple program:
#include <stdio.h>
int main() {
printf("%10.10f\n", 0.523431);
printf("%10.10f\n", 10.43454);
return 0;
}
My output is:
0.5234310000
10.4345400000
Why doesn't this work?
The number before the . is minimum characters total, not just before the radix point.
printf("%21.10f\n", 0.523431);
When you use "%10.10f" you are telling printf() "use 10 character positions to print the number (optional minus sign, integer part, decimal point and decimal part). From these 10 positions, reserve 10 for decimal part. If this is not possible, ignore the first number and use whatever positions needed to print the number so that the number of decimal positions is kept"
So that's what's printf() is doing.
So you need to indicate how many positions you are going to use, for example, 15, and how many positions from these are going to be decimals.... for example, 9. That will leave you with 5 positions for the minus sign and integer part and one position for the decimal point.
That is, try "%15.9f" in your printf's

Count number of digits after `.` in floating point numbers?

This is one interview question.
How do you compute the number of digit after . in floating point number.
e.g. if given 3.554 output=3
for 43.000 output=0.
My code snippet is here
double no =3.44;
int count =0;
while(no!=((int)no))
{
count++;
no=no*10;
}
printf("%d",count);
There are some numbers that can not be indicated by float type. for example, there is no 73.487 in float type, the number indicated by float in c is 73.486999999999995 to approximate it.
Now how to solve it as it is going in some infinite loop.
Note : In the IEEE 754 Specifications, a 32 bit float is divided as 24+7+1 bits. The 7 bits indicate the mantissa.
I doubt this is what you want since the question is asking for something that's not usually meaningful with floating point numbers, but here is the answer:
int digits_after_decimal_point(double x)
{
int i;
for (i=0; x!=rint(x); x+=x, i++);
return i;
}
The problem isn't really solvable as stated, since floating-point is typically represented in binary, not in decimal. As you say, many (in fact most) decimal numbers are not exactly representable in floating-point.
On the other hand, all numbers that are exactly representable in binary floating-point are decimals with a finite number of digits -- but that's not particularly useful if you want a result of 2 for 3.44.
When I run your code snippet, it says that 3.44 has 2 digits after the decimal point -- because 3.44 * 10.0 * 10.0 just happens to yield exactly 344.0. That might not happen for another number like, say, 3.43 (I haven't tried it).
When I try it with 1.0/3.0, it goes into an infinite loop. Adding some printfs shows that no becomes exactly 33333333333333324.0 after 17 iterations -- but that number is too big to be represented as an int (at least on my system), and converting it to int has undefined behavior.
And for large numbers, repeatedly multiplying by 10 will inevitably give you a floating-point overflow. There are ways to avoid that, but they don't solve the other problems.
If you store the value 3.44 in a double object, the actual value stored (at least on my system) is exactly 3.439999999999999946709294817992486059665679931640625, which has 51 decimal digits in its fractional part. Suppose you really want to compute the number of decimal digits after the point in 3.439999999999999946709294817992486059665679931640625. Since 3.44 and 3.439999999999999946709294817992486059665679931640625 are effectively the same number, there's no way for any C function to distinguish between them and know whether it should return 2 or 51 (or 50 if you meant 3.43999999999999994670929481799248605966567993164062, or ...).
You could probably detect that the stored value is "close enough" to 3.44, but that makes it a much more complex problem -- and it loses the ability to determine the number of decimal digits in the fractional part of 3.439999999999999946709294817992486059665679931640625.
The question is meaningful only if the number you're given is stored in some format that can actually represent decimal fractions (such as a string), or if you add some complex requirement for determining which decimal fraction a given binary approximation is meant to represent.
There's probably a reasonable way to do the latter by looking for the unique decimal fraction whose nearest approximation in the given floating-point type is the given binary floating-point number.
The question could be interpreted as such:
Given a floating point number, find the shortest decimal representation that would be re-interpreted as the same floating point value with correct rounding.
Once formulated like this, the answer is Yes we can - see this algorithm:
Printing floating point numbers quickly and accurately. Robert G. Burger and R. Kent Dybvig. ACM SIGPLAN 1996 Conference on Programming Language Design and Implementation, June 1996
http://www.cs.indiana.edu/~dyb/pubs/FP-Printing-PLDI96.pdf
See also references from Compute the double value nearest preferred decimal result for a Smalltalk implementation.
Sounds like you need to either use sprintf to get an actual rounded version, or have the input be a string (and not parsed to a float).
Either way, once you have a string version of the number, counting characters after the decimal should be trivial.
It is my logic to count the number of digits.
number = 245.98
Take input as a string
char str[10] = "245.98";
Convert string to int using to count the number of digits before the decimal point.
int atoi(const char *string)
Use logic n/10 inside the while to count the numbers.
Numbers after decimal logic
Get the length of the string using strlen(n)
inside the while (a[i]! ='.'). then increment i
Later you can add step 3 logic output and step 4 logic output
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char num[100] = "345653.8768";
int count=0;
int i=0;
int len;
int before_decimal = atoi(num);
int after_decimal;
int total_Count;
printf("Converting string to int : %d\n", before_decimal);
//Lets count the numbers of digits before before_decimal
while(before_decimal!=0){
before_decimal = before_decimal/10;
count++;
}
printf("number of digits before decimal are %d\n",count);
//Lets get the number of digits after decimal
// first get the lenght of the string
len = strlen(num);
printf("Total number of digits including '.' are =%d\n",len);
//Now count the number after '.' decimal points
// Hope you know how to compare the strings
while(num[i]!='.'){
i++;
}
// total lenght of number - numberof digits after decimal -1(becuase every string ends with '\0')
after_decimal= len-i-1;
printf("Number of digits after decimal points are %d\n",after_decimal);
//Lets add both count Now
// ie. Number of digits before decmal and after decimal
total_Count = count+ after_decimal;
printf("Total number of digits are :%d\n",total_Count);
return 0;
}
Output:
Converting string to int : 345653
number of digits before decimal are 6
Total number of digits including '.' are =11
Number of digits after decimal points are 4
Total number of digits are :10
There are no general exact solutions. But you can convert the value to string and don't count the part exceeding the type's precision and exclude the trailing 0s or 9s. This will work for more cases but it still won't return the correct answer for all.
For example double's accuracy is about 15 digits if the input is a decimal string from the user (17 digits for binary-decimal-binary round trip), so for 73.486999999999995 there are 15 - 2 = 13 digits after the radix point (minus the 2 digits in the int part). After that there are still many 9s in the fractional part, subtract them from the count too. Here there are ten 9s which means there are 13 - 10 = 3 decimal digits. If you use 17 digits then the last digit which may be just garbage, exclude it before counting the 9s or 0s.
Alternatively just start from the 15 or 16th digit and iterate until you see the first non-0 and non-9 digit. Count the remaining digits and you'll get 3 in this case. Of course while iterating you must also make sure that the trailing is all 0s or all 9s
Request: e.g. if given 3.554 output = 3, for 43.000 output = 0
Problem: that's already a decimal like 0.33345. When this gets converted to a double, it might be something like 0.333459999...125. The goal is merely to determine that 0.33345 is a shorter decimal that will produce the same double. The solution is to convert it to a string with the right number of digits that results in the same original value.
int digits(double v){
int d=0; while(d < 50){
string t=DoubleToString(v,d); double vt = StrToDouble(t);
if(MathAbs(v-vt) < 1e-15) break;
++d;
}
return d;
}
double v=0.33345; PrintFormat("v=%g, d=%i", v,digits(v));// v=0.33345, d=5
v=0.01; PrintFormat("v=%g, d=%i", v,digits(v));// v=0.01, d=2
v=0.00001; PrintFormat("v=%g, d=%i", v,digits(v));// v=1e-05, d=5
v=5*0.00001; PrintFormat("v=%g, d=%i", v,digits(v));// v=5e-05, d=5
v=5*.1*.1*.1; PrintFormat("v=%g, d=%i", v,digits(v));// v=0.005, d=3
v=0.05; PrintFormat("v=%g, d=%i", v,digits(v));// v=0.05, d=2
v=0.25; PrintFormat("v=%g, d=%i", v,digits(v));// v=0.25, d=2
v=1/3.; PrintFormat("v=%g, d=%i", v,digits(v));// v=0.333333, d=15
What you can do is multiply the number by various powers of 10, round that to the nearest integer, and then divide by the same number of powers of 10. When the final result compares different from the original number, you've gone one digit too far.
I haven't read it in a long time, so I don't know how it relates to this idea, but How to Print Floating-Point Numbers Accurately from PLDI 1990 and 2003 Retrospective are probably very relevant to the basic problem.

Floating point results

In my C code:
I see some of the results in floating point come out to be for example 2.404567E+1. it seems to me that for results less then 1 the results turn out to be in some exponential series.
So, I have 2 questions:
how can I get the result rounded off to some digits ie instead of 5.23542342734 I just want the result to be 5.23
How can I get rid of exponential results and get results as for example 0.1648 instead of 1.6483517E-1
You can control the output format of printf() (I'm assuming you're talking about printf()?) in a number of ways. e.g.:
printf("%.2f\n", 5.23542342734); // Prints "5.23"
printf("%.4f\n", 1.6483517E-1); // Prints "0.1648"
See e.g. http://www.cplusplus.com/reference/clibrary/cstdio/printf/ (or a million other references out there on the internet) for more details on format specifiers for printf().
Adjust format string:
printf ("%.2f", float_data);
http://linux.die.net/man/3/printf
Or to use to truncate/approximate the value to some decimal places, i think the following should work:
trunc = floor (float_val * 10000) / 10000;
The above will preserve only upto 4 decimal places of float_var and store it to trunc. Use round () if needed.

Resources