LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 02-29-2012, 10:32 PM   #1
Find
Member
 
Registered: Jan 2012
Posts: 32

Rep: Reputation: Disabled
Bit shifting with floats (C/C++)


I just want to verify that if I shift a c/C++ variable to the left by 1 that it is still multiplying by 2 even if the variable is a float and regardless of implementation.
 
Click here to see the post LQ members have rated as the most helpful post in this thread.
Old 02-29-2012, 10:52 PM   #2
Dark_Helmet
Senior Member
 
Registered: Jan 2003
Posts: 2,786

Rep: Reputation: 374Reputation: 374Reputation: 374Reputation: 374
Why not write a short program to test it? Something like:
Code:
#include <stdio.h>

int main( int argc, char *argv[] )
{
  float testFloat = 2.5;

  printf( "testFloat (before): %f\n", testFloat );
  testFloat = testFloat << 1;
  printf( "testFloat (after): %f\n", testFloat );
  return 0;
}
But to answer the question, no, you cannot meaningfully bit-shift a float. As the above code demonstrates when you try to compile, an error is displayed:
Code:
error: invalid operands to binary << (have ‘float’ and ‘int’)
Further, if you try to "trick" the compiler into bit shifting a float (e.g. as demonstrated on this page) by using some casting, you are not guaranteed to get a "multiply by two" result.

Floats, and doubles, are stored in a special format as described in this wikipedia page. Specifically, the 32 bits used for a float are split into two groups: a significand and an exponent. A bit shift can potentially shift bits from the exponent group into the significand group or vice versa.
 
2 members found this post helpful.
Old 03-01-2012, 08:02 PM   #3
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Code:
#include <iostream>


int main()
{
	std::cout << ".16 << 2 == " << (.16 * (1 << 2)) << std::endl;
	std::cout << ".16 >> 2 == " << (.16 / (1 << 2)) << std::endl;
}
Code:
.16 << 2 == 0.64
.16 >> 2 == 0.04
Kevin Barry
 
1 members found this post helpful.
Old 03-02-2012, 08:13 AM   #4
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by Dark_Helmet View Post
you cannot meaningfully bit-shift a float.
Right. However, at least C99 has functions ldexpf(), ldexp(), and ldexpl(), which do the same logical operation to a float, double, or long double (correspondingly). In other words,
Code:
double x, y;
int    n;

y = ldexp(x, n); /* y = x * (1 << n) */
except it works for the full double range, n = -1021 .. 1022, and may be much faster than a multiplication on some architectures.

This is not a programming trick, though. The low-level instruction executed by the CPU is different for floating-point values than it is for integers. I am not certain, but it is possible some C++ compiler options map << for floating-point values to those instructions automatically. For compatibility, better use ldexp() function directly. (There are also corresponding inverse frexp() functions, which split any floating-point value to a normalized fraction ±[0.5, 1) and a power-of-two exponent.)
 
1 members found this post helpful.
Old 03-02-2012, 09:08 AM   #5
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Quote:
Originally Posted by Nominal Animal View Post
This is not a programming trick, though. The low-level instruction executed by the CPU is different for floating-point values than it is for integers. I am not certain, but it is possible some C++ compiler options map << for floating-point values to those instructions automatically. For compatibility, better use ldexp() function directly. (There are also corresponding inverse frexp() functions, which split any floating-point value to a normalized fraction ±[0.5, 1) and a power-of-two exponent.)
Using those functions incurs a dependence on -lm, also.

C++03 guarantees that << and >> are defined for "integral types" but not for "floating types", so it might not even compile in some cases. For example, Comeau doesn't compile the expression double a = .16 << 2;.
Kevin Barry

Last edited by ta0kira; 03-02-2012 at 09:45 AM. Reason: grammar correction
 
1 members found this post helpful.
Old 03-02-2012, 10:33 AM   #6
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: Mint, Armbian, NetBSD, Puppy, Raspbian
Posts: 3,515

Rep: Reputation: 239Reputation: 239Reputation: 239
I think it is a very silly idea.

A floating point is not shiftable.
 
Old 03-02-2012, 02:17 PM   #7
Dark_Helmet
Senior Member
 
Registered: Jan 2003
Posts: 2,786

Rep: Reputation: 374Reputation: 374Reputation: 374Reputation: 374
Without prolonging this thread unnecessarily, I think I look at the original question a little differently than ta0kira and Nominal Animal.

My focus is on the OP's language that "if I shift a c/C++ variable to the left by 1" -- meaning that the OP's interest is to directly apply bit shifting to the variable(s).

My concern was not the perceived "multiply by 2" side effect of bit shifting. If the OP was looking for an efficient means of multiplying a value by a power of 2, that's fine. But bit-shifting is useful for more than math shortcuts. Indeed, a big part of my old job was using bit shifting to implement binary queues.
 
2 members found this post helpful.
Old 03-02-2012, 03:57 PM   #8
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by Dark_Helmet View Post
bit-shifting is useful for more than math shortcuts. Indeed, a big part of my old job was using bit shifting to implement binary queues.
Right. Also, many file formats (GIF, MPEG for example) treat data as a sequence of bits.

I assumed we are talking about multiplication by a power of two, not bit sequence manipulation.

For me, only unsigned integer types make any sense when handling bit sequences -- I mean, the part where you extract and shift the bits into more manageable units, or inversely pack units as a bit sequence.

In general, in C99, I use unsigned char for CHAR_BIT-bit bytes, or unsigned long for CHAR_BIT * sizeof (unsigned long) -bit words (typically most efficient handling unit, uses local endian byte order). This is either 32 bits or 64 bits in all current Linux architectures (ILP32 and LP64, respectively).

To convert to say floating-point types, it is usually more efficient to just construct the bit sequence in a suitable unsigned integer type (uint32_t for floats, uint64_t for doubles), then type-pun the value (via reinterpret_cast in C++). Conversion using ldexp()/frexp() is more general, but also much slower. It is much faster to determine the correct bit patterns at compile time, and not use floating-point at all.

Even signed integers have serious issues; shifting a signed integer down duplicates the high bit, whereas shifting an unsigned integer down inserts zero high bits. This means that (int)(-1) >> 1 == (int)(-1) in both C99 and C++.
 
1 members found this post helpful.
Old 03-02-2012, 04:41 PM   #9
Dark_Helmet
Senior Member
 
Registered: Jan 2003
Posts: 2,786

Rep: Reputation: 374Reputation: 374Reputation: 374Reputation: 374
Quote:
I assumed we are talking about multiplication by a power of two, not bit sequence manipulation.
Correct. What I was inarticulate at explaining in my last reply (regarding that I "looked at" the question a little differently):

My impression was that you and ta0kira interpreted the question as though the "multiply by 2" effect was the OP's ultimate goal--that the bit shifting was a means to an end.

I interpreted the question as though the OP wanted to bit shift any variable. And as a consequence, use the "multiply by 2" as a mechanism to verify the shift or as an alternate method for shifting.

That's all I was getting at.

Though, as a side note, you reminded me of that old job a little more with the signed int shifting reference. The signed int shift was quite useful. We were simulating some hardware design interaction. The binary queues I mentioned were the square waves propagating through the simulated design. The signed ints were useful in modeling a "pull-up resistor" in the circuit. The unsigneds were useful for pull-downs.

Anyway, not very useful trivia...
 
1 members found this post helpful.
Old 03-04-2012, 04:17 PM   #10
Find
Member
 
Registered: Jan 2012
Posts: 32

Original Poster
Rep: Reputation: Disabled
Thanks everyone, that was helpful!
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
shifting database from 32 bit linux to 64 bit syedkaleem Linux - Newbie 3 01-13-2011 05:12 PM
Bit shifting 6-byte value into a u64 ranthal Linux - Kernel 5 07-07-2009 09:26 PM
noob question -- Floats in C kdrlx Programming 16 03-22-2008 07:58 PM
floats in c++ ArlexBee-871RBO Programming 2 03-02-2007 08:08 PM
C++ floats and doubles ArlexBee-871RBO Programming 0 03-01-2007 09:04 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 12:15 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration