在尝试为我的游戏制作网格列表的空间网格时,我试图根据特定网格的坐标数据制作唯一的哈希。我尝试获取网格数据:WorldName world_name; uint8_t stage_index; short int pos_x; short int pos_y; short int pos_z;
并尝试构建一个唯一的uint64_t hash_bitfield
。
当网格坐标为正时,我的uint64_t GenerateHash(...)
效果很好。但是,当任何都是负数时,我会产生不良影响:
world: 1 -->> 0000 0001
stage: 1 -->> 0000 0001
pos_x: 23 -->> 0000 0000 0001 0111
pos_y: -23 -->> 1111 1111 1110 1001
pos_z: 23 -->> 0000 0000 0001 0111
[ world ] [ stage ] [ pos_x ] [ pos_y ] [ pos_z ]
--byte7-- --byte6-- --byte5-- --byte4-- --byte3-- --byte2-- --byte1-- --byte0--
1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 1001 0000 0000 0001 0111 <-- what I get
0000 0001 0000 0001 0000 0000 0001 0111 0000 0000 0001 0111 0000 0000 0001 0111 <-- when y is positive
What I expected: vvvvvvvvvvvvvvvvvvv
0000 0001 0000 0001 0000 0000 0001 0111 1111 1111 1110 1001 0000 0000 0001 0111
请注意,pos_y为负数会在该字节的每隔一位翻转为1。当所有数字都是正数时,就不会发生这种事。正如您在下面的代码中所看到的,我尝试在将位复制到uint64_t
(注释块)后手动翻转符号位。它也没用。
#include <iostream>
#include <string>
#include <sstream>
#include <bitset>
using namespace std;
enum WorldName{ // These are collections of gameobj sectors
WORLD_TYPE1,
WORLD_TYPE2,
WORLD_TYPE3,
MAX_WORLDS
};
uint64_t GenerateHash( WorldName world_name, uint8_t stage_index, short int pos_x, short int pos_y, short int pos_z ){
uint64_t world_name_t = world_name;
uint64_t stage_index_t = stage_index;
uint64_t pos_x_t = pos_x;
uint64_t pos_y_t = pos_y;
uint64_t pos_z_t = pos_z;
// Try to flip the sign manually (it doesn't help)
//uint64_t pos_x_t, pos_y_t, pos_z_t;
//if( pos_x < 0 ){ pos_x_t = ~(uint64_t( abs( pos_x ) )) + 1; } else { pos_x_t = pos_x; }
//if( pos_y < 0 ){ pos_y_t = ~(uint64_t( abs( pos_y ) )) + 1; } else { pos_y_t = pos_y; }
//if( pos_z < 0 ){ pos_z_t = ~(uint64_t( abs( pos_z ) )) + 1; } else { pos_z_t = pos_z; }
uint64_t hash_bitfield = 0x0;
hash_bitfield |= world_name_t << (8 * 7);
hash_bitfield |= stage_index_t << (8 * 6);
hash_bitfield |= pos_x_t << (8 * 4);
hash_bitfield |= pos_y_t << (8 * 2);
hash_bitfield |= pos_z_t;
return hash_bitfield;
}
void PrintBitString( std::string bitstr, std::string label="", bool print_ruler=true ){
std::string buffer;
int count = 0;
for( size_t i = 0; i < bitstr.size(); i++ ){
buffer += bitstr[i];
count++;
if( count >3 ){ buffer += ' '; count = 0; }
}
if( print_ruler ){
int num_of_bytes_to_draw = (bitstr.size() / 8);
for( size_t k = num_of_bytes_to_draw; k > 0; --k ){
cout << "--byte" << k - 1 << "-- ";
}
cout << endl;
}
cout << buffer << endl;
}
int main() {
WorldName world_name = (WorldName) 1; // 4B
uint8_t stage_index = 1; // 1B
short int pos_x = 23; // 2B
short int pos_y = -23; // 2B
short int pos_z = 23; // 2B
std::bitset<8> world_name_bits( world_name );
std::bitset<8> stage_index_bits( stage_index );
std::bitset<16> pos_x_bits( pos_x );
std::bitset<16> pos_y_bits( pos_y );
std::bitset<16> pos_z_bits( pos_z );
cout << "world: " << world_name << "\t-->> " << world_name_bits << endl;
cout << "stage: " << (int)stage_index << "\t-->> " << stage_index_bits << endl;
cout << "pos_x: " << pos_x << "\t-->> " << pos_x_bits << endl;
cout << "pos_y: " << pos_y << "\t-->> " << pos_y_bits << endl;
cout << "pos_z: " << pos_z << "\t-->> " << pos_z_bits << endl << endl;
uint64_t my_hash = GenerateHash( world_name, stage_index, pos_x, pos_y, pos_z );
uint64_t my_hash_abs = GenerateHash( world_name, stage_index, pos_x, abs(pos_y), pos_z );
cout << "[ world ] [ stage ] [ pos_x ] [ pos_y ] [ pos_z ]" << endl;
std::bitset<64> bits( my_hash );
std::bitset<64> bits_abs( my_hash_abs );
PrintBitString( bits.to_string() );
PrintBitString( bits_abs.to_string(),"",false );
cout << endl;
system("PAUSE");
}
如何获得一个看起来像我的[期望]位域的uint64_t(其中pos_y的位域仅影响byte2和byte3的16位)?谢谢你的帮助!
答案 0 :(得分:0)
您可以将pos_x
等变量转换为unsigned short
,然后再将其分配给pos_x_t
uint_64_t pos_x_t = (unsigned short) pos_x;
或者您可以屏蔽值
uint_64_t pos_x_t = uint_64_t(pos_x) & 0xFFFF;
或者在hash_bitfield
hash_bitfield |= (pos_x_t & 0xFFFF) << (8 * 4);
遮挡也可以在换挡后进行,但是你需要使用遮挡的移位版本。