Solved

Double and long double in g++

Posted on 2001-06-17
21
1,105 Views
Last Modified: 2010-08-05
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;
  }    



}

0
Comment
Question by:glebspy
  • 10
  • 7
  • 2
  • +1
21 Comments
 
LVL 30

Expert Comment

by:Axter
ID: 6200723
Exactly what precision are you looking for?
Give an example of what you want as an output.
0
 
LVL 1

Author Comment

by:glebspy
ID: 6200732
%x30
                                 1.111111111111111111111111e-05
              %x30
                                 1.111111111111111164357484e-05
              %x30
                                    0.0000111111112346407026052
0
 
LVL 30

Expert Comment

by:Axter
ID: 6200745
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
 
LVL 30

Expert Comment

by:Axter
ID: 6200748
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
 
LVL 1

Author Comment

by:glebspy
ID: 6200753
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
 
LVL 30

Expert Comment

by:Axter
ID: 6200755
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
 
LVL 30

Expert Comment

by:Axter
ID: 6200757
>>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
 
LVL 1

Author Comment

by:glebspy
ID: 6200760
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
 
LVL 1

Author Comment

by:glebspy
ID: 6200764
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
 
LVL 30

Expert Comment

by:Axter
ID: 6200766
Do you know how many bits are in your double adn long double?
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 30

Expert Comment

by:Axter
ID: 6200767
Do you know how many bits are in your double AND long double?
0
 
LVL 1

Author Comment

by:glebspy
ID: 6200769
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
 
LVL 1

Author Comment

by:glebspy
ID: 6200900
I'm back.
0
 
LVL 7

Accepted Solution

by:
KangaRoo earned 100 total points
ID: 6201069
>> 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
 
LVL 1

Author Comment

by:glebspy
ID: 6201100
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
 
LVL 9

Expert Comment

by:jasonclarke
ID: 6201759
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
 
LVL 7

Expert Comment

by:KangaRoo
ID: 6201883
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
 
LVL 1

Author Comment

by:glebspy
ID: 6201913
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
 
LVL 9

Expert Comment

by:jasonclarke
ID: 6201975
> 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
 
LVL 1

Author Comment

by:glebspy
ID: 6204730
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
 
LVL 1

Author Comment

by:glebspy
ID: 6351436
Thanks everyone ..
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now