O que é o que? · bei.pm
Nesta seção, há artigos sobre formatos de arquivo e engenharia reversa.
Agora, o que acontece é o seguinte:
Existem muitas linguagens de programação por aí e muitas pessoas que conhecem certas coisas por nomes completamente diferentes - ou que nem têm ideia da existência de conceitos fundamentais, porque sua linguagem de programação abstrai isso delas.
tl;dr:
Minha notação é baseada principalmente no C99 <stdint.h>
. Quem entende essa notação certamente conseguirá lidar bem com a minha.
Inteiro
Inteiros são, de forma simples, números inteiros, ou seja, números sem parte decimal.
Os inteiros são geralmente definidos em formatos de dados dentro de um espectro numérico fixo, quase como uma resolução. Eu indico isso em bits - porque um "byte" e tipos baseados nisso (Word, Qword, ...) geralmente são dependentes da plataforma.
Além disso, também se distingue entre números naturais (ℕ, ou seja, sem sinal - Unsigned) e números inteiros (ℤ, ou seja, com sinal - Signed).
Essa informação é visível através de um sinal no identificador (u
ou s
).
É possível que números inteiros com sinal sejam representados como complemento de um ou como complemento de dois.
Na ausência de especificação diferente, utiliza-se o complemento de dois, pois é a representação preferida na computação moderna.
Números sem sinal são indicados por mim em minhas documentações como uint
, com a precisão subsequente em bits.
Números com sinal são indicados por mim em minhas documentações como sint
, também com a precisão subsequente em bits.
Eu evito o uso do tipo de dado "char" para caracteres, uma vez que cadeias de caracteres geralmente representam apenas sequências de valores inteiros com uma interpretação especial.
Portanto, elas são representadas como uint(8)[].
Exemplos:
Notação | Equivalente C99 stdint.h |
Descrição | Faixa Numérica |
---|---|---|---|
uint(16) | uint16_t | Número Inteiro Não Assinado, 16 Bits de Comprimento | 0 - 65.535 |
sint(8) | int8_t | Número Inteiro Assinado, 8 Bits de Comprimento, Complemento de Dois | -126 - 127 |
uint(24) | uint32_t:24 | Número Inteiro Não Assinado, 24 Bits de Comprimento | 0 - 16.777.216 |
Valores de ponto fixo
Valores de ponto fixo são valores numéricos da gama dos Números Racionais (Q), que, portanto, possuem uma vírgula e casas decimais.
Nos valores de ponto fixo, a posição da vírgula é determinada rigidamente pelo tipo de dado - daí o nome.
Isso resulta em um intervalo fixo de valores para números desse tipo de dado; matematicamente, o espaço numérico é finito.
Na prática, esse tipo de dado é principalmente usado em plataformas sem unidades de hardware de ponto flutuante suficientemente rápidas, uma vez que o cálculo de valores de ponto fixo pode ser realizado por unidades inteiras.
O tipo de dado também é utilizado, por exemplo, por sistemas de gerenciamento de banco de dados, quando exigências fixas precisam ser atendidas.
Pense, por exemplo, em sistemas para armazenamento permanente de dados financeiros; a maioria das moedas limita-se a 2 casas decimais.
(No entanto, não é sábio usar valores de ponto fixo para isso; é mais inteligente armazenar diretamente a menor unidade monetária como um inteiro e deixar o resto para o nível de representação)
Assim como nas especificações inteiras, ao lidar com valores de ponto fixo, eu indico a resolução do número antes e depois da vírgula:
ufixed(9,7)
refere-se a um tipo de dado que reserva 9 bits sem sinal para o valor antes da vírgula, e 7 bits para o valor depois da vírgula; no total, portanto, tem 16 bits de largura e pode, por exemplo, cobrir um intervalo de (0,0) a (511,127) como um vetor de dois inteiros independentes.
Entretanto, essa interpretação deixaria 28 números sem uso em sua representação decimal, já que provavelmente se restringiria a um máximo de (511,99) na prática.
Em vez de uma interpretação direta do valor de ponto fixo como um vetor de 2 inteiros separados - o que praticamente sempre resulta em um intervalo de dados não utilizado ao converter para números decimais e exige um carry manual - o intervalo decimal pode ser interpretado como um quociente de toda a sua resolução.
Usando o exemplo mencionado de ufixed(9,7)
, resulta em um quociente com um denominador de 27 - o intervalo numérico vai de 0,00 até 511 + 126⁄127
Para conversão em uma representação decimal, a casa decimal deve ser dividida por 128.
Com essa variante, operações aritméticas se tornam mais simples, pois o carry é gerado automaticamente, tornando essa abordagem geralmente preferida.
No entanto, essa variante tem a desvantagem de que as casas decimais na representação decimal não têm mais uma resolução garantida, então um único ponto decimal não representa mais o valor 0.01
, mas sim 0.007874
, o que resultará em erros de arredondamento.
A interpretação utilizada é documentada conforme o local de uso.
Valores de ponto flutuante
Valores de ponto flutuante são expressões matemáticas mais complexas, nas quais um número inteiro com resolução fixa é expresso por um termo matemático de forma que o valor decimal seja formado por deslocamento - e, assim, se orienta diretamente pela notação científica.
A maneira mais comum de implementar isso foi padronizada pelo
IEEE 754 e desde então é reconhecida internacionalmente.
Um valor de ponto flutuante geralmente consiste nas seguintes componentes:
Sinal (0 ou 1 ) |
Expoente | Mantissa |
Enquanto o sinal pode ser facilmente determinado como uma informação binária de sim/não, o número real é formado pela equação
Mantissa * 2Expoente
Além disso, há uma série de valores constantes que cobrem casos especiais de números racionais - incluindo ±∞
e NaN
("não é um número válido").
Valores de ponto flutuante são especialmente úteis quando a precisão não é tão importante, uma vez que esse tipo de valor inevitavelmente leva a erros de arredondamento e, portanto, à perda de precisão. Tipicamente, valores de ponto flutuante são usados, por exemplo, para definir coordenadas, como vetores de vértices em modelos 3D ou curvas Bézier/spline para fins de representação óptica.
Nos formatos de dados, os valores de ponto flutuante são especificados como float(Mantissa, Expoente)
.
Se um formato distinto do IEEE 754 for utilizado, isso será indicado adequadamente.