Eu estava lendo um artigo da Microsoft sobre como Ampliar conversões e Option Strict On quando cheguei à parte
As conversões a seguir podem perder precisão:
- Inteiro para Único
- Longo a Simples ou Duplo
- Decimal para Simples ou Duplo
No entanto, essas conversões não perdem informações ou magnitude.
.. mas de acordo com outro artigo sobre tipos de dados ,
O tipo inteiro pode armazenar de -2.147.483.648 a 2.147.483.647 e
Tipo único pode armazenar de
- 1,401298E-45 a 3,4028235E + 38 para números positivos,
- e -3,4028235E + 38 a - 1,401298E-45 para números negativos
.. so Single pode armazenar muito mais números que Inteiro. Não conseguia entender em que situação essa conversão de Integer para Single pode perder precisão. Alguém poderia explicar, por favor?
fonte
Integer
s (99,2%) não podem ser representados comoSingle
, portanto, "quando" é "praticamente sempre".Single
pode representar apenas 4.278.190.079 números diferentes. UmSingle
valor representa um número se e somente se o expoente armazenado não for 255, o que significa que existem 255 * 2 ^ 24Single
s que representam números. Destes, dois deles representam o mesmo número (ou seja, zero), e os outros representam números diferentes.[-16777216,16777216]
(2 ^ 24 = largura do significando) podem ser exatamente representados. Números maiores são arredondados para o múltiplo mais próximo de 2, 4, 8, ... dependendo do tamanho deles.Single
tem duas maneiras de armazenar zero. EntãoSingle
, de fato, pode representar menos números distintos do queInteger
.Os tipos de ponto flutuante (como Single e Double) são representados na memória por um sinal, uma mantissa e um expoente. Pense nisso como notação científica:
Eles - como você pode esperar - usam a base 2. Existem outros ajustes que permitem representar o infinito e o NaN, e o expoente é deslocado (retornará a isso), e uma abreviação para a mantissa (retornará a isso também) . Procure o padrão IEEE 754 que abrange sua representação e operações para obter mais detalhes.
Para nossos propósitos, podemos imaginá-lo como um número binário "mantissa" e um "expoente" que diz onde colocar o separador decimal.
No caso de Single, temos 1 bit para ele assinar, 8 para o expoente e 23 para a mantissa.
Agora, o importante é armazenar a mantissa a partir do dígito mais significativo. Lembre-se de que todos os zeros à esquerda não são relevantes. E, considerando que estamos trabalhando em binário, sabemos que o dígito mais significativo é 1 ※. Bem, como sabemos disso, não precisamos armazená-lo. Graças a essa abreviação, o alcance efetivo da mantissa é de 24 bits.
※: A menos que o número que estamos armazenando seja zero. Para isso, teremos todos os bits definidos como zero. No entanto, se tentarmos interpretar isso sob a descrição que eu dei, você teria 2 ^ 24 (o implícito 1) multiplicado por 1 (2 à potência do expoente 0). Portanto, para corrigi-lo, o expoente zero é um valor especial. Também existem valores especiais para armazenar o infinito e o NaN no expoente.
De acordo com o deslocamento do expoente - além de evitar os valores especiais -, com o deslocamento, é possível colocar o ponto decimal antes do início da mantissa ou após seu término, sem a necessidade de ter um sinal para o expoente.
Isso significa que, para números grandes, o tipo de ponto flutuante colocará o ponto decimal além do final da mantissa.
Lembre-se de que a mantissa é um número de 24 bits. Ele nunca representará um número de 25 bits ... não possui esse bit extra. Portanto, o único não pode distinguir entre 2 ^ 24 e 2 ^ 24 + 1 (esses são os primeiros números de 25 bits e diferem no último bit, que não é representado no único).
Assim, para números inteiros, o intervalo do único é -2 ^ 24 a 2 ^ 24. E tentar adicionar 1 a 2 ^ 24 resultará em 2 ^ 24 (porque, no que diz respeito ao tipo, 2 ^ 24 e 2 ^ 24 + 1 são o mesmo valor). Experimente online . É por isso que há uma perda de informações ao converter de número inteiro para único. E é também por isso que um loop que usa um único ou um duplo pode realmente ser um loop infinito sem você perceber.
fonte
1
bit implícito inicial no significando. Está implícito que o campo de expoente tendencioso é diferente de zero . Os subnormais (também conhecidos como denormais) incluem+-0.0
um0
pouco do seu significado. Eu acho que você pode simplificar para considerar apenas0.0
um caso totalmente especial, mas0.0
na verdade segue as mesmas regras de codificação de outros subnormais.Aqui está um exemplo real de quando a conversão de
Integer
paraSingle
pode perder precisão:O
Single
tipo pode armazenar todos os números inteiros de -16777216 a 16777216 (inclusive), mas não pode armazenar todos os números inteiros fora desse intervalo. Por exemplo, ele não pode armazenar o número 16777217. Por esse motivo, não pode armazenar nenhum número ímpar maior que 16777216.Podemos usar o Windows PowerShell para ver o que acontece se convertermos um
Integer
em umSingle
e vice-versa:Observe que 16777217 foi arredondado para 16777216 e 16777219 foi arredondado para 16777220.
fonte
float
s representáveis mais próximos continua crescendo como potências de. pt.wikipedia.org/wiki/…Os tipos de ponto flutuante são semelhantes à "notação científica" em física. O número é dividido em um bit de sinal, um expoente (multiplicador) e uma mantissa (dígitos significativos). Assim, à medida que a magnitude do valor aumenta, o tamanho da etapa também aumenta.
O ponto flutuante de precisão única possui 23 bits de mantissa, mas existe um "1 implícito"; portanto, o mantissa é efetivamente de 24 bits. Portanto, todos os números inteiros com magnitude de até 2 24 podem ser representados exatamente em um ponto flutuante de precisão única.
Acima disso, sucessivamente menos números podem ser representados.
Portanto, dos 2 32 possíveis valores inteiros assinados de 32 bits, apenas 2 * (2 24 + 7 * 2 23 ) = 9 * 2 24 podem ser representados em um ponto flutuante de precisão única. Isso representa 3,515625% do total.
fonte
Os flutuadores de precisão única têm 24 bits de precisão. Tudo o que for arredondado para o número de 24 bits mais próximo. Pode ser mais fácil entender em notação científica decimal, mas lembre-se de que os flutuadores reais usam binário.
Digamos que você tenha 5 dígitos decimais de memória. Você pode optar por usá-los como um int não assinado regular, permitindo que você tenha qualquer número entre 0 e 99999. Se quiser representar números maiores, use a notação científica e aloque apenas dois dígitos para o expoente, portanto agora você pode representar algo entre 0 e 9,99 x 10 99 .
No entanto, o maior número que você pode representar exatamente agora é apenas 999. Se você tentou representar 12345, pode obter 1,23 x 10 4 ou 1,24 x 10 4 , mas não pode representar nenhum dos números intermediários, porque não tem dígitos suficientes disponíveis.
fonte