Is static_cast<int>(static_cast<double>(a)) == a?

B

Bo Peng

Dear C++ experts,

I need to store and retrieve a meta information that can be int or
double. The program would be significantly simpler if I can handle two
types uniformly. Right now, I am using a single interface:

void setInfo(double); // store info
double info(); // retrieve info

and use
setInfo(static_cast<double>(a))
and
static_cast<int>(info())

to save and retrieve integers. I have not seen any problem yet but I am
worried that maybe sometimes, 12 can be saved as 11.99999999 and
retrieved as 11.

Many thanks in advance.
Bo
 
P

Philipp Reh

Dear C++ experts,

I need to store and retrieve a meta information that can be int or
double. The program would be significantly simpler if I can handle two
types uniformly. Right now, I am using a single interface:

void setInfo(double); // store info
double info(); // retrieve info

and use
setInfo(static_cast<double>(a))
and
static_cast<int>(info())

to save and retrieve integers. I have not seen any problem yet but I am
worried that maybe sometimes, 12 can be saved as 11.99999999 and
retrieved as 11.

Many thanks in advance.
Bo

Hi,

the representation of double in C++ is completly implementation defined
and so is the conversion from double to int.

If you need to handle types uniformly but you need just one type at a time
use a variant. boost::variant can help here.
 
V

Victor Bazarov

Bo said:
I need to store and retrieve a meta information that can be int or
double. The program would be significantly simpler if I can handle two
types uniformly. Right now, I am using a single interface:

void setInfo(double); // store info
double info(); // retrieve info

and use
setInfo(static_cast<double>(a))

There is no need for the static_cast here.
and
static_cast<int>(info())

to save and retrieve integers. I have not seen any problem yet but I
am worried that maybe sometimes, 12 can be saved as 11.99999999 and
retrieved as 11.

Unless your integers have more digits than your double can represent,
you have nothing to worry about. In a usual system nowadays, 'double'
(which has 16 digits of precision) can represent _any_ 'int' (which
has only 10 digits. If you want to check, you can write a simple
program that counts all integers from INT_MIN to INT_MAX and if the
condition you put in the subject line is not satisfied, report back.

V
 
S

Steve Pope

Philipp Reh said:
the representation of double in C++ is completly implementation defined
and so is the conversion from double to int.

I think this is a little misleading, especially the second
half of the statement. A double value which represents an
exact integer must be converted to that integer in any implementation.

The representation of doubles is implementation-dependent as you
state, but if you can ensure that IEEE floating point double precision
is being used, then a large range of integers are precisely represented.

This is reliable enough such that some languages (matlab, perl)
do not bother to have a separate integer type.

Steve
 
B

Bo Peng

Unless your integers have more digits than your double can represent,
you have nothing to worry about. In a usual system nowadays, 'double'
(which has 16 digits of precision) can represent _any_ 'int' (which
has only 10 digits. If you want to check, you can write a simple
program that counts all integers from INT_MIN to INT_MAX and if the
condition you put in the subject line is not satisfied, report back.

The following code does not report any problem so I guess I can relax?
This is gor gcc/linux only though.

#include <iostream>

int main()
{
for(int i=-INT_MAX; i < INT_MAX; ++i)
if( static_cast<int>(static_cast<double>(i)) != i)
std::cout << i << " is in trouble\n";
}

Cheers,
Bo
 
B

Bo Peng

Steve said:
A double value which represents an
exact integer must be converted to that integer in any implementation.
The representation of doubles is implementation-dependent as you
state, but if you can ensure that IEEE floating point double precision
is being used, then a large range of integers are precisely represented.

This is good to know. Maybe this is somewhere in the C/C++ standard.
This is reliable enough such that some languages (matlab, perl)
do not bother to have a separate integer type.

OK. If matlab and perl can take the risk, so can I. :)

Thank you very much for your informative and quick reply.

Bo
 
N

Noah Roberts

Bo said:
Dear C++ experts,

I need to store and retrieve a meta information that can be int or
double. The program would be significantly simpler if I can handle two
types uniformly. Right now, I am using a single interface:

void setInfo(double); // store info
double info(); // retrieve info

and use
setInfo(static_cast<double>(a))
and
static_cast<int>(info())

to save and retrieve integers. I have not seen any problem yet but I am
worried that maybe sometimes, 12 can be saved as 11.99999999 and
retrieved as 11.

Float creep. Yes, it happens. You can get values that bounce around,
slide left/right, etc... Most implementations seem to handle the
particular case you are talking about ok but the problem still exists
and can cause issues in other areas.
 
C

Clark S. Cox III

Bo said:
The following code does not report any problem so I guess I can relax?
This is gor gcc/linux only though.

#include <iostream>

int main()
{
for(int i=-INT_MAX; i < INT_MAX; ++i)
if( static_cast<int>(static_cast<double>(i)) != i)
std::cout << i << " is in trouble\n";
}

Then you are likely OK for that particular platform, but remember to
re-check this anytime you build for a different compiler/OS/processor
combination (for instance, this will not work on a platform where int
and double are both 64-bits).
 
J

Jack Klein

Dear C++ experts,

I need to store and retrieve a meta information that can be int or
double. The program would be significantly simpler if I can handle two
types uniformly. Right now, I am using a single interface:

void setInfo(double); // store info
double info(); // retrieve info

and use
setInfo(static_cast<double>(a))
and
static_cast<int>(info())

to save and retrieve integers. I have not seen any problem yet but I am
worried that maybe sometimes, 12 can be saved as 11.99999999 and
retrieved as 11.

Many thanks in advance.
Bo

You've received a lot of answers containing guesses. The C++ standard
inherits <float.h> (or <cfloat>) from C, and it defines macros
FLT_DIG, DBL_DIG, and LDBL_DIG that provide the guarantees you are
asking for for the three floating point types.

Since the minimum value for FLT_DIG is 6, and the minimum for the
others is 10, any integer value in the range of +/- 9,999,999,999,999
may be stored in a float and later back into a (wide enough) integer
type and yield the exact value.
 
S

Steve Pope

Jack Klein said:
You've received a lot of answers containing guesses. The C++ standard
inherits <float.h> (or <cfloat>) from C, and it defines macros
FLT_DIG, DBL_DIG, and LDBL_DIG that provide the guarantees you are
asking for for the three floating point types.
Since the minimum value for FLT_DIG is 6, and the minimum for the
others is 10, any integer value in the range of +/- 9,999,999,999,999
may be stored in a float and later back into a (wide enough) integer
type and yield the exact value.

Cool. Thanks.

Steve
 
C

Clark S. Cox III

Jack said:
You've received a lot of answers containing guesses. The C++ standard
inherits <float.h> (or <cfloat>) from C, and it defines macros
FLT_DIG, DBL_DIG, and LDBL_DIG that provide the guarantees you are
asking for for the three floating point types.

Since the minimum value for FLT_DIG is 6, and the minimum for the
others is 10, any integer value in the range of +/- 9,999,999,999,999
may be stored in a float and later back into a (wide enough) integer
type and yield the exact value.

That is certainly not true. With 6 digits of precision, a float can not
accurately represent integers in the range of a 32-bit integer (a 16-bit
integer would be fine). With 10 digits, of precision a double can
represent all of the integers in a 32-bit integer, but not a 64-bit integer.
 
V

Victor Bazarov

Jack said:
[...]
Since the minimum value for FLT_DIG is 6, and the minimum for the
others is 10, any integer value in the range of +/- 9,999,999,999,999
may be stored in a float and later back into a (wide enough) integer
type and yield the exact value.

Uh... How do you arrive at that conclusion? First of all, "the range
of +/- 9,999,999,999,999" requires 13 digits of precision. We could
dismiss that as a typo, of course, but then, you say "stored in a float"
when you should probably say "stored in a double".

And shouldn't we actually be using 'std::numeric_limits' instead?

V
 

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,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top