Displaying big doubles in C [duplicate] - c

This question already has answers here:
Printf big double value with high precision in C
(4 answers)
Closed 4 years ago.
I've got a problem with diplaying big doubles.
Here's a code I've prepared:
#include <stdio.h>
#include <float.h>
#define M_PI 3.141592653589793238462643383279502884197169399375105820974944
int main()
{
printf("%.70f\n",M_PI);
return 0;
}
It displays:
3.1415926535897931159979634685441851615905761718750000000000000000000000
But once I change M_PI for DBL_MAX everything is shown correctly.
What's worse is that when dot in M_PI definition is removed (leaving a really big number) the result is 0.
What do I do wrong? How can I display some huge numbers?

In IEEE 754 64-bit binary floating point, the most common implementation of double, 3.141592653589793115997963468544185161590576171875 is the closest representable number to 3.141592653589793238462643383279502884197169399375105820974944, and so is what should be printed. In most cases, rounding error on conversion to double will appear after about 16 decimal digits.
DBL_MAX, by its definition, has to be exactly representable as a double, so there is no rounding error on its conversion from decimal string to double.

Related

C pow() function printing gigantic numbers? [duplicate]

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

C double assignment incorrect at runtime (but correct with printf) [duplicate]

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.

Why is %f working incorrectly for large double numbers in print statement? [duplicate]

This question already has answers here:
Why does floating-point arithmetic not give exact results when adding decimal fractions?
(31 answers)
Closed 3 years ago.
double a = 1E100
printf("%f", a);
It seems to be printing a different value other than 1 followed by a 100 zeros:
10000000000000000159028911097599180468360808563945281389781327557747838772170381060813469985856815104
What might be the problem here?
The double type, assuming it uses IEEE 754 double precision floating point representation, only holds about 16 decimal digits of precision.
So any decimal digits after that will only be an approximate value, i.e. the closest value to 1E100 that it can represent.

Unexpected behavior for floating point number in C programming [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 3 years ago.
I'm getting confused with floating point number in c programming
#include <stdio.h>
int main()
{
float a = 255.167715;
printf("%f", a);
return 0;
} // it print value of 255.167709
Why it produce value like so? To be honest can you tell how it actually works in C programming?
In binary, 255.167715 is approximately 11111111.001010101110111101011110110010000000110001110…2. In your C implementation, most likely, the source code 255.167715 is converted to 11111111.0010101011101111010111101100100000001100011102, which is 255.16771499999998695784597657620906829833984375, because 255.167715 is a double constant, and that is the closest value representable in your implementation’s double type to the decimal number 255.167715, because the double type has only 53-bit significands. (A significand is the fraction portion of a floating-point number. There is also a sign and an exponent portion.)
Then, for float a = 255.167715;, this double value is converted to float. Since the float type has only 24-bit significands, the result is 11111111.00101010111011112, which is 255.1677093505859375 in decimal.
When you print this with the default formatting of %f, six digits after the decimal place are used, so it prints “255.167709”.
The short answer is that there is no such single-precision floating-point number as 255.167715. This is true for any computer using IEEE 754 floating-point formats; the situation is not unique to C. As a single-precision floating-point number, the closest value is 255.167709.
Single-precision floating point gives you the equivalent of 7 or so decimal digits of precision. And as you can see, the input you gave and the output you got agreed to seven places, namely 255.1677. Any digits past that are essentially meaningless.
For much more about the sometimes-surprising aspects of floating-point math, see "Is floating point math broken?".

Compare integer and float [duplicate]

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).

Resources