This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 5 years ago.
I came across this code recently. It produces strange results (lots of random digits after about the 18th digit.) I tried to find information on the limits to sprintf but could not find it. I am trying to figure out if the answer is actually correct or just garbage. When passed 0.025 (as a double) it prints out:
0.025000000000000001387778780781445675529539585113525390625
#define MAX_NUM_STR_LEN 128
void File_WriteNumber(File *fp, double value) {
char numbuf[MAX_NUM_STR_LEN];
int sz = sprintf(numbuf, "%.100g", value);
fwrite (numbuf , sizeof(char), sz, fp);
}
Answer is actually correct - not random digits.
double can typically represent exactly about 264 different values.
0.025 is not one of them with a binary64 double.
The closest double is 0.025000000000000001387....
The next closest double is 0.024999999999999997918...
sprintf() is doing just fine.
Related
This question already has answers here:
c++ pow(2,1000) is normaly to big for double, but it's working. why?
(3 answers)
Closed 1 year ago.
sorry if this is a silly question, I am relatively new to C programming. Thus I have probably misunderstood something fundamental about variables/overflows.
I made this simple program and I can't explain the result
#include <stdio.h>
#include <math.h>
int main() {
double number = pow(2, 1000);
printf("%f\n", number);
}
The result of that (compiled with gcc) is a humongous number that should never fit in a variable of type double: 10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376.000000
Usually when I try to assign a constant that is too large for it's type the compiler gives me an error.
So my question is: What is this number? Why am I not getting any errors? Is the variable number actually storing this value? Plainly, what's happening?
Doubles are not stored like integers. This page explains how double are representated in memory
Doubles contain 1 byte of sign, 11 bits for the exponent and 53 bits for the sigificand precision. Thus you can store numbers up to 1.7*10^308. Thus, your number cand be represented in a double (although with a limited precision). When printing it with %f, you just get its numerical value (approximated).
In C, double type can fit more than 300 decimal digits! A double is stored in 8 bytes, holding a number in the range 2.3E-308 to 1.7E+308 (15 decimal places accuracy).
Reference: https://www.tutorialspoint.com/cprogramming/c_data_types.htm
This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 2 years ago.
N00b here, in C I assign a value using
#include <stdio.h>
int main(){
double test_num;
test_num = 0.99999999;
printf("%11.10f\t",test_num);
printf("foo");
return 1;
}
Here's the print output
0.9999999900 foo
Here's the value from debugger (Clion 2020.1, LLDB 9.0.1, Bundled compiler)
0.99999998999999994
Why are these numbers different? The compiled/runtime value seems to be the debugger value which is breaking my program
The closest IEEE 754 64-bit binary float to 0.99999999 is 0.99999998999999994975240724670584313571453094482421875. That is the value your program is actually working with. It differs from 0.99999999 by about 5e-17. Is that difference big enough to matter in your program?
0.99999998999999994 is the result of truncating to 17 significant digits. Rounding to 10 digits would get the printf result.
This question already has an answer here:
Rounding issue when using long long on PIC
(1 answer)
Closed 4 years ago.
char q[150];
void main(void){
System_Initialization();
UART_Init_2();
while(1){
double A=23.045610;
sprintf(q,"%f\r\n",A);
UART_Tx_2(q);}}
When I Read value of A its give 23.045410 instead of 23.045610
anyone know why this will happened?
i am using PIC18F67k22 controller and Xc8 Compiler
On the PIC18, the data types float and double are the same, and only 32 bits long. That is not enough bits to store more than five or so decimal digits. Therefore you can expect some rounding error at the end of the decimals.
This question already has answers here:
Why are floating point numbers inaccurate?
(5 answers)
Why is scanf taking the wrong input for large float numbers? [duplicate]
(1 answer)
Is floating point math broken?
(31 answers)
Closed 5 years ago.
I'm having problems with strtof conversions, some values it works well but another ones it returns +1 or -1 of the value. My program reads the value from a file but for simplicity I have tried putting directly the value to strtof and it has the same behavior.
My simple code:
#include <stdlib.h>
int main(int argc, char **argv)
{
printf("%f", strtof("17309217",NULL));
}
It returns
17309216.000000
The same value that it gives if I convert "17309216" or "17309215".
I have been doing some more tests and it seems a "pattern", "17309214" works well but "17309213", "17309212" and "17309211" all return "17309212". After this "17309210" works well but "17309209", "17309208" and "17309207" return "17309208", and so on...
What is the explanation for this behaviour? Now I convert the string with other methods, I don't need a method to convert it. I only want to know why strtof is doing this, so I can decide where I can use it and where can't.
I have been reading some other questions asked related to wrong conversions but all are related to the decimal rounding, not an entire unit.
Thanks in advance,
You're converting to a 32-bit floating point which may not have the precision to handle that many digits.
This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 6 years ago.
I have used this code to generate root, if output is not integer it should return -1.
#include <stdio.h>
#include <math.h>
int main(){
long int n=0;
long int num,p,reti;
double ret;
scanf("%ld",&n);
while(n!=0){
scanf("%ld %ld",&p,&num);
ret=pow(num,(double)1/p);
reti=(int)ret;
printf("%lf %lf\n",ret,(double)reti);
if(ret!=(double)reti){
reti=-1;
}
printf("%ld\n",reti);
n=n-1;
}
return 0;
}
but if I give input as
1
5 3125
it should give 5, but it is giving -1.
ret is not exactly 5.00000, you're just not printing enough digits after the decimal point to see the difference. Change your format to %.20lf and it will show 5.00000000000000088818, which is not equal to (double)5.
This is because pow() works with floating point numbers, and there are some inaccuracies introduced. (double)1/5 can't be represented exactly in binary floating point. See Is floating point math broken?
The reason why is this block of code:
if(ret!=(double)reti){
reti=-1;
}
reti is some integer value - converting it to double will convert it to a double representation, but odds are good that it will not be exactly equal to ret. This is a common issue with floating point numbers - generally speaking, you should never compare pure equality. Instead, you should compare the difference between the two numbers and confirm that it's within some acceptable error range (e.g. 0.00001).