Newbye quetion: Why a double can store more number than a long ?

  • Thread starter jose luis fernandez diaz
  • Start date
J

jose luis fernandez diaz

Hi,

My OS is:

cronos:jdiaz:tmp>uname -a
HP-UX cronos B.11.11 U 9000/800 820960681 unlimited-user license


I compile in 64-bits mode the program below:

cronos:jdiaz:tmp>cat kk.C
#include <iostream.h>
#include <limits>

int main()
{
long l_min = numeric_limits<long>::min();
long l_max = numeric_limits<long>::max();
double d_min = numeric_limits<double>::min();
double d_max = numeric_limits<double>::max();
cout << sizeof(long) << " " << sizeof(double) << endl;
cout << l_min << " " << l_max << " " << d_min << " " << d_max <<
endl;


return 0;
}
cronos:jdiaz:tmp>a.out
8 8
-9223372036854775808 9223372036854775807 2.22507e-308 1.79769e+308



The double and long types have the same size, but the double limits
are bigger. Can anyone explein this to me ?

Thanks,
Jose Luis.
 
L

Lew Pitcher

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hi,

My OS is:

cronos:jdiaz:tmp>uname -a
HP-UX cronos B.11.11 U 9000/800 820960681 unlimited-user license


I compile in 64-bits mode the program below:

cronos:jdiaz:tmp>cat kk.C
#include <iostream.h>
#include <limits>

int main()
{
long l_min = numeric_limits<long>::min();
long l_max = numeric_limits<long>::max();
[snip]

Well, since you are using a different language from C, we in the comp.lang.c
newsgroup cannot assist you. Your question does not relate to C, and should be
(presumably, from the crossposting, was) asked in a forum related to the
language in which you wrote your example. This appears to be C++, so that forum
would be comp.lang.c++.


- --
Lew Pitcher
IT Consultant, Enterprise Application Architecture,
Enterprise Technology Solutions, TD Bank Financial Group

(Opinions expressed are my own, not my employers')
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (MingW32)

iD8DBQFAljf6agVFX4UWr64RAnujAJwJ4mOsZZ9THxxul4vwzrvTo/acYwCcDLiJ
+EqfYBtEqbJjlf/u1b7p2DQ=
=7HZL
-----END PGP SIGNATURE-----
 
K

Karl Heinz Buchegger

jose said:
Hi,

My OS is:

cronos:jdiaz:tmp>uname -a
HP-UX cronos B.11.11 U 9000/800 820960681 unlimited-user license

I compile in 64-bits mode the program below:

cronos:jdiaz:tmp>cat kk.C
#include <iostream.h>
#include <limits>

int main()
{
long l_min = numeric_limits<long>::min();
long l_max = numeric_limits<long>::max();
double d_min = numeric_limits<double>::min();
double d_max = numeric_limits<double>::max();
cout << sizeof(long) << " " << sizeof(double) << endl;
cout << l_min << " " << l_max << " " << d_min << " " << d_max <<
endl;

return 0;
}
cronos:jdiaz:tmp>a.out
8 8
-9223372036854775808 9223372036854775807 2.22507e-308 1.79769e+308

The double and long types have the same size, but the double limits
are bigger. Can anyone explein this to me ?

Well.

1.79769E308

does not mean that the number is accurate to the last digit. It means

1797690000000000000000....000000.....000000
and the next smallest number is probably something like
1797680000000000000000....000000.....000000

so there are large gaps between numbers. Those gaps get smaller when
the numbers get smaller.
 
J

Jeff Schwab

jose said:
Hi,

My OS is:

cronos:jdiaz:tmp>uname -a
HP-UX cronos B.11.11 U 9000/800 820960681 unlimited-user license


I compile in 64-bits mode the program below:

cronos:jdiaz:tmp>cat kk.C
#include <iostream.h>

#include said:
#include <limits>

int main()
{

using namespace std;
long l_min = numeric_limits<long>::min();
long l_max = numeric_limits<long>::max();
double d_min = numeric_limits<double>::min();
double d_max = numeric_limits<double>::max();
cout << sizeof(long) << " " << sizeof(double) << endl;
cout << l_min << " " << l_max << " " << d_min << " " << d_max <<
endl;


return 0;
}
cronos:jdiaz:tmp>a.out
8 8
-9223372036854775808 9223372036854775807 2.22507e-308 1.79769e+308



The double and long types have the same size, but the double limits
are bigger. Can anyone explein this to me ?

Typically, some of the bits representing a double are interpreted as an
exponent, and the rest as a multiplier. Floating-point math results in
approximate results, whereas any operation closed over the field of
integers will give an exact result when applied to long int's (if we
discount {over,under}flow).

http://en.wikipedia.org/wiki/IEEE_floating-point_standard
 
J

James McIninch

<posted & mailed>

The code below isn't C language code, but the question still applies.

A double can represent larger numbers because it lacks the resolution of the
long type. For a long integer, you have one number with absolute precision
for each integer within the range. For a double, you have exactly the same
number of values as the long, but on average, the difference between each
individual value and the next is much greater. Instead of counting by 1's,
you are counting by tens of thousands.

It may be easier to understand if you think about it this way, a integer
simply stores a number. A double uses the same number of bits to store two
numbers: one an integer, and one to tell it where to stick the decimal
point. The range of integers (where there is precision) is much smaller
because only a portion of the double is used to store the integral part
(mantissa) while another portion of the bits is used to store the position
of the decimal point (exponent). That's a simplification, but you get the
idea.

Integers are perfectly precise with a narrow range, and doubles are, on
average, very imprecise but cover a much wider range. Both doubles and
integers (in this case, since they are the same number of bits on your
system) have the same number of values.
 
T

Terry

Lew Pitcher said:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hi,

My OS is:

cronos:jdiaz:tmp>uname -a
HP-UX cronos B.11.11 U 9000/800 820960681 unlimited-user license


I compile in 64-bits mode the program below:

cronos:jdiaz:tmp>cat kk.C
#include <iostream.h>
#include <limits>

int main()
{
long l_min = numeric_limits<long>::min();
long l_max = numeric_limits<long>::max();
[snip]

Well, since you are using a different language from C, we in the comp.lang.c
newsgroup cannot assist you. Your question does not relate to C, and should be
(presumably, from the crossposting, was) asked in a forum related to the
language in which you wrote your example. This appears to be C++, so that forum
would be comp.lang.c++.


- --
Lew Pitcher
IT Consultant, Enterprise Application Architecture,
Enterprise Technology Solutions, TD Bank Financial Group

Not very helpful.

Regards
 
C

CBFalconer

jose said:
I compile in 64-bits mode the program below:

cronos:jdiaz:tmp>cat kk.C
#include <iostream.h>
#include <limits>

int main()
{
long l_min = numeric_limits<long>::min();
long l_max = numeric_limits<long>::max();
double d_min = numeric_limits<double>::min();
double d_max = numeric_limits<double>::max();
cout << sizeof(long) << " " << sizeof(double) << endl;
cout << l_min << " " << l_max << " " << d_min << " " << d_max << endl;

return 0;
}

C++ is off topic on c.l.c. Please refrain from any such
cross-postings.

--
Some useful references:
<http://www.ungerhu.com/jxh/clc.welcome.txt>
<http://www.eskimo.com/~scs/C-faq/top.html>
<http://benpfaff.org/writings/clc/off-topic.html>
<http://anubis.dkuug.dk/jtc1/sc22/wg14/www/docs/n869/> (C99)
 
J

joe durusau

CBFalconer said:

Well, the question doesn't have anything to do with unix, either, but
you might see whether your sompiler has sizeof() in it. That could tell
you the size of long and of double, and might provide a clue.

The best place to persue this sort of thing is a textbook. There are
very few newsgroups that devote themselves to trying to run down
questions relating to problems that probably pertain to a specific
compiler/platform issue such as this one. Too bad, but that's the
way it is.

Speaking only for myself,

Joe Durusau
 
F

Flash Gordon

On Mon, 3 May 2004 17:09:27 +0100

Not very helpful.

Seemed helpful to me. It contained no incorrect information and told the
OP where help would be available.
 
J

jose luis fernandez diaz

Hi,

I have made the program below to try to understand how a floating
point number is made by my computer (HP-UX cronos B.11.11 U 9000/800):

#include <stdio.h>
#include <math.h>

union
{
float f;
unsigned char uc[sizeof(float)];
} f_union;


int main()
{
f_union.f=1.0F;

unsigned char u1=1, u2;
u1 <<= sizeof(unsigned char)*8-1;

for (int i=0; i < sizeof(float); ++i)
{
u2=f_union.uc;
for(int j=0; j<sizeof(unsigned char)*8; j++)
{
printf("%d", ((u1 & u2)!=0));
u2 <<= 1;
}
}
printf("\n");

int exp;
double man = frexp(f_union.f, &exp);
printf("%lf %d\n%f\n", man, exp,f_union.f);


return 0;
}


but I didn't. Perhaps the program is wrong. Here are some outputs:

00111111100000000000000000000000
0.500000 1
1.000000

01000000000000000000000000000000
0.500000 2
2.000000

01000000010000000000000000000000
0.750000 2
3.000000


01000000100000000000000000000000
0.500000 3
4.000000

01000000101000000000000000000000
0.625000 3
5.000000

01000001000000000000000000000000
0.500000 4
8.000000




Any hint are welcome.

Thanks,
Jose Luis.
 
K

Karl Heinz Buchegger

jose said:
Hi,

I have made the program below to try to understand how a floating
point number is made by my computer (HP-UX cronos B.11.11 U 9000/800):

Your program won't help you in understanding what's the deal with
floating point numbers and why they have a greater range then eg. long.

Let us simplify the whole thing in a more familiar environment.
Assume you are my 'computer'. But I will allow you to calulate
with 5 digits only (and no sign for simplicity)

If you use those 5 digits for 'long' only , you can use those 5
digits to count from 00000 to 99999, so your range is 100000 numbers.
But you can do different also. You can divide the available 5 digits
into a mantissa and an exponent. Say you use 2 digits for the exponent
and the remaining 3 digits for the mantissa (you are familiar with
sientific notation, are you?). So eg. a number 100 can be represented
in various ways:

number scientific not. our notation
**************************************
100 100 * 10^0 100 00
100 10 * 10^1 010 01
100 1 * 10^2 001 02

Note: in the column 'our notation', no representation uses more then
5 digits which fits perfectly to what I allowed to you :)

Now lets see some other numbers.
Say you need to represent 1000 in 'out notation'. How can you do that?
Well you can eg. do 001 03. That would be 1 * 10^3. Or you could do
010 02 (10 * 10^2), or 100 01 (100 * 10^1). Fine. But now try to represent
1001 in 'out notation'. You can't. That's because the only way to get there
would be to increment the mantissa. Let's see whats happening then:

(1000) 001 03 -> (~1001) 002 03 -> 2 * 10^3 -> 2000
(1000) 010 02 -> (~1001) 011 02 -> 11 * 10^2 -> 1100
(1000) 100 01 -> (~1001) 101 01 -> 101 * 10^1 -> 1010

You see, using only 5 digits, it is impossible to get at the number 1001. You can
get 1000 and you can get 1010, but no numbers inbetween. It follows from the fact
that you reserve some of the available 5 digits to represent an exponent, which
drops the 'range' of numbers representable with the remaining 3 digits. But you
get the freedome to move the comma around by fiddeling with the exponent. Using
those 5 digit 'scientific notation' it is easy to represent

1000 -> 100 01
10000 -> 100 02
100000 -> 100 03
1000000 -> 100 04
10000000 -> 100 05

Right now we are way 'over' the upper limit for 5-digit-long, which was
99999. But we bought this by reducing the granularity. We cannot represent
all numbers in 10 millions, just some of them.

100 05 -> 10000000
101 05 -> 10100000

All numbers between 10000000 and 10100000 are not representable by our 5 digit
scheme but need to be approximated by either 10000000 or 10100000.

Back to your computer. It doesn't use only 5 digits, but much more. Also the
exponent is not taken to base 10, but to base 2. This reduces the effect you
just saw. But the principle is still the same. You buy the greater range
by reducing the granularity.
 
J

jose luis fernandez diaz

Ok. I understand.

Regards,
Jose Luis.

Karl Heinz Buchegger said:
Your program won't help you in understanding what's the deal with
floating point numbers and why they have a greater range then eg. long.

Let us simplify the whole thing in a more familiar environment.
Assume you are my 'computer'. But I will allow you to calulate
with 5 digits only (and no sign for simplicity)

If you use those 5 digits for 'long' only , you can use those 5
digits to count from 00000 to 99999, so your range is 100000 numbers.
But you can do different also. You can divide the available 5 digits
into a mantissa and an exponent. Say you use 2 digits for the exponent
and the remaining 3 digits for the mantissa (you are familiar with
sientific notation, are you?). So eg. a number 100 can be represented
in various ways:

number scientific not. our notation
**************************************
100 100 * 10^0 100 00
100 10 * 10^1 010 01
100 1 * 10^2 001 02

Note: in the column 'our notation', no representation uses more then
5 digits which fits perfectly to what I allowed to you :)

Now lets see some other numbers.
Say you need to represent 1000 in 'out notation'. How can you do that?
Well you can eg. do 001 03. That would be 1 * 10^3. Or you could do
010 02 (10 * 10^2), or 100 01 (100 * 10^1). Fine. But now try to represent
1001 in 'out notation'. You can't. That's because the only way to get there
would be to increment the mantissa. Let's see whats happening then:

(1000) 001 03 -> (~1001) 002 03 -> 2 * 10^3 -> 2000
(1000) 010 02 -> (~1001) 011 02 -> 11 * 10^2 -> 1100
(1000) 100 01 -> (~1001) 101 01 -> 101 * 10^1 -> 1010

You see, using only 5 digits, it is impossible to get at the number 1001. You can
get 1000 and you can get 1010, but no numbers inbetween. It follows from the fact
that you reserve some of the available 5 digits to represent an exponent, which
drops the 'range' of numbers representable with the remaining 3 digits. But you
get the freedome to move the comma around by fiddeling with the exponent. Using
those 5 digit 'scientific notation' it is easy to represent

1000 -> 100 01
10000 -> 100 02
100000 -> 100 03
1000000 -> 100 04
10000000 -> 100 05

Right now we are way 'over' the upper limit for 5-digit-long, which was
99999. But we bought this by reducing the granularity. We cannot represent
all numbers in 10 millions, just some of them.

100 05 -> 10000000
101 05 -> 10100000

All numbers between 10000000 and 10100000 are not representable by our 5 digit
scheme but need to be approximated by either 10000000 or 10100000.

Back to your computer. It doesn't use only 5 digits, but much more. Also the
exponent is not taken to base 10, but to base 2. This reduces the effect you
just saw. But the principle is still the same. You buy the greater range
by reducing the granularity.
 
A

Abhishek

Hi,

Long stores the integers as a normal bit representation and a double is like
a bigger float, in that it stores values in IEEE Floating point format.

You should know more about it if you want to do any serious programming in
any language. Please check google for IEEE Floating point format.



message news: said:
Hi,

My OS is:

cronos:jdiaz:tmp>uname -a
HP-UX cronos B.11.11 U 9000/800 820960681 unlimited-user license


I compile in 64-bits mode the program below:

cronos:jdiaz:tmp>cat kk.C
#include <iostream.h>
#include <limits>

int main()

long l_min = numeric_limits<long>::min();
long l_max = numeric_limits<long>::max();
double d_min = numeric_limits<double>::min();
double d_max = numeric_limits<double>::max();
cout << sizeof(long) << " " << sizeof(double) << endl;
cout << l_min << " " << l_max << " " << d_min << " " << d_max <<



return 0;


8 8
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top