For a while, I've been representing large powers of 10 in constants using scientific notation, just so I don't have to count the zeros. e.g.
#define DELAY_USEC 1e6
A colleague pointed out that this isn't safe, because it's not an integer and is not guaranteed to always equal 1000000 exactly. Documentation seems to confirm this, but I'm wondering if its true in practicality. Is there any way to safely declare a power-of-ten integer using a shorthand? Is it safe just to cast it to an int in the define?
It's really not safe because the compiler will consider it as a floating point number, so the precision is limited to 53 bits instead of 64 bits of integers (long int) for more you can read about the presentation of floating point numbrers
http://en.wikipedia.org/wiki/Floating_point
You ask specifically about powers of ten.
1e6
will be exactly one million. You can go up to1e22
without anything bad happening. However, note that in both C++ and C,1e6
is adouble
constant, rather than an integer constant.Negative powers of ten are a different story.
1e-1
is inexact, as are all lower powers.You'll never get rounding errors on something less than
INT_MAX
, since the specification fordouble
sets aside 52 bits for you to use. Your "fractional component" is just your integer, and your "exponent" will be 1, and floating point doesn't struggle with that.In theory, no. Neither language specifies how floating point values are represented, or which values can be represented exactly. (UPDATE: apparently, C11 does recommend a representation. C++, and older C dialects, don't).
In practice, yes, for quite a large range of values. Any implementation you're remotely likely to encounter will use a 64-bit IEEE representation for
double
. This can represent any integer value up to 253 (approximately 9x1015) exactly. It can certainly represent anything representable by a 32-bit integer type.It seems that
gcc
assumes a constant defined using scientific notation as a floating point number unless it is cast.A simple C code shows this:
On a x86-64 machine,
gcc
generates this assembly code ($ gcc -S define.c
):As stated here, 10e15 and 10e22 are the maximum power of ten numbers that have an exact representation in simple and double-precision floating-point format, respectively.
Larger power of ten numbers can not be represented using 32-bit or 64-bit integer types.
You want to use user defined literals:
then you can simple do: