glebspy
asked on
Double and long double in g++
The output of the following code is
%x30
1.111111111111111164357484 e-05
%x30
1.111111111111111164357484 e-05
%x30
0.000011111111234640702605 2
but pil is a long double variable and I want it to be printed to higher precision than pid.
How can I do this?
How can I do this using c-style sprintf?
#include<iostream>
#include<iomanip>
#include<typeinfo>
#include<fstream>
#include<string>
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<dirent.h>
#include<sys/dirent.h>
#include<fcntl.h>
#include<errno.h>
#include<paths.h>
#include<math.h>
void main(void){
long double pil=0.00001111111111111111 1111111111 1111111111 1111111111 1;
double pid=pil;
float pi=pil;
cout.precision(50);
string t;
{
cout<<"%x30"<<endl;
char*z=new char[300];
sprintf(z,"%50.25Lg",pil);
t=z;
delete[]z;
cout<<t<<endl;
}
{
cout<<"%x30"<<endl;
char*z=new char[300];
sprintf(z,"%50.25g",pid);
delete[]z;
t=z;
cout<<t<<endl;
}
{
cout<<"%x30"<<endl;
char*z=new char[300];
sprintf(z,"%50.25f",pi);
delete[]z;
t=z;
cout<<t<<endl;
}
}
%x30
1.111111111111111164357484
%x30
1.111111111111111164357484
%x30
0.000011111111234640702605
but pil is a long double variable and I want it to be printed to higher precision than pid.
How can I do this?
How can I do this using c-style sprintf?
#include<iostream>
#include<iomanip>
#include<typeinfo>
#include<fstream>
#include<string>
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<dirent.h>
#include<sys/dirent.h>
#include<fcntl.h>
#include<errno.h>
#include<paths.h>
#include<math.h>
void main(void){
long double pil=0.00001111111111111111
double pid=pil;
float pi=pil;
cout.precision(50);
string t;
{
cout<<"%x30"<<endl;
char*z=new char[300];
sprintf(z,"%50.25Lg",pil);
t=z;
delete[]z;
cout<<t<<endl;
}
{
cout<<"%x30"<<endl;
char*z=new char[300];
sprintf(z,"%50.25g",pid);
delete[]z;
t=z;
cout<<t<<endl;
}
{
cout<<"%x30"<<endl;
char*z=new char[300];
sprintf(z,"%50.25f",pi);
delete[]z;
t=z;
cout<<t<<endl;
}
}
ASKER
%x30
1.111111111111111111111111 e-05
%x30
1.111111111111111164357484 e-05
%x30
0.000011111111234640702605 2
1.111111111111111111111111
%x30
1.111111111111111164357484
%x30
0.000011111111234640702605
int main(int argc, char* argv[])
{
char buffer[1024];
long double num_list[5] = {
1.123456789012345678901234 5,
0.123456789012345678901234 5,
543.1234567890123456789012 345,
1.000011111111234640702605 2,
1.000011111119234640702605 2};
for (int d = 0;d < 5;d++)
{
sprintf(buffer,"%1.25e",nu m_list[d]) ;
printf("Value of buffer = %s\n",buffer);
}
return 0;
}
{
char buffer[1024];
long double num_list[5] = {
1.123456789012345678901234
0.123456789012345678901234
543.1234567890123456789012
1.000011111111234640702605
1.000011111119234640702605
for (int d = 0;d < 5;d++)
{
sprintf(buffer,"%1.25e",nu
printf("Value of buffer = %s\n",buffer);
}
return 0;
}
The above example code outputs the following:
Value of buffer = 1.123456789012345700000000 0e+000
Value of buffer = 1.234567890123456800000000 0e-001
Value of buffer = 5.431234567890123800000000 0e+002
Value of buffer = 1.000011111111234600000000 0e+000
Value of buffer = 1.000011111119234700000000 0e+000
Is this what you're looking for?
Value of buffer = 1.123456789012345700000000
Value of buffer = 1.234567890123456800000000
Value of buffer = 5.431234567890123800000000
Value of buffer = 1.000011111111234600000000
Value of buffer = 1.000011111119234700000000
Is this what you're looking for?
ASKER
I don't think so.
The point is to compare and contrast the precision stored in a long double relative to a double, relative to a float.
I need to be able to demonstrate that a long double holds more digits than a double. That is what I want my programme to do. As you can see, it doesn't.
The point is to compare and contrast the precision stored in a long double relative to a double, relative to a float.
I need to be able to demonstrate that a long double holds more digits than a double. That is what I want my programme to do. As you can see, it doesn't.
To change the precision in sprintf/printf you need to add a decimal before the field type character, and then add numbers before and after the decimal.
Example:
printf("%3.4i", number);
The above example outputs a number with 3 digits to the left of the decimal, and 4 digits to the right of the decimal.
Example:
printf("%3.4i", number);
The above example outputs a number with 3 digits to the left of the decimal, and 4 digits to the right of the decimal.
>>The point is to compare and contrast the precision
>>stored in a long double relative to a double, relative
>>to a float
This depends on your computer. Does it use a 32bit Integer or a 64bit Integer.
What is your OS, and what compiler are you using?
>>stored in a long double relative to a double, relative
>>to a float
This depends on your computer. Does it use a 32bit Integer or a 64bit Integer.
What is your OS, and what compiler are you using?
ASKER
I don't think so.
The point is to compare and contrast the precision stored in a long double relative to a double, relative to a float.
I need to be able to demonstrate that a long double holds more digits than a double. That is what I want my programme to do. As you can see, it doesn't.
The point is to compare and contrast the precision stored in a long double relative to a double, relative to a float.
I need to be able to demonstrate that a long double holds more digits than a double. That is what I want my programme to do. As you can see, it doesn't.
ASKER
sorry, I didn't intend to repost that.
vil@vela:~>uname -a
SunOS vela 5.7 Generic_106541-08 sun4m sparc sun4m
vil@vela:~>g++ -v
Reading specs from /usr/local/lib/gcc-lib/spa rc-sun-sol aris2.7/2. 95.1/specs
gcc version 2.95.1 19990816 (release)
vil@vela:~>uname -a
SunOS vela 5.7 Generic_106541-08 sun4m sparc sun4m
vil@vela:~>g++ -v
Reading specs from /usr/local/lib/gcc-lib/spa
gcc version 2.95.1 19990816 (release)
Do you know how many bits are in your double adn long double?
Do you know how many bits are in your double AND long double?
ASKER
No. The expected functionality is of course that long double should have more.
I can try to find out if there's a simple way.
I'm going to lunch now, back in an hour or so.
I can try to find out if there's a simple way.
I'm going to lunch now, back in an hour or so.
ASKER
I'm back.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
hmm,
I found a float.h in /usr/bin/include, but I don't explicitly include<float.h>. (It contains as you suggest the identifiers DBL_DIG, DBL_EPS, LDBL_DIG and LDBL_EPS.)
I tried putting
cout<<DBL_DIG<<endl; in my executable but it gave me an error message. On the other hand it doesn't complain when I declare a long double.
I don't understand this behaviour. If you can explain it and give me a prescription, I'd be grateful. It sounds like it would make a difference if I included float.h, but I don't understand why.
I found a float.h in /usr/bin/include, but I don't explicitly include<float.h>. (It contains as you suggest the identifiers DBL_DIG, DBL_EPS, LDBL_DIG and LDBL_EPS.)
I tried putting
cout<<DBL_DIG<<endl; in my executable but it gave me an error message. On the other hand it doesn't complain when I declare a long double.
I don't understand this behaviour. If you can explain it and give me a prescription, I'd be grateful. It sounds like it would make a difference if I included float.h, but I don't understand why.
why not just use sizeof?
#include <iostream>
using namespace std;
int main()
{
cout << sizeof(double) << endl; // 8 with VC++ on Win32
cout << sizeof(long double) << endl; // 8 with VC++ on Win32
return 0;
}
#include <iostream>
using namespace std;
int main()
{
cout << sizeof(double) << endl; // 8 with VC++ on Win32
cout << sizeof(long double) << endl; // 8 with VC++ on Win32
return 0;
}
I only pointed you at <float.h> to take a look at those #defines, it is not required to #include this file when using floating points.
If double and long double actually have different sizes on your system, then the value #defined for DBL_DIG is different from that #defined with LDBL_DIG and it is easier to read that from the header then finding it out by actually writing the code for it.
With MinGW gcc there is no difference between double and long double, when you declare a long double the is compiled the same as when you declared a double. They are
#define DBL_DIG 15
#define DBL_EPSILON 1.1102230246251568e-16
#define LDBL_DIG 15
#define LDBL_EPSILON 1.1102230246251568e-16L
------
#include <float.h>
#include <iostream>
int main()
{
cout << DBL_DIG << endl;
cout << DBL_EPSILON << endl;
cout << LDBL_DIG << endl;
cout << LDBL_EPSILON << endl;
}
If double and long double actually have different sizes on your system, then the value #defined for DBL_DIG is different from that #defined with LDBL_DIG and it is easier to read that from the header then finding it out by actually writing the code for it.
With MinGW gcc there is no difference between double and long double, when you declare a long double the is compiled the same as when you declared a double. They are
#define DBL_DIG 15
#define DBL_EPSILON 1.1102230246251568e-16
#define LDBL_DIG 15
#define LDBL_EPSILON 1.1102230246251568e-16L
------
#include <float.h>
#include <iostream>
int main()
{
cout << DBL_DIG << endl;
cout << DBL_EPSILON << endl;
cout << LDBL_DIG << endl;
cout << LDBL_EPSILON << endl;
}
ASKER
ok, I understand.
Do you have any help for my original question, namely why a long double doesn't seem to hold any more precision than a double (despite the fact that they have different #defines in float.h, which I'm not including) and whether and how I can change this situation.
Do you have any help for my original question, namely why a long double doesn't seem to hold any more precision than a double (despite the fact that they have different #defines in float.h, which I'm not including) and whether and how I can change this situation.
> namely why a long double doesn't seem to hold any more
precision
most likely due to what is reasonable to implement on the hardware on a given platform, i.e. 64 bit floating point arithmetic is sensibly implemented in hardware on x86 platforms, but maybe 128 bit arithmetic is not.
C++ itself says nothing other than sizeof(long double) >= sizeof(double) >= sizeof(float). So, a compiler *could* have them all the same.
The only alternative that I know is to have code to deal with higher precision numbers. There are abitrary precision number classes out there.
precision
most likely due to what is reasonable to implement on the hardware on a given platform, i.e. 64 bit floating point arithmetic is sensibly implemented in hardware on x86 platforms, but maybe 128 bit arithmetic is not.
C++ itself says nothing other than sizeof(long double) >= sizeof(double) >= sizeof(float). So, a compiler *could* have them all the same.
The only alternative that I know is to have code to deal with higher precision numbers. There are abitrary precision number classes out there.
ASKER
The contents of my float.h file give me good reason to believe that >64bit precision is implemented in hardware on my platform.
The question is therefore not to do with hardware, unless you disagree with this conclusion.
The question is therefore not to do with hardware, unless you disagree with this conclusion.
ASKER
Thanks everyone ..
Give an example of what you want as an output.