Question

I have to multiply an integer value by 2^31. I have googled it, and it looks like doubles have a range among 2.23e-308 <= |X| <= 1.79e308 when using 64 bits, and a float among 1.18e-38 <= |X| <= 3.40e38.

That's a lot more than what I need. But it doesn't work.

I have this constant value in my header file:

static const float SCALE_FACTOR = 2^-31;

and if then I just do:

float dummy = SCALE_FACTOR;

Then, dummy's value is 11.

I don't know if the problem is assigning a constant value like that, but I don't know how else to write it without losing precision.

Any help?

EDIT:Sorry, stupid question. My MatLab background betrayed me and forgot that ^ is not for exponentiation in C++. I have voted to close.

Was it helpful?

Solution

^ is a bitwise xor operator in C++, not a mathematical exponentiation operator. You have a few alternatives.

  1. Because you're storing the constant in an intrinsically lossy format, a float, you could just work out the base-10 e form literal and use that: perhaps something like 4.6566128730773926e-010 for 2^-31. This is prone to error (I've made one, for example), and isn't necessarily portable between floating point formats.
  2. You can set the constant using a constant expression that can be evaluated at compile time, and use an integer literal: either 0x80000000 or 1UL << 31 for 2^31, or 1.0f / 0x80000000 for 2^-31 for example.

You could use a pow function of some kind to calculate the value at runtime, of course.

Incidentally, if you're using integers, why not just use a long long or other 64bit integral type, instead of a floating point which may well present you with rounding errors? It isn't totally clear from your question whether you are looking at floating point values because you need floating point value ranges, or because you are merely worried about overflowing a 32-bit integer value.

OTHER TIPS

In your code

static const float SCALE_FACTOR = 2^-31;

the static is superfluous (constants have internal linkage by default), the ^ denotes bitwise XOR, the - is meaningless (at least if you want to "multiply by 2^31" as stated), and float is needlessly a special choice, as opposed to the default floating point type double (which e.g. is the type of a floating point literal such as 3.14).

Also, in C++ reserve shouting ALL UPPERCASE identifiers for macros (the common convention). Using them for constants is a Java-ism. Ironically the Java convention originated with C, where in times past constants had to be expressed as macros.

Instead, therefore write

double const scale_factor = 1uL << 31;

where

  • not explicitly specifying internal linkage (keyword static),

  • using default floating point type double instead of float,

  • not using ALL UPPERCASE identifier (which should be reserved for macros),

  • using left bitshift << to compute power of two, instead of incorrect ^,

  • not adding any meaningless minus sign,

  • using type unsigned long (specified by uL) to be sure to have sufficient range.

^ is an operator for bitwise XOR, not for raising to power. You need std::pow().

Multiplying by a power of 2 is equivalent to shifting left by that power. To multiply an integer by two to the 31, just shift it:

unsigned long value = whatever;
unsigned long value_times_2_to_the_31 = value << 31;

There's no need for floating-point math here. But just for completeness, to produce a double value of 2 to the 31:

double two_to_the_31 = std::ldexp(1.0, 31);

Note that while the result of the shift expression with a signed type would be formally undefined in some situations, that results from overflowing the integer type; using floating-point math instead doesn't eliminate the overflow, it just puts it into a different part of the code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top