Necesito empaquetar 3 valores de 10 bits(0..1023 codificados como int o short) en una palabra de 4 bytes(int). Como deben ser las operaciones a nivel de bits para solo elegir los 10 bits menos significativos de cada componente y situarlos en el lugar de la palabra de 4 bytes correcto y despues poder leer los valores de la componente desde dicha palabra. Muchas gracias.
Hola
a ver.. no es muy dificil... tienes el int a 0, para guardar el primer dato simplemente se lo sumas al int, para guardar el segundo dato y le suma al int (y<<10) y para guardar el tercero le sumas al int (z<<20). para sacarlos es muy facil, lo unico q haces es valor=(valorguardado>>(10*i))%1024; (i = 0..2).
como ves no es muy dificil, un saludo!
Y los acarreos? no sería mejor hacer un or ?
por otra parte no tendría que ser:
valor=(valorguardado>>(10*i))%1024; --- > valor=(valorguardado>>(10*i))%0x03ff; ?
saludos
Funciona bien si solo introduzco datos una vez. Si una vez empaquetado, necesito sobreescribir el valor de uno de los componente, da un resultado incorrecto.
a ver... para introducir otro dato despues de haber guardado uno antes lo q tienes q hacer es sacarlo, es decir, restar y dejar los 10 bits a 0 para q cuando añadas otro valor se te guarde correctamente....
void ponvalor(int indice, int valor){
int antiguovalor=(valorguardado>>(10*i))%1024;
valorguardado-=antiguovalor<<(10*i);
valorguardado+=valor<<(10*i);
}
eso deberia funcionar, corregirme si me equivoco...
PD: ethernet, pq haces modulo 1023??un valor de 10 bits va de 0 a 1023, pero un modulo de 1023 va solamente hasta el 1022, asiq daria fallo en el caso de q el valor fuese 1023, x lo q el 1024 esta bien
un saludo y omaddon, dime si funciona cuando lo leas
tywok
En vez de los desplazamientos yo usaría máscaras y ors para la escritura y ands para poner a 0 la parte que luego quieras reescribir con un or, tal como dice ethy.
pero bueno, hacerlo con mascaras es lo mismo q hago yo, pero desde otro punto de vista... no creo q vaya mas rapido ni nada, aunque bueno, vosotros sabreis, ya q sabeis mas q yo...
un saludo
Creo que los desplazamientos están al mismo nivel de velocidad que un or o un and, son funciones básicas. Y si no, en cualquier caso tendrán tiempos parecidísimos, no notarías las diferencia.
La máscara para los 10 bits más significativos sería un & 0x000003FF si no me he equivocado.
int Get(int v, int i) //i = [0, 1, 2]
{
return( (v >> (10 * i) ) & 0x3FF);
}
void Set(int & v, int i, int s) //s = valor a poner
{
int m[] = {0x3FFFFC00, 0x3FF003FF, 0x000FFFFF};
v = (v & m[i]) | (s << (10 * i) );
}
Juer, qué friki :blink:
Ya funciona. Gracias a todos por vuestras respuestas.
CitarLa máscara para los 10 bits más significativos sería un & 0x000003FF si no me he equivocado.
bueno, pues para la mascara si, pq en binario es diez unos seguidos, pero si lo haces en modulo, tienes q poner el siguiente, osea, el 1024. las dos cosas estan bien (ole)
PD: omaddon, al final como lo hiciste, x simple curiosidad??
un saludo
Cita de: "tywok"
PD: ethernet, pq haces modulo 1023??un valor de 10 bits va de 0 a 1023, pero un modulo de 1023 va solamente hasta el 1022, asiq daria fallo en el caso de q el valor fuese 1023, x lo q el 1024 esta bien
Perdon, me confundí, quise poner un & ;).
El código de Juan Mellado funciona bien.
int Get(int v, int i) //i = [0, 1, 2]
{
return( (v >> (10 * i) ) & 0x3FF);
}
void Set(int & v, int i, int s) //s = valor a poner
{
int m[] = {0x3FFFFC00, 0x3FF003FF, 0x000FFFFF};
v = (v & m) | (s << (10 * i) );
}
Lo único, es que he añadido una comprobación para evitar que en la función Set, introduzcan un valor suparior a 10bits, porque si lo hacen modificarias también la componente superior.
Juan Mellado rocks (ole) (ole) (ole)
Cuando hacemos algo deberiamos hacerlo bien no? y si dejamos un poco de lado el orgullo coder podemos usar código de otras personas y ya que estamos hablando de videojuegos podemos recurrir a uno de los códigos de juegos que tenemos a nuestra disposición, en este caso unreal (tim sweney rocks)
*-----------------------------------------------------------------------------
FBitWriter.
-----------------------------------------------------------------------------*/
//
// Writes bitstreams.
//
struct CORE_API FBitWriter : public FArchive
{
friend struct FBitWriterMark;
public:
FBitWriter( INT InMaxBits )
: Num ( 0 )
, Max ( InMaxBits )
, Buffer ( (InMaxBits+7)/8 )
, Overflowed ( 0 )
{
guard(FBitWriter::FBitWriter);
ArIsNet = ArIsPersistent = ArIsSaving = 1;
unguard;
}
void SerializeBits( void* Src, INT LengthBits )
{
guard(FBitWriter::SerializeBits);
if( Num+LengthBits<=Max )
{
for( INT i=0; i<LengthBits; i++,Num++ )
if( ((BYTE*)Src)[i/8]&(1<<(i&7)) )
Buffer(Num/8) |= (1<<(Num&7));
else
Buffer(Num/8) &= ~(1<<(Num&7));
}
else Overflowed = 1;
unguard;
}
void WriteInt( DWORD Result, DWORD Max )
{
Result = INTEL_ORDER(Result);
SerializeBits( &Result, appCeilLogTwo(Max) );
}
void WriteBit( BYTE In )
{
guard(FBitWriter::WriteBit);
SerializeBits( &In, 1 );
unguard;
}
void Serialize( void* Src, INT LengthBytes )
{
guard(FBitWriter::Serialize);
SerializeBits( Src, LengthBytes*8 );
unguard;
}
INT GetNumBytes()
{
return (Num+7)/8;
}
INT GetNumBits()
{
return Num;
}
UBOOL GetOverflowed()
{
return Overflowed;
}
void SetOverflowed()
{
Overflowed = 1;
}
BYTE* GetData()
{
return &Buffer(0);
}
private:
TArray<BYTE> Buffer;
INT Num;
INT Max;
UBOOL Overflowed;
};
/*-----------------------------------------------------------------------------
FBitReader.
-----------------------------------------------------------------------------*/
//
// Reads bitstreams.
//
struct CORE_API FBitReader : public FArchive
{
public:
FBitReader( BYTE* Src=NULL, INT CountBits=0 )
: Num ( CountBits )
, Buffer ( (CountBits+7)/8 )
, Pos ( 0 )
, Overflowed ( 0 )
{
guard(FBitReader::FBitReader);
ArIsNet = ArIsPersistent = ArIsLoading = 1;
if( Src )
appMemcpy( &Buffer(0), Src, (CountBits+7)/8 );
unguard;
}
void SetData( FBitReader& Src, INT CountBits )
{
guard(FBitReader::SetData);
Num = CountBits;
Pos = 0;
Overflowed = 0;
Buffer.Empty();
Buffer.Add( (CountBits+7)/8 );
Src.SerializeBits( &Buffer(0), CountBits );
unguard;
}
void SerializeBits( void* Dest, INT LengthBits )
{
guard(FBitReader::SerializeBits);
if( Pos+LengthBits<=Num )
{
for( INT i=0; i<LengthBits; i++,Pos++ )
if( Buffer(Pos/8)&(1<<(Pos&7)) )
((BYTE*)Dest)[i/8] |= (1<<(i&7));
else
((BYTE*)Dest)[i/8] &= ~(1<<(i&7));
}
else SetOverflowed();
unguard;
}
DWORD ReadInt( DWORD Max )
{
INT Result=0;
SerializeBits( &Result, appCeilLogTwo(Max) );
return INTEL_ORDER(Result);
}
BYTE ReadBit()
{
BYTE Bit=0;
SerializeBits( &Bit, 1 );
return Bit;
}
void Serialize( void* Dest, INT LengthBytes )
{
guard(FBitReader::Serialize);
SerializeBits( Dest, LengthBytes*8 );
unguard;
}
UBOOL AtEnd()
{
return Overflowed || Pos==Num;
}
UBOOL GetOverflowed()
{
return Overflowed;
}
void SetOverflowed()
{
Overflowed = 1;
}
BYTE* GetData()
{
return &Buffer(0);
}
INT GetNumBytes()
{
return (Num+7)/8;
}
INT GetNumBits()
{
return Num;
}
INT GetPosBits()
{
return Pos;
}
private:
TArray<BYTE> Buffer;
INT Num;
INT Pos;
UBOOL Overflowed;
};
ROCKS, ROCKS UNREAL ROCKS !
Mars :P
Esto demuestra una de las Leyes de Murphy que reza que cualquier cosa sencilla puede explicarse de manera que resulte incomprensible :ph34r:
A mi me resulta sencillo leer ese codigo. Lo mejor es enemigo de lo bueno