Float value input error [duplicate] - c

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 7 years ago.
With working with floating point values I don't know why my C compiler or the System is behaving unexpectedly. Not making it so confusing. Here is a simple program to take float value input and print the same.
#include <stdio.h>
int main()
{
float num;
printf("Enter float value ");
scanf("%f", &num);
printf("Value = %f", num);
return 0;
}
On multiple run of the same code giving me different and weird outputs. Here are some sample runs.
Sample Run #1 Correct Output
Enter float value 12.0312
Value = 12.031200
Sample Run #2 Incorrect and unexpected output
Enter float value 324.123
Value = 324.122986
Sample Run #3 Incorrect and unexpected output
Enter float value 945.1234
Value = 945.123413
I don't know why the system is adding some garbage values at the end. I am using GNU GCC compiler in code::blocks.

Your float cannot represent every conceivable number exactly. It has limitations. The closest float to "324.123" is 324.122986...
If you need more precision, use double, but even that has its limits too.
A float will be correct (match similarly limited input) to at least FLT_DIG significant digits. To print a number to FLT_DIG significant digits use:
printf("%.*e", FLT_DIG - 1, num);
FLT_DIG is at least 6.
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, ... C11dr §5.2.4.2.2 11

printf("Value = %f", num);
It will add some value if like :
Enter float value 945.1234
Value = 945.123413
because float value always print a 6 digit after the decimal point
to avoid this you can use the statement like :
printf("Value = %.3f", num);
This Will Give You A desire output as you want
it will print only three number after the decimal point
you can set as per your requirement like
"%.2f" ->for 2 number after the decimal
"%.3f" ->for 3 number after the decimal
"%.4f" ->for 4 number after the decimal

Related

I made a simple C program to receive a float as input from user and display it in screen. But the value changes by a small amount while printing [duplicate]

This question already has answers here:
Why do I see a double variable initialized to some value like 21.4 as 21.399999618530273?
(14 answers)
Closed 1 year ago.
I made a simple C program to get a float as input from the user using scanf() function and dispay it using printf() function. But when the input number is quite large, the output deviates slightly. Why might that happen?
For example: if I give input as 2345, out put will be as expected. But if I give the output as 1234567898, the output will be unexpected.
#include <stdio.h>
int main()
{
float number;
scanf("%f", &number);
printf("The number %f", number);
return 0;
}
Single precision floating point (float) is good for approximately 6 significant decimal digits. double allows 15 significant figures. 1234567898.0 has 10 significant figures. Only the most significant first 6 digits can be relied on.

Using floorf to reduce the number of decimals

I would like to use the first five digits of a number for computation.
For example,
A floating point number: 4.23654897E-05
I wish to use 4.2365E-05.I tried the following
#include <math.h>
#include <stdio.h>
float num = 4.23654897E-05;
int main(){
float rounded_down = floorf(num * 10000) / 10000;
printf("%f",rounded_down);
return 0;
}
The output is 0.000000.The desired output is 4.2365E-05.
In short,say 52 bits are allocated for storing the mantissa.Is there a way to reduce the number of bits being allocated?
Any suggestions on how this can be done?
A number x that is positive and within the normal range can be rounded down approximately to five significant digits with:
double l = pow(10, floor(log10(x)) - 4);
double y = l * floor(x / l);
This is useful only for tinkering with floating-point arithmetic as a learning tool. The exact mathematical result is generally not exactly representable, because binary floating-point cannot represent most decimal values exactly. Additionally, rounding errors can occur in the pow, /, and * operations that may cause the result to differ slightly from the true mathematical result of rounding x to five significant digits. Also, poor implementations of log10 or pow can cause the result to differ from the true mathematical result.
I'd go:
printf("%.6f", num);
Or you can try using snprintf() from stdlib.h:
float num = 4.23654897E-05; char output[50];
snprintf(output, 50, "%f", num);
printf("%s", output);
The result is expected. The multiplication by 10000 yield 0.423.. the nearest integer to it is 0. So the result is 0. Rounding can be done using format specifier %f to print the result upto certain decimal places after decimal point.
If you check the return value of floorf you will see it returns If no errors occur, the largest integer value not greater than arg, that is ⌊arg⌋, is returned. where arg is the passed argument.
Without using floatf you can use %e or (%E)format specifier to print it accordingly.
printf("%.4E",num);
which outputs:
4.2365E-05
After David's comment:
Your way of doing things is right but the number you multiplied is wrong. The thing is 4.2365E-05 is 0.00004235.... Now if you multiply it with 10000 then it will 0.42365... Now you said I want the expression to represent in that form. floorf returns float in this case. Store it in a variable and you will be good to go. The rounded value will be in that variable. But you will see that the rounded down value will be 0. That is what you got.
float rounded_down = floorf(num * 10000) / 10000;
This will hold the correct value rounded down to 4 digits after . (not in exponent notation with E or e). Don't confuse the value with the format specifier used to represent it.
What you need to do in order to get the result you want is move the decimal places to the right. To do that multiply with larger number. (1e7 or 1e8 or as you want it to).
I would like to use the first five digits of a number for computation.
In general, floating point numbers are encoded using binary and OP wants to use 5 significant decimal digits. This is problematic as numbers like 4.23654897E-05 and 4.2365E-05 are not exactly representable as a float/double. The best we can do is get close.
The floor*() approach has problems with 1) negative numbers (should have used trunc()) and 2) values near x.99995 that during rounding may change the number of digits. I strongly recommend against it here as such solutions employing it fail many corner cases.
The *10000 * power10, round, /(10000 * power10) approach suffers from 1) power10 calculation (1e5 in this case) 2) rounding errors in the multiple, 3) overflow potential. The needed power10 may not be exact. * errors show up with cases when the product is close to xxxxx.5. Often this intermediate calculation is done using wider double math and so the corner cases are rare. Bad rounding using (some_int_type) which has limited range and is a truncation instead of the better round() or rint().
An approach that gets close to OP's goal: print to 5 significant digits using %e and convert back. Not highly efficient, yet handles all cases well.
int main(void) {
float num = 4.23654897E-05f;
// sign d . dddd e sign expo + \0
#define N (1 + 1 + 1 + 4 + 1 + 1 + 4 + 1)
char buf[N*2]; // Use a generous buffer - I like 2x what I think is needed.
// OP wants 5 significant digits so print 4 digits after the decimal point.
sprintf(buf, "%.4e", num);
float rounded = (float) atof(buf);
printf("%.5e %s\n", rounded, buf);
}
Output
4.23650e-05 4.2365e-05
Why 5 in %.5e: Typical float will print up to 6 significant decimal digits as expected (research FLT_DIG), so 5 digits after the decimal point are printed. The exact value of rounded in this case was about 4.236500171...e-05 as 4.2365e-05 is not exactly representable as a float.

Floating point number is rounding off in C [duplicate]

This question already has answers here:
Why are floating point numbers inaccurate?
(5 answers)
Closed 6 years ago.
i started learning c. Today, while i am working on a program, i found an interesting thing and i made another small program (similar to my issue) to check it.
#include<stdio.h>
int main(void)
{
float num1=867.0;
float num2=.6921;
printf("sum = %.4f \n",num1+num2);
return 0;
}
if i run the above program, i am getting 867.6921 as the answer. but if i changed the .4%f to %f the answer is changing to sum = 867.692078. why's the change in the output? Also, is there any way that i can get the answer without using the .4%f?
but if i changed the .4%f to %f the answer is changing to sum = 867.692078
printf rounds the result to that many digits after the floating point you specified, the default is .6. While rounding, it uses the current floating point rounding mode, the default is round to the nearest.
The float type has about seven digits of precision (can be anywhere from 6-9 digits). One alternative is to use g instead of f. This fixes the number of precise digits in the number, not just those after the decimal.
printf("sum = %.7g \n",num1+num2);
This produces output
sum = 867.6921
and will always give seven digits of precision for any input. Number formats would be like :
0.000000E+07
0000000
000000.0
00000.00
0000.000
000.0000
...etc

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.

Printing float variables [duplicate]

This question already has answers here:
C floating point precision [duplicate]
(6 answers)
Closed 8 years ago.
Below is my code and program output:
#include <stdio.h>
int main()
{
float salary;
printf("Please enter the salary : ");
scanf("%f", &salary);
printf("Your Salary is : %f\n", salary);
}
desktop:~$ ./a.out
Please enter the salary : 101.8889999
Your Salary is : 101.889000
desktop:~$
I tried many ways by entering random decimal values but sometime it printed correct values (as entered during scanf call) and sometimes it just prints something near to it. Why is it that the float variable values are not printing correct values as entered?
As per example above - if I enter 101.8889999 then the value saved in salary float variable is 101.889000?
I tried changing the last line as :
printf("Your Salary is : %10.9f\n", salary);
But still it gave below output:
Please enter the salary : 101.889000
Your Salary is : 101.888999939
Please enter the salary : 10.999999999
Your Salary is : 11.000000000
Which is the correct value to print float using printf and is it that float values may / may not be stored as exact values as entered in float variables?
In C and in many other languages, floating point numbers are stored with a fixed number of bits (usually 32 or 64) so there is a limit to how much precision they can have, and there are only a finite number of numbers that can be exactly represented with a float. For all other numbers, the float can only store an approximation. You can see how many bits are used by printing the value of 8 * sizeof(float).
Additionally, floating point operations generally have rounding errors which makes them ill-suited for dealing with money.
If you are dealing with money, you might consider storing the values as an integer that represents the number of pennies, or the hundredths of a penny, or something like that.

Resources