Raised This Month: $ Target: $400
 0% 

Bit shift on negative numbers


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Black Rose
Veteran Member
Join Date: Feb 2011
Location: Upplands Väsby, Sweden
Old 04-19-2014 , 18:51   Bit shift on negative numbers
Reply With Quote #1

EDIT: Answer...
http://stackoverflow.com/questions/1...e-numbers-in-c
http://en.wikipedia.org/wiki/Bitwise...ithmetic_shift

I'll leave this for anyone searching.


This is just a general question as I solved the problem already. I'm just curious.

So I was trying to make a function to convert 32bit integers to any number of bits integers and back, but I ran into problems.
If I have an integer which equals to 511, in bits it would look like this:
00000000 00000000 00000001 11111111.
I shift that 8 bits to the right, I would end up with this:
00000000 00000000 00000000 00000001.
No problem there.

Now let's say I've got an integer that is -1, In bits that would be:
11111111 11111111 11111111 11111111.
Now I assumed if I shift these 8 bits to the right I would end up with this:
00000000 11111111 11111111 11111111
To my surprise it was unchanged.
Is this the way bit shifts work on negative numbers?
Does it fill with whatever the last bit is set to? Is it perhaps a bug? EDIT: C++ seems to do the same thing, I guess it's not a bug.
Or am I just missing the obvious answer? ^^

I solved it by bitmasking with this:
temp &= (1<<(32-X)) - 1;
where X stands for number of bits in the new integer, for example 8. Then it would run the input
11111111 10101010 01010101 10101010
through the bitmask
00000000 11111111 11111111 11111111
and the result would be
00000000 10101010 01010101 10101010
EDIT: I found out using logical shift instead of arithmetic shift will give the result that I want without bitmasking, so I changed to that instead.
Logical right shift is done with >>> instead of >>.

And of course, for anyone interested, here's the code:
EDIT: Of course when I posted this I realized the first two functions were useless. I renamed them adding the "Inv" at the end because the array is inverted and then made 2 new functions.
Code:
#include <amxmodx> public plugin_init() {     register_plugin("Test Plugin 3", "", "[ --{[email protected] ]");         new output[64], len;     new output2[64], len2;         new num = 15000;         new intX[32];     new bits = 7;     new levels = Int32toUIntX(num, intX, sizeof intX, bits);     server_print("Levels: %d", levels);     for ( new i = levels * bits - 1 ; i >= 0 ; i-- ) {         if ( ( i % bits ) == bits - 1 && i != levels * bits - 1 )             len += formatex(output[len], charsmax(output) - len, " ");         len += formatex(output[len], charsmax(output) - len, "%d", num & (1<<i) ? 1 : 0);     }     server_print("32bit pre : %s, number: %d", output, num);         len = 0;         for ( new i ; i < levels ; i++ ) {         if ( i )             len += formatex(output[len], charsmax(output) - len, " ");         for ( new j = bits - 1 ; j >= 0 ; j-- )             len += formatex(output[len], charsmax(output) - len, "%d", intX[sizeof intX - levels + i] & (1<<j) ? 1 : 0);     }     for ( new i ; i < levels ; i++ )             len2 += formatex(output2[len2], charsmax(output2) - len2, "%s%d", i == 0 ? "" : ",", intX[sizeof intX - levels + i]);     server_print("%s%dbit post: %s, numbers: %s", bits < 10 ? " " : "", bits, output, output2);         len = 0;     len2 = 0;         new int32 = UIntXtoInt32(intX, sizeof intX, bits);     for ( new i = levels * bits - 1 ; i >= 0 ; i-- ) {         if ( ( i % bits ) == bits - 1 && i != levels * bits - 1 )             len += formatex(output[len], charsmax(output) - len, " ");         len += formatex(output[len], charsmax(output) - len, "%d", int32 & (1<<i) ? 1 : 0);     }     server_print("32bit post: %s, number: %d", output, int32);         len = 0;     arrayset(intX, 0, sizeof intX);             // Inverted...     server_print("^nInverted");     levels = Int32toUIntXInv(num, intX, bits);     server_print("Levels: %d", levels);     for ( new i = levels * bits - 1 ; i >= 0 ; i-- ) {         if ( ( i % bits ) == bits - 1 && i != levels * bits - 1 )             len += formatex(output[len], charsmax(output) - len, " ");         len += formatex(output[len], charsmax(output) - len, "%d", num & (1<<i) ? 1 : 0);     }     server_print("32bit pre : %s, number: %d", output, num);         len = 0;         for ( new i = levels - 1 ; i >= 0 ; i-- ) {         if ( i != levels - 1 )             len += formatex(output[len], charsmax(output) - len, " ");         for ( new j = bits - 1 ; j >= 0 ; j-- )             len += formatex(output[len], charsmax(output) - len, "%d", intX[i] & (1<<j) ? 1 : 0);     }     for ( new i = levels - 1 ; i >= 0 ; i-- )             len2 += formatex(output2[len2], charsmax(output2) - len2, "%s%d", i == levels - 1 ? "" : ",", intX[i]);     server_print("%s%dbit post: %s, numbers: %s", bits < 10 ? " " : "", bits, output, output2);         len = 0;         int32 = UIntXtoInt32Inv(intX, sizeof intX, bits);     for ( new i = levels * bits - 1 ; i >= 0 ; i-- ) {         if ( ( i % bits ) == bits - 1 && i != levels * bits - 1 )             len += formatex(output[len], charsmax(output) - len, " ");         len += formatex(output[len], charsmax(output) - len, "%d", int32 & (1<<i) ? 1 : 0);     }     server_print("32bit post: %s, number: %d", output, int32); } stock Int32toUIntX(int32, intX[], arraysize, X) {     new temparraysize = arraysize - 1;     new levels, temp = int32;     while ( temparraysize >= 0 ) {         if ( temp )             levels++;         intX[temparraysize--] = temp & ((1<<X) - 1);         temp >>>= X;     }     return levels; } stock UIntXtoInt32(intX[], arraysize, X) {     new int32, i, temparraysize = arraysize - 1;     while ( i < arraysize ) {         int32 += intX[temparraysize--] << X * i;         i++;     }     return int32; } stock Int32toUIntXInv(int32, intX[], X) {     new i, temp = int32;     while ( temp ) {         intX[i++] = temp & ((1<<X) - 1);         temp >>>= X;     }     return i; } stock UIntXtoInt32Inv(intX[], arraysize, X) {     new int32, i = arraysize - 1;     while ( i >= 0 ) {         int32 += intX[i] << X * i;         i--;     }     return int32; }
Code:
32bit pre : 1110101 0011000, number: 15000
 7bit post: 1110101 0011000, numbers: 117,24
32bit post: 1110101 0011000, number: 15000

Inverted
Levels: 2
32bit pre : 1110101 0011000, number: 15000
 7bit post: 1110101 0011000, numbers: 117,24
32bit post: 1110101 0011000, number: 15000
Note: These functions are pretty useless overall. I started making them to be able to send large integers through the new menusystem info[] parameter. I later realized this is useless because if either cell is null, the input would end. Still finished them as an example to teach myself and to help others struggling with bits. You're far better off using something like this for example:
Code:
#define Int8toInt32(%0,%1,%2,%3) ( %3 | (%2<<8) | (%1<<16) | (%0<<24) ) server_print("TEST1: %d", Int8toInt32(0, 0, 255, 255)); // TEST1: 65535 new testnum = 16744223; server_print("TEST2: %d, %d, %d", (testnum>>16)&0xFF, (testnum>>8)&0xFF, testnum&0xFF); // TEST2: 255, 127, 31

EDIT: I feel smart now...
If I use 7-bit integers, the 8th bit is free to use as a placeholder to make the integer "not null", which would pass fine through the info[] parameter. At the other end bitmasking the first 7 bits to counter the effect of the negative number.
__________________

Last edited by Black Rose; 04-20-2014 at 19:13.
Black Rose is offline
Reply


Thread Tools
Display Modes

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 On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 01:27.


Powered by vBulletin®
Copyright ©2000 - 2022, vBulletin Solutions, Inc.
Theme made by Freecode