Link to home
Start Free TrialLog in
Avatar of glebspy
glebspy

asked on

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



}

Avatar of Axter
Axter
Flag of United States of America image

Exactly what precision are you looking for?
Give an example of what you want as an output.
Avatar of glebspy
glebspy

ASKER

%x30
                                 1.111111111111111111111111e-05
              %x30
                                 1.111111111111111164357484e-05
              %x30
                                    0.0000111111112346407026052
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;
}
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?
Avatar of glebspy

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.
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.
>>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?
Avatar of glebspy

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.
Avatar of glebspy

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/sparc-sun-solaris2.7/2.95.1/specs
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?
Avatar of glebspy

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.
Avatar of glebspy

ASKER

I'm back.
ASKER CERTIFIED SOLUTION
Avatar of KangaRoo
KangaRoo

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of glebspy

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.
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;
}
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;
}
Avatar of glebspy

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.

> 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.
Avatar of glebspy

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.
Avatar of glebspy

ASKER

Thanks everyone ..