Dúvida sobre conversão de inteiro de 8 bits negativo em hexadecimal [RESOLVIDO]

1. Dúvida sobre conversão de inteiro de 8 bits negativo em hexadecimal [RESOLVIDO]

M.
XProtoman

(usa Fedora)

Enviado em 11/09/2016 - 12:30h

Boa tarde a todos,

O tópico é um pouco light, sem código. Estava estudando fazer um método para conversão de inteiro em hexadecimal quando surgiu a possibilidade de converter números negativos, e um desses números foi o valor mínimo de inteiro com sinal de 8 bits(uint8_t), que é -128 que gerou 0x80.

Python me confirmou esse valor:
$ python3
>>> hex(-128)
'-0x80'


A coisa mudou de figura quando utilizei -64, python retorna isso:
$ python3
>>> hex(-64)
'-0x40'


Minha implementação deu como resultado 0xC0 para -64.

O fprintf retorna 0xFFFFFFC0 para -64.

Na minha implementação não existe sinal negativo e não se trata de um número negativo.

Quem está certo? Python, C(fprintf) ou minha implementação?

Estou supondo que as 3 estão corretas, no caso C e minha implementação acho que são o mesmo resultado e tem a proposta igual, já Python é um número negativo, -128(0x80) deve ter sido coincidência.


  


2. MELHOR RESPOSTA

Paulo
paulo1205

(usa Ubuntu)

Enviado em 12/09/2016 - 05:52h

XProtoman escreveu:

Quem está certo? Python, C(fprintf) ou minha implementação?

Estou supondo que as 3 estão corretas, no caso C e minha implementação acho que são o mesmo resultado e tem a proposta igual, já Python é um número negativo, -128(0x80) deve ter sido coincidência.


No caso de Python, você precisa tomar o cuidado de lembrar que a saída da função hex() é do tipo string. Se você tomar a saída dessa função e tentar operar com ela como se fosse um inteiro, sem explicitamente a converter para inteiro, vai tomar erros.

>>> a=hex(-50)
>>> a
'-0x32' <-- NOTE QUE ESTÁ ENTRE APÓSTROFOS
>>> 5-a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'int' and 'str'
>>> 5-int(a,16)
55


Em C, você falou de usar int8_t, e disse que fprintf() produz “0xFFFFFFC0” para -64. Como você está trabalhando com int8_t, você deveria ter usado a conversão "%hhX", em lugar de apenas "%X". Fez isso?

Veja a diferença:
#include <stdio.h>
#include <stdint.h>

int main(void){
int8_t x=-64;
printf("%X\n", x);
printf("%hhX\n", x);
return 0;
}

Se compilar o rodar o programa acima, você vai receber o seguinte resultado.
FFFFFFC0
C0


Lembre-se que quando se usa printf() -- ou, na verdade, qualquer outra função que utilize quantidade variável de argumentos -- todos os argumentos de tipos inteiros com tamanho menor que o tamanho de int (ou unsigned int) são convertidos para int (ou unsigned int), e dados do tipo float são convertidos para double. Além disso quando um valor negativo é convertido para um inteiro com maior quantidade de bits, o sinal é preservado.

unsigned char a=255;
signed char b=a; /* Nos nossos PCs, isso faz b=-1. */
/* Na memória, tanto a como b têm um valor 0xFF. */
int ia=a, ib=b; /* Suponho que int tem 32 bits. */
/* ia==255 (a é unsigned e ia é grande o bastante para acomodar o valor real de a). */
/* ib==-1 (b é signed, e o o sinal é levado em conta na hora de estender o número). */
/* Na memória, ia contém 0x000000FF, e ib contém 0xFFFFFFFF. */


Outro aspecto desta discussão é que nós estamos supondo um sistema de representação numérica que usa complemento a 2. Com essa suposição, a faixa de valores de int8_t vai de -128 (0x80) a 127 (0x7F). Isso cria um descompasso na quantidade de números negativos ou positivos que podem ser representados (128 negativos e 127 positivos -- lembrando que zero não é positivo nem negativo), e consequentemente, um dos valores extremos que não se comporta bem quando se tenta obter seu simétrico.

Existem outras representações possíveis, como, por exemplo magnitude com sinal (um bit reservado para o sinal, e o resto representando quão longe de zero está o número; o simétrico de um número se obtém pela simples inversão do bit de sinal) e complemento a 1 (o simétrico de um número é a inversão de todos os seus bits). Uma característica marcantes desses dois últimos sistemas é que ambos possuem duas representações possíveis para o valor zero: uma com o bit de sinal ligado, e outra com ele desligado.

C não especifica nenhuma forma de representar internamente os números. Em princípio, qualquer representação interna é válida, desde que alguns limites mínimos sejam respeitados e que as operações com os números funcionem de acordo com o comportamento descrito para elas.

Geralmente os nossos PCs usam internamente complemento a 2 para inteiros porque é mais simples construir circuitos elétricos usando essa representação, e nossos compiladores C usam essa implementação e a deixam transparecer sobre os nossos dados inteiros. Mas essa transparência com a qual estamos relativamente habituados não deve ser assumida como sempre verdadeira se nós quisermos escrever um programa realmente portável.

Por outro lado, nós também estamos habituados a usar representação de magnitude com sinal, especialmente para números de ponto flutuante. Inclusive a existência de um “zero negativo” é às vezes desejável para indicar um valor com todas as propriedades de um valor negativo, porém tão pequeno que não pode ser representado com precisão suficiente por uma magnitude maior que zero (por exemplo “-pow(10, -1000)”). Mas também não devemos assumir que essa representação de ponto flutuante será sempre verdadeira: podem existir outras máquinas com representações diferentes, e o padrão do C não favorece nenhuma representação em particular, desde que as propriedades da operações sejam satisfeitas.

Já com Python, eu não conheço o suficiente da linguagem para saber se as regras são tão abertas como as do C, ou se ainda mais abertas. Parece-me que Python não faz amarração a tipos nativos -- tanto é que geralmente se consegue representar números gigantes sem nenhuma biblioteca adicional.

3. Re: Dúvida sobre conversão de inteiro de 8 bits negativo em hexadecimal [RESOLVIDO]

M.
XProtoman

(usa Fedora)

Enviado em 12/09/2016 - 11:39h

Obrigado paulo1205 pela resposta, perfeita e muita completa.

Eu estava imprimindo com PRIX8 do inttypes.h, foi por isso que estava saindo 0xFFFFFFC0 em vez da saída que você mostrou com %hhX, muito obrigado.

____________________
“Mas nós sabemos que a razão de a maioria estar aqui, é a nossa afinidade com a desobediência!” (Morpheus)






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts