Pergunta

Eu estou realizando algumas conversões tipo de dados onde eu preciso para representar uint, long, ulong e decimal como 754 valores de ponto flutuante dupla IEEE. Eu quero ser capaz de detectar se o tipo de dados IEEE 754 não pode conter o valor antes de realizar a conversão.

A solução de força bruta seria para embrulhar um try-catch em torno de um elenco para dobrar procurando OverflowException. Leitura através de alguns da CLR documentação implica que algumas conversões apenas silenciosamente mudar o valor, sem qualquer exceção.

Existe alguma maneira à prova de idiotas para fazer essa verificação? Eu estou olhando para ser completo sobre a facilidade de implementação. Tenho a sensação de que eu vou estar perto lendo a especificação IEEE 754 e verificar matissa e expoente cuidadosamente ...

Devo acrescentar, que eu sou mais preocupado com o que representa números inteiros com precisão e que a perda de ponto flutuante de precisão é uma preocupação secundária (mas ainda vale a pena considerar).

EDIT: Int32 é capaz de ser totalmente expressa como IEE-754. Também o tipo de dados Decimal é uma parte muito importante da questão.

Atualização Importante: se você está se referindo a esta pergunta, você também deve ler esta pergunta: IEEE-754 Duplo (ponto flutuante de 64-bits) ou longo (64-bit inteiro) Revisited

Ele observa uma falha na resposta, onde alguns valores muito grandes também são capazes de ser exatamente representado por IEEE-754. Enquanto isso pode significar que o valor será corretamente ida e volta, para o meu propósito original (isso vai ida e volta para JavaScript) que não vai.

Além disso, parece haver um erro no CLRs tipo System.Double porque ele não permite corretamente esses valores para ida e volta.

Foi útil?

Solução

Uma solução simples poderia ser algo como ( Se x é um int ):

if ((int)(double)x != x) { 
  // won't convert
} else {
  // will convert
}

e assim por diante por muito tempo, etc.

(duplo) x irá converter x de um int para um duplo. O (int), em seguida, converte-lo de volta novamente. Então, (int) (duplos) x convertidos formar um int para um casal e, em seguida, de volta. Essencialmente, o código é a verificação de que a conversão para dupla é reversível (e, portanto, que a dupla pode armazenar o valor exato do int).

Outras dicas

Esta depende principalmente da faixa de números que você está operando com. Enquanto você estiver dentro de 15 dígitos (por um dupla ), você deve estar no lado seguro para números inteiros.

Basicamente, o que você precisa para ter em conta é o número de dígitos significativos. Então, enquanto você número é menor do que o limite significativo dígito, ele permanecerá exata; se ele fica maior, você vai perder precisão (mesmo que esses são números inteiros).

Então, enquanto o seu número é <2 ^ 53, você é geralmente boa.

IEEE 754 Duplo tem 52 bits para mantissa e você está convertendo de / para o inteiro / longo por isso muito fácil de teste. Se o seu inteiro consomem menos de 52 bits, então ele deve ser conversível sem problemas para IEEE 754 double.

Eu presumo (eu sei com certeza em caso de Java, mas não C # e preguiçoso para verificar) que int é de 32 bits e longo é 64 bits. Então, com certeza int pode caber em dupla, sem qualquer problema, tanto sinal e unsign.

Para ulong, você simplesmente se todos os bits mais altos do que o bit 52th é um como ((aULong && 0xFFF0000000000000) == 0).

Por muito tempo, você tem que trazer o seu sinal para a consideração. Desde Long é 2º complemento mas IEEE754 não é (só tem pouco negativo), que acho que é seguro para apenas negativo secreta tempo para positivo (* 1) e verificar como positivo. Assim, se o tempo é negativo, tempo, com -1 primeiro (não fazer nada para positivo). Em seguida, verifique-o como ulong.

Espero que isso ajude.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top