10

get a complier error while trying to do

float_val=float_val<<1;

It gives out a error saying "error C2296: '<<' : illegal, left operand has type 'float '"

Can't v left shift float vars? Why is this so?

Akash
  • 4,956
  • 11
  • 42
  • 70
  • 1
    How exactly would you expect the shift to be done in case of a float? – Tudor Feb 16 '12 at 17:01
  • I guess, same as int (power of 2) – Akash Feb 16 '12 at 17:01
  • 1
    Because the different bits of a float have different meanings, it doesn't make sense to do a bit shift on a float – Dan F Feb 16 '12 at 17:03
  • 2
    A good reading: [IEEE_754-2008](http://en.wikipedia.org/wiki/IEEE_754-2008) – Alexander Pavlov Feb 16 '12 at 17:03
  • possible duplicate of [How to perform a bitwise operation on floating point numbers](http://stackoverflow.com/questions/1723575/how-to-perform-a-bitwise-operation-on-floating-point-numbers) – Shahbaz Feb 16 '12 at 17:08
  • One should always write code for what it is doing, write `*2` if you meant to double the value. Write `<<1` if you're really doing a bitwise shift (i.e, hardware register with bit fields). Either way the compiler will generate the exact same machine code. Trying to scale a float by a power of 2 using shift is writing cryptic code Trust your compiler to make efficient machine code, and just write clean code. – Michael Mar 22 '16 at 14:09

7 Answers7

20

You can't left shift float variables, because (a) your FPU generally will not have a barrel shifter exposed to you so physically cannot generate code to do that, and (b) what would it even mean? The underlying bit representation consists of multiple fields with different meanings, do you really want those bits bleeding into each other?

If you want to multiply the number held in that variable by two, you should just do that instead.

If you want to reinterpret the float as some type that left shift makes sense on (e.g. a suitably large unsigned integer type) for some horrible bit hack like Carmack's square root, well, you can do that too, but on modern hardware it is highly unlikely that you really need to: seriously consider if there is a better way to do what you want.

moonshadow
  • 86,889
  • 7
  • 82
  • 122
  • 7
    +1. But to be pedantic, the FPU almost certainly *will* have a barrel shifter, because it's pretty much required in order to do floating-point addition. – Oliver Charlesworth Feb 16 '12 at 17:07
  • 2
    @Oli: but even if you could control it, it's not wired up to shift the whole float, just the mantissa... I shall clarify. – moonshadow Feb 16 '12 at 17:09
  • It's ok, your answer is already fine. I was just being the stereotypical SO pedant! – Oliver Charlesworth Feb 16 '12 at 17:10
  • On amd64, FP math is usually done in SSE registers. There's nothing stopping you from using integer left/right shifts on those registers. (Except for the fact that the results won't be useful for much of anything!) – Peter Cordes Jun 26 '15 at 02:32
5

Check out the standard function ldexpf if you want to quickly multiply or divide a float by a power of 2. A bit obscure obviously :-).

https://linux.die.net/man/3/ldexpf

Aaron Madsen
  • 51
  • 1
  • 1
3

Shifting floats makes no sense since it's represented as the concatenation of a sign bit, an exponent and a mantissa. Since shifting operation is about shifting bits, it would imply shifting bits from mantissa to exponent and / or to sign bit.

Scharron
  • 17,233
  • 6
  • 44
  • 63
1

Floating point numbers don't have bits at the level of value-representation, which is why you can't apply bitwise operations to them.

See this answer for more information.

Community
  • 1
  • 1
1

Since the left shift operator is defined as multiplication by a power of 2, it makes perfect sense for floating point types. However, the C language does not define its use, so instead you have to use the scalbn function or similar.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
0

You cannot left shift objects of float type.

C says the operands of the bitwise shift operators shall have integer type.

ouah
  • 142,963
  • 15
  • 272
  • 331
-2

You'd have to transform the float to something else first. Such as:

float f = 128;
f = (float) (((int) f) << 1 );

And in the above, f should be 256.0.

Now obviously this is problematic if you start with 128.4 as the cast will drop the .4. You may not want to be using a float in first place.

Wes Hardaker
  • 21,735
  • 2
  • 38
  • 69