Double and long double in g++

The output of the following code is

%x30
                    1.111111111111111164357484e-05
%x30
                    1.111111111111111164357484e-05
%x30
                       0.0000111111112346407026052


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.000011111111111111111111111111111111111111111111111;
  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;
  }    



}

LVL 1
glebspyAsked:
Who is Participating?
 
KangaRooConnect With a Mentor Commented:
>> a simple way
Eh, yes, check the headers that #define limits for floating point vars, in my MinGW GCC that is <float.h>. The #defines you need to see are probably DBL_DIG and DBL_EPSILON

>> The expected functionality is of course that long double should have more
Indeed, but at least with GCC on Win32 there is no difference between double and long double (both are 64 bit floating points).
0
 
AxterCommented:
Exactly what precision are you looking for?
Give an example of what you want as an output.
0
 
glebspyAuthor Commented:
%x30
                                 1.111111111111111111111111e-05
              %x30
                                 1.111111111111111164357484e-05
              %x30
                                    0.0000111111112346407026052
0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
AxterCommented:
int main(int argc, char* argv[])
{
     char buffer[1024];
     long double num_list[5] = {
          1.1234567890123456789012345,
          0.1234567890123456789012345,
          543.1234567890123456789012345,
          1.0000111111112346407026052,
          1.0000111111192346407026052};
     for (int d = 0;d < 5;d++)
     {
          sprintf(buffer,"%1.25e",num_list[d]);
          printf("Value of buffer = %s\n",buffer);
     }
               
     return 0;
}
0
 
AxterCommented:
The above example code outputs the following:
Value of buffer = 1.1234567890123457000000000e+000
Value of buffer = 1.2345678901234568000000000e-001
Value of buffer = 5.4312345678901238000000000e+002
Value of buffer = 1.0000111111112346000000000e+000
Value of buffer = 1.0000111111192347000000000e+000

Is this what you're looking for?
0
 
glebspyAuthor Commented:
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.
0
 
AxterCommented:
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.
0
 
AxterCommented:
>>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?
0
 
glebspyAuthor Commented:
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.
0
 
glebspyAuthor Commented:
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/sparc-sun-solaris2.7/2.95.1/specs
gcc version 2.95.1 19990816 (release)
0
 
AxterCommented:
Do you know how many bits are in your double adn long double?
0
 
AxterCommented:
Do you know how many bits are in your double AND long double?
0
 
glebspyAuthor Commented:
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.
0
 
glebspyAuthor Commented:
I'm back.
0
 
glebspyAuthor Commented:
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.
0
 
jasonclarkeCommented:
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;
}
0
 
KangaRooCommented:
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;
}
0
 
glebspyAuthor Commented:
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.

0
 
jasonclarkeCommented:
> 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.
0
 
glebspyAuthor Commented:
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.
0
 
glebspyAuthor Commented:
Thanks everyone ..
0
All Courses

From novice to tech pro — start learning today.