user5009225
user5009225

Reputation:

conversion from long double to long long int

I have a long double sine and a long long int amp. I am using <cmath> and have code as follows:

sine = sin(point);
amp  = round(sine * 2^31);

Here the variable point is incrementing in 0.009375 intervals. The first line here works fine but on the second I receive this error message:

error: invalid operands of types 'long double' and 'int' to binary 'operator^'

I'm unsure what this error means and the main request here is 'How can I get around this to get an output integer into the variable amp?'

Upvotes: 1

Views: 1032

Answers (2)

Peter
Peter

Reputation: 36617

The reason for the error is that * is multiplication, and ^ is the bitwise xor operator which can only be applied to integral types.

Multiplication (*) has higher precedence than ^. So the compiler interprets amp = round(sine * 2^31); as amp = round( (sine *2)^31);. sine (presumably) has type long double, so the result of sine*2 is also of type long double. long double is not an integral type, so cannot be an operand of ^. Hence the error.

Your mistake is assuming that ^ represents exponentiation, which it does not.

You can fix the problem by either

amp = round (sine * pow(2.0, 31));   // all floating point

or

amp = round (sine * (1UL << 31));

The second computes 1 leftshifted 31 bits as an unsigned long (which is guaranteed able to represeny the result, unlike unsigned or int for which there is not such a guarantee). Then, in doing the multiplication, it promotes that value to long double.

If you are doing predominantly floating point operations, the first is more understandable to people who will maintain such code. The second is probably rather cryptic to someone who writes numeric code but is not well acquainted with bit fiddling operations - as, ironically, you have demonstrated in your belief that ^ is exponentiation.

You would need to test to determine which option offers greater performance (given the need to convert unsigned long to long double in the second , and potential for std::pow() in the first to be optimised for some special cases). In other words, there is potential for the compiler optimiser to get aggressive in both cases, or for the implementation of pow() to be lovingly hand-crafted, or both.

Upvotes: 0

Mark B
Mark B

Reputation: 96301

In C++ the ^ operator means exclusive or, not exponentiation. You probably meant (1ULL << 31).

Upvotes: 2

Related Questions