# Thread: Bit shifts

1. ## Bit shifts

I'm converting some code from Fortran to C and I've run into a problem with the random number generator convertion. It seems that when doing a bit shift in C it produces a different result than the bitshift in the Fortran. Does anyone have any ideas on how this would happen? Since the generator depends on these shifts I can't convert the code correctly if the shift is not going to work the same way.
Thanks

2. Well unless you post code, it's hard to say

But shifting negative numbers right in C++ is implementation specific.

3. bit shifting in C/C++ disregards the content of variables, only regards the size and the fact of not being floating point, because floating point operations are done by the co-processor

4. Hmm, well I think I found the problem, but I don't know if it is solvable. I realized that the integers in the Fortran code are not actually 4 bytes long (as was initially told) but actually just have a precision to 9 decimal digits (-999999999 to 999999999). This would mean that any bit shift using normally declared variables in C are going to be different because of the precision. Anyt thoughts on how to get around this would be apreciated, also please note that the Fortran code cannot change.

5. Well that fits nicely into 4 bytes - what's the problem?

How about posting some example results, and perhaps we can figure out what is going on
Say, in your fortran code, what does 1234 shifted 4 places left and 4 places right get you?

6. Well, the problem doesn't present itself until you put in big numbers. Thats why I guessed that the problem was in the size of the integer. The 4 bit int does not go from -999999999 to 999999999, it has a smaller range in C++, as far as I know. Anyway, I'm using long in the C code to make sure that I'm getting 4 bit integers.
The results are here:
C++:
777755849 << 5 results in 24888187168
And the same number in Fortran shifted 5 left results in:
-881616608

7. Try using a signed int or long.
Code:
```   signed int num;

num = (signed int) 777755849 << 5;
cout << num << endl;```

8. That worked for the first number generated, but then:
C++:
ix = -9054424
ix = 9054354
The first number is the initial then the second is shifted 17 to the right
and Fortran:
ix = -9054424
ix = -9066350
under the same calculation

Also, I forgot to say the exact calculation includes an exclusive or, the reason I left this out was because I determined the problem with the calculation was with the shift. The calculation is this:
Code:
`ix = ix ^ (ix >> 17);`

9. Code:
```#include <iostream>

void foo(int ix)
{
std::cout << "foo: ix = " << ix << std::endl;
std::cout << "foo: ix >> 17 = " << (ix >> 17) << std::endl;
ix = ix ^ (ix >> 17);
std::cout << "foo: ix = " << ix << std::endl;
}

void bar(int ix)
{
std::cout << "bar: ix = " << ix << std::endl;
std::cout << "bar: (unsigned)ix >> 17 = " << ((unsigned)ix >> 17) << std::endl;
ix = ix ^ ((unsigned)ix >> 17);
std::cout << "bar: ix = " << ix << std::endl;
}

int main()
{
foo(-9054424);
bar(-9054424);
return 0;
}

/* my output
foo: ix = -9054424
foo: ix >> 17 = -70
foo: ix = 9054354
bar: ix = -9054424
bar: (unsigned)ix >> 17 = 32698
bar: ix = -9066350
*/```

10. Confirming what Dave posted, it looks like you need to cast to unsigned int before you do any shift operation:
Code:
`   num = num ^ static_cast<unsigned int>(num) >> 17;`
Which is the opposite of what I posted before.

11. The Fortran bit shifts eventually loops to zero and so the Fortran after shifting to the left enough will get to zero and stop. The C++ shift however will keep looping (it will go to 1, and then keep going). So does anyone know how to make the C not go to one (for example, a different shift command)

12. Perhaps you should post some code, because as long as you cast to unsigned it should go to 0. For example:
Code:
```#include <iostream>
#include <climits>
using namespace std;

int main()
{
int num = 0x1;
cout << hex << num << dec << endl;
for (int i=0; i<sizeof(int)*CHAR_BIT; ++i)
{
num = static_cast<unsigned int>(num) << 1;
cout << hex << num << dec << endl;
}
}```

13. ...random number generator convertion.
If you're simply trying to generate a random number, it's easy in C/C++. You can use the standard rand() function. And, here's the cprogramming.com tutorial.

Playing around with bits is always fun, but it can be tricky in C/C++ because an integer can be 16, 32, or even 64 bits depending on the system.

14. Hmm, well I think I found the problem, but I don't know if it is solvable. I realized that the integers in the Fortran code are not actually 4 bytes long (as was initially told) but actually just have a precision to 9 decimal digits (-999999999 to 999999999). This would mean that any bit shift using normally declared variables in C are going to be different because of the precision. Anyt thoughts on how to get around this would be apreciated, also please note that the Fortran code cannot change.
You can get larger range in C++ by using 64 bits. But how are you determining this precison? I wouldn't trust the Fortran write routines. You should also look at an assembly listing or manual to find the exact shifting and types the Fortran compiler is using.

Popular pages Recent additions