views:

399

answers:

8

Is the difference between integer multiply(temporarily forgetting about division) still in favor of shifting and if so how big is the difference?

It simply seems such a low level optimization, even if you wanted it the shouldn't the (C#/Java) to bytecode compiler or the jit catch it in most cases?

Note: I tested the compiled output for C#(with gmcs Mono C# compiler version 2.6.7.0) and the multiply examples didn't use shift for multiplying even when multiplying by a multiple of 2.

C# http://csharp.pastebin.com/hcrRnPrb

cil http://csharp.pastebin.com/0js9F2c1

P.S. I forgot how it might be somewhat useful to use it on bytes, but still having some trouble on using it for Numbers.

+21  A: 

First reason:

Sometimes - most times - you want to treat an integer as a number. Sometimes though an integer is a convenient way to represent a set of bits.

Multiplication is an operation on numbers.

Shifting is an operation on a set of bits.

That there happens to be a relationship between the results of multiplication and the results of shifting is not particularly relevant. The operations are logically different.

Second reason:

C# and Java were both designed to be familiar to C developers, albeit at a superficial level. Therefore common idioms from C were included in C# and Java.

Eric Lippert
C# and Java(especially the latter) dropped many things from c and c++.
Roman A. Taycher
More importantly I'm curious why you would want to represent 2 bytes as an int if its not meant to be a number.
Roman A. Taycher
@Roman: Because you can move it around (and other operations) twice as efficiently as if you stored two bytes in separate variables.
Ben Voigt
I'm guessing if you only have two effecieny doesn't matter as much, if you have more why not use a byte array?
Roman A. Taycher
@Roman whether or not something is a performance bottleneck cannot be debated out of context. If you have multiple operations on two bytes e.g. 1000 operations and a few thousand concurrent users then that will make a difference
Rune FS
Context is what I'm after what sort of context is it a significant performance gain?
Roman A. Taycher
@Roman: Signals to/from external devices: soundcard, PLC, etc
GvS
Ben Voigt
Roman A. Taycher
+11  A: 

If I wanted to multiply a number by 4, I would write * 4. If my intent is to left-shift some bits 2 places, I would write << 2.

Re the question:

Why do Java and C# have bitshifts operators?

I do a lot of work on binary data, where I'm not thinking about integers etc - just binary - and in that area it is entirely logical to use shift operators constantly.

Sure, I could type * 2 etc, but what I actually want to do is shift the bits.

This is common in a range of areas where bytes matter (for example graphics programming, serialization, etc).

Additionally, there are some subtleties of shift operations where you don't want it to behave like an integer, in particular when dealing with the edges... the rules for what happens when you left-shift a bit off the map, or right-shift bits into the map (-ve vs +ve etc) are well understood but critical. Likewise, the checked/unckecked behaviour of integer multiplication is sometimes very important.

Marc Gravell
+7  A: 

You are right, if shift operators are used only as an alternative for multiplications, it should be left to the compiler.

I suppose you overlooked applications like:

  • Encryption / decryption
  • CRC calculation
  • Bitmap manipulation (Graphics, Database locks)
  • Compression/Decompression
  • Setting up data for hardware registers
  • Change encoding

and much more need bit-twiddling for efficient implementation without native code.

stacker
A: 

Because the language designers thought it would be good to have them.

It's not really important that they are equivalent to some other opperation, and that the compilers are smart enough to implement the operations efficiently. If that's where we're going, then you don't need much more than a macro assembler and a really good link time optimizer, maybe on a VM with a garbage collector. Those are not the goals language designers normally pursue.

TokenMacGuy
+1  A: 

What you are asking is essentially not why there are bitshift operators in C#/Java, but why the javac compiler doesn't optimize multiplications and divisions with powers of two into bitshifts.

The knee-jerk reaction to this is that multiplication and division have different semantics than bitshifts, so it does not map 100% to replace the operations.

Also, you forgot the extra compilation step that happens in the JIT (HotSpot) where all kinds of additional optimizations happen. There is frankly no need to optimize this particular step, as opposed to C where the code is as the compiler generates it.

Thorbjørn Ravn Andersen
A: 

For example, your program may use something like bit masks. In that case bitshift operation is a necessity. Or if you are just solving some weird task that requires encoding of states in a specified manner.

Watch this tutorial - most of the samples come from math problems. If you are simply making a site or a GUI application, you probably do not need shifting, but sometimes you really do...

SPIRiT_1984
I agree that bitshifting has it's area where they make the code easier to read/write bur you could get by without them and simply use *2^n or /2^n instead of <<n and >>n. So they are not required but nice to have
Rune FS
@Rune FS, -1>>1 is not the same as -1/2, whether sign-extended or not. Rewriting shift operations using only mathematical operators is actually quite fiddly.
Jon Hanna
@Jon you missed the point which is they are not required but can be rewritten (and signs makes no sense when talking about bit patterns since they inferre a specific interpretation of the pattern which is not a part of the pattern it self. E.g. There's multiple bit patterns that in a given context represents -1 and they All represent a positive integer in different contexts and and part of a file being encrypted in yet another context
Rune FS
@Rune FS, you missed my point is that they cannot be rewritten trivially. We can rewrite every instruction given only a subtract-and-branch-if-negative instruction, but there's good reasons why we don't. Finally you make my point when you talk about -1, as you're the one mixing thinking about math and thinking about bit patterns, I'm arguing that the two are best kept separate with separate operators.
Jon Hanna
@Jon I state in my org comment that I think shift operators are a good thing but the answers says their are required which is not true. and they are trivial to implement operator >> (uint mask, uint places){return mask / (uint)Math.Pow(2,places); }. Which is what I tried to explain above. ANd as you said your self "we can rewritte..." I.e. shift operators are _not_ required but they are _nice_ to have
Rune FS
@Rune FS, Not as trivial to sign-extend.
Jon Hanna
@Jon the above implementation works for _all_ bit masks. As I said in my first reply to you. Don't make the mistake of applying how you're interpreting the input/result on how you implement the operator.The above implementation don't care if you give it what _you_ think is a negative integer. It simply sees a bitmask, and works for _all_ bit masks (as long as they not to long to be represented by a uint)
Rune FS
@Rune FS. Well then, it isn't doing what the >> operator does in C# or Java, because both of those languages have >> behave differently on negative numbers (and while it doesn't matter what *I* think is a negative number, it does matter what the rest of the framework thinks of as a negative number). You can't say "we can replace >>" and then give an example that doesn't replace >>.
Jon Hanna
A: 

So that you can shift bits left and right. What you want those bits and their shift operations to represent is entirely upto you.

mumtaz
@ Rune FS... O ! man ...ha ha ha... that was a hilarious mistake. Thanks for the correction.
mumtaz
A: 

In addition to the other reasons here, there are plenty of cases where you may need to shift (or other bit operations) to interface with a 3rd party library or a remote application over a network.

Seth