Wednesday, 5 July 2017

Float Point Number Representation Binary Options


Semelhante aos números binários decimais, pode ter flutuadores também. Agora eu leio que pode ter flutuadores do tipo 0,5. 0,1. 0,25. 0,01. 0,125. 0.001. e assim por diante. Mas, por exemplo, como é o 0.1 (em decimal) representado em binário também, dado um flutuador decimal, como convertê-lo para o equivalente decimal, (dado que não é tão direto). Editar: Então eu entendo que a melhor pergunta seria como converter um flutuador decimal em binário. Agora eu entendo que multiplicamos a parte decimal, até que ele se torne zero. Agora, é muito possível que dois pontos flutuantes possam ter a mesma representação correu, perguntou em 12 de dezembro às 19:41 Sahil: Quando os números são convertidos em ponto flutuante (como analisando uma seqüência contendo um número e convertendo-o em ponto flutuante) Números diferentes podem produzir o mesmo resultado. É impreciso dizer que o resultado de ponto flutuante representa esses números. Por padrão IEEE 754, um valor de ponto flutuante representa exatamente um número, o que você obtém ao interpretar sua codificação conforme especificado no padrão. Você pode dizer que dois números diferentes podem ter a mesma aproximação em ponto flutuante, mas é importante lembrar que é apenas uma aproximação. Ndash Eric Postpischil 1 de dezembro às 23:10 Outra observação que poderia ser útil. A parte inteira de um número de ponto flutuante está presente no binário na sua forma normal, por exemplo, se o valor for 25.7482 você terá os bits 11001 (25) no ponto flutuante, com os bits seguintes representando a fração (na verdade, o primeiro 1 nunca é armazenado, está implícito no formato). Se você subtrair 25.0 desse número e multiplicar por 10, você obtém 7.482 e, ao examinar a parte inteira desse valor, você pode obter o primeiro dígito fracionário, 7. Subtrair 7.0, multiplicar por 10, dá 4.82. Portanto, o próximo dígito 4, e assim por diante. Esse processo, na teoria, acabará eventualmente com um resultado zero, uma vez que todos os valores que podem ser exatamente representados no formato de ponto flutuante têm uma representação decimal exata no entanto, esse resultado exato poderia ter muito mais dígitos do que realmente razoáveis, dada a precisão do original Ponto flutuante (e você pode precisar de uma precisão extra internamente para obter esse resultado totalmente exato, de qualquer forma - você precisa garantir que a multiplicação por 10 não gere um erro de arredondamento). E, para números como 6.432e-200, este método é viável, mas não muito eficiente (você estará gerando 199 zeros antes dos primeiros 6 surgiram). Respondeu 22 de dezembro 12 em 19: 44O tamanho de um flutuador é dependente da plataforma, embora um máximo de 1.8e308 com uma precisão de aproximadamente 14 dígitos decimais é um valor comum (o formato IEEE de 64 bits). Precisão do ponto flutuante Os números dos pontos flutuantes têm precisão limitada. Embora isso dependa do sistema, o PHP normalmente usa o formato de dupla precisão IEEE 754, que dará um erro relativo máximo devido ao arredondamento na ordem de 1.11e-16. As operações aritméticas não elementares podem dar erros maiores e, é claro, a propagação de erros deve ser considerada quando várias operações são combinadas. Além disso, números racionais que são exatamente representáveis ​​como números de ponto flutuante na base 10, como 0.1 ou 0.7. Não tem uma representação exata como números de ponto flutuante na base 2, que é usado internamente, independentemente do tamanho da mantisa. Portanto, eles não podem ser convertidos em suas contrapartes binárias internas sem uma pequena perda de precisão. Isso pode levar a resultados confusos: por exemplo, o piso ((0,10.7) 10) geralmente retornará 7 em vez do esperado 8. Uma vez que a representação interna será algo como 7.9999999999999991118. . Portanto, nunca confie nos resultados do número flutuante para o último dígito e não compare os números de ponto flutuante diretamente para a igualdade. Se for necessária uma maior precisão, as funções matemáticas de precisão arbitrária e as funções gmp estão disponíveis. Para uma explicação de quotsimplequot, veja o guia de ponto flutuante raquo that039s também intitulado quotPor que não meus números adicionam upquot Convertendo para flutuar Para obter informações sobre converter seqüências s para flutuar. Veja a conversão de seqüência de caracteres em números. Para valores de outros tipos, a conversão é realizada convertendo primeiro o valor em número inteiro e depois flutuando. Consulte Convertendo para inteiro para obter mais informações. A partir do PHP 5, um aviso é lançado se um objeto for convertido em flutuador. Comparando flutuadores Conforme observado no aviso acima, o teste de valores de ponto flutuante para igualdade é problemático, devido à forma como eles são representados internamente. No entanto, existem maneiras de fazer comparações de valores de ponto flutuante que funcionam em torno dessas limitações. Para testar valores de ponto flutuante para igualdade, é usado um limite superior no erro relativo devido ao arredondamento. Este valor é conhecido como o epsilon da máquina, ou unidade roundoff, e é a menor diferença aceitável nos cálculos. A e b são iguais a 5 dígitos de precisão. Ltphp a 1.23456789 b 1.23456780 epsilon 0.00001 se (abs (a - b) lt epsilon) echo true gt Algumas operações numéricas podem resultar em um valor representado pela NAN constante. Este resultado representa um valor indefinido ou irrepresentável em cálculos de ponto flutuante. Qualquer comparação solida ou estrita desse valor em relação a qualquer outro valor, inclusive em si, terá resultado de FALSE. Como a NAN representa qualquer número de valores diferentes, a NAN não deve ser comparada com outros valores, inclusive em si, e deve ser verificada para usar isnan (). Notas de contribuições do usuário 30 apontar apenas um comentário sobre algo da inserção de precisão do ponto flutuante, que segue: Isto está relacionado. 0,3333333. Enquanto o autor provavelmente sabe do que eles estão falando, essa perda de precisão não tem nada a ver com a notação decimal, tem a ver com a representação como um binário de ponto flutuante em um registro finito, como quando 0.8 termina em decimal, é O 0.110011001100 de repetição. Em binário, que está truncado. 0,1 e 0,7 também não estão terminando em binário, de modo que também são truncados, e a soma desses números truncados não corresponde à representação binária truncada de 0,8 (e é por isso que (piso) (0,810) produz um diferente, mais Resultado intuitivo). No entanto, uma vez que 2 é um fator de 10, qualquer número que termina em binário também termina em decimal. Dica de informática geral: se você estiver acompanhando o dinheiro, faça a si mesmo e seus usuários o favor de lidar com tudo internamente em centavos e faça o máximo de matemática possível em números inteiros. Armazene valores em centavos, se possível. Adicione e subtraia em centavos. Em cada operação que envolva flutuadores, pergunte-se o que acontecerá no mundo real, se eu tiver uma fração de um centavo aqui e se a resposta é que esta operação gerará uma transação em centavos inteiros, não tente carregar precisão fracionada fictícia Isso só irá destruir as coisas mais tarde. Gostaria de salientar uma característica do suporte a ponto flutuante do PHP que não ficou claro em qualquer lugar aqui e estava me deixando louco. Este teste (onde vardump diz que a0.1 e b0.1) se (agtb) echo blah falhará em alguns casos devido à precisão escondida (problema C padrão, que o PHP não faz menção, então eu pensei que eles se haviam livrado Disso). Devo ressaltar que originalmente pensei que este era um problema com os carros que estavam sendo armazenados como cordas, então eu forcei-os a ser flutuadores e eles ainda não foram avaliados corretamente (provavelmente dois problemas diferentes lá). Para corrigir, eu tive que fazer este kludge horrível (o equivalente de qualquer maneira): se (round (a, 3) gtround (b, 3)) echo blah THIS funciona. Obviamente mesmo que vardump diga que as variáveis ​​são idênticas, e elas DEVEM SER idênticas (começaram em 0,01 e adicionaram 0.001 repetidamente), elas não são. Há alguma precisão escondida lá que me faz arrancar meu cabelo. Talvez isso seja adicionado à documentação ltphp binarydata32 pack (H. 00000000) float32 descompactar (f. Binarydata32) 0.0 binarydata64 pack (H. 0000000000000000) float64 descompactar (d. Binarydata64) 0.0 gt Eu recebo 0 tanto para 32 bits quanto 64 - números de bits. Mas, por favor, não use suas próprias funções para converter de flutuador para binário e vice-versa. O desempenho de loop em PHP é horrível. Usando o pacote descompactado, você usa a codificação dos processadores, o que sempre está correto. Em C, você pode acessar os mesmos 32 64 dados como flutuante duplo ou 32 64 bits inteiros. Não há conversões. Para obter a codificação binária: ltphp float32 pack (f. 5300231) binarydata32 desembalar (H. float32) 0EC0A14A float64 pack (d. 5300231) binarydata64 descompactar (H. float64) 000000C001385441 gt E meu exemplo há meio ano: ltphp binarydata32 pack ( H. 0EC0A14A) float32 descompactar (f. Binarydata32) 5300231 pacote binarydata64 (H. 000000C001385441) float64 descompactar (d. Binarydata64) 5300231 gt E, por favor, lembre-se dos garotos Endian Big e Little. A caixa de precisão de ponto flutuante na prática significa: lt echo (69.1-floor (69.1)) gt Think thisll return 0.1 Ele não - retorna 0.099999999999994 lt echo round ((69.1-floor (69.1)) gt Isso retorna 0.1 e é o Solução alternativa que usamos. Tenha em atenção que lt echo (4.1-floor (4.1)) gt retorna 0.1 - então, se você, como nós, testar isso com números baixos, você não vai, como nós, entender por que de repente seu script pára de funcionar, até você gastar Muito tempo, como nós, depurando isso. Então, isso é adorável então. Uma maneira eficaz de comparar dois números reais (incluindo números de ponto flutuante) com alta precisão e ainda poder definir precisão é usando a função BC Math bccomp () Por exemplo: ltphp a 1.23456789 b 1.23456780 precisão 5 se (bccomp (precisão ab) 0) echo true true gt ltphp a sprintf (.17f. 0.1 0.2) b 0.3 se (bccomp (ab 17) 0) eco FALSE FALSE gt Como m dot lebkowskiphp no gmail dot com (php. net language. types. float81416) anotado 9 comentários abaixo: quando o PHP converte um flutuador em uma seqüência de caracteres, o separador decimal usado depende das convenções de localidade atual. No entanto, para declarar um número de ponto flutuante, é preciso sempre usar um ponto completo, caso contrário o código seria dependente da localidade (imagine o pesadelo): ltphp float 1.5 float (1.5) float 1. 5 Erro de sinalização: erro de sintaxe, inesperado, float ( Float) 1.5 float (1.5) float (float) 1,5 float (1) gt Agora, se você possui uma seqüência de caracteres contendo um número localizado, você pode convertê-lo de volta para um número de ponto flutuante usando a seguinte função: ltphp Convert a localized Cadeia numérica em um número de ponto flutuante, seqüência de parâmetros sNumber A seqüência de números localizados para converter. Flutuador de retorno O número convertido. Função str2num (sNumber) aConvenções localeConv () sNumber trim ((string) sNumber) bIsNegative (0 aConvenções nsignposn ampamp (sNumber ampamp) sNumber) sCharacters aConventions decimalpoint. Aconvenções mondecimalpoint. AConventions negativesign sNumber pregreplace (. Pregquote (sCharacters). D.. Trim ((string) sNumber)) iLength strlen (sNumber) if (strlen (aConventions decimalpoint)) sNumber strreplace (aConventions decimalpoint, .. sNumber) if (strlen (aConventions Mundocimalpoint)) sNumber strreplace (aConventions mondecimalpoint, .. sNumber) s NegativoSign aConventions negativesign se (strlen (sNegativeSign) ampamp 0 aConventions nsignposn) bIsNegative (sNegativeSign sNumber sNegativeSign sNumber) if (bIsNegative) sNumber strreplace (aConventions negativesign,. SNumber) fNumber (flutuador ) SNumber se (bIsNegative) fNumber - fNumber return fNumber gt Exemplo: ltphp setLocale (LCALL. FrBE. UTF-8) separador decimal é agora um flutuador de vírgulas - 123456.789 string (string) float vardump (float) float (-123456,789) String vardump (string) (11) -123456,789 vardump (string flutuante) float (-123456) vardump (str2num (string)) fl Aveia (-123456,789) gt Ele também funciona com cordas retornadas pela função numberformat (): ltphp setLocale (LCALL. O separador decimal frBE. UTF-8) agora é um comcom convconjunto localeconv () float - 123456.789 string conv intcurrsymbol. Numerário (float. Conv fracdigits, conv decimalpoint, conv milessep) vardump (float) float (-123456,789) vardump (string) string (15) EUR -123.456,79 vardump (string flutuante) float (0) vardump ( Str2num (string)) float (-123456,79) gt Aqui está uma função para converter um flutuador de formato exponencial em um flutuador de formato decimal, por exemplo, 1.6e12 a 1600000000000. Isso ajudará a resolver o problema especificado por kjohnson acima. Eu testá-lo, mas não em qualquer situação do mundo real, de modo que todos os relatórios de erros de feedback sejam apreciados. A função ltphp exptodec (floatstr) formata uma cadeia de número de ponto flutuante em notação decimal, suporta flutuadores assinados, também suporta formatação não padrão, e. 0,2e2 para 20, e. 1.6E6 a 1600000, -4.566e-12 para -0.000000000004566, 34e10 a 340000000000 Autor: Bob certifique-se de uma string padrão de flutuador php (ou seja, mude 0.2e2 para 20). O php irá automaticamente formatar flutuadores decimais se eles estiverem dentro de um determinado intervalo floatstr (String) (flutuante) (floatstr)) se houver um E na seqüência de float se ((pos strpos (strtolower (floatstr), e)) false) pegue o lado do E, por exemplo 1.6E6 gt exp E6, num 1.6 exp substr (floatstr. Pos 1) num substr (floatstr. 0. pos) strip off num sign, se houver um, e deixá-lo fora se for (não necessário) se (((numsign Num 0)) (numsign -)) num substr (num. 1) else numsign if (numsign) numsign strip off exponencial sign (ou - como em E6) se houver um, caso contrário, lança erro, por exemplo E6 gt se ((expsign exp 0)) (expsign -)) exp substr (exp. 1) else triggererror (Não foi possível converter notação exponencial para notação decimal: flutuante inválido floatstr. EUSERERROR) obter o número de casas decimais para o Direito do ponto decimal (ou 0 se não houver ponto dec), por exemplo, 1,6 gt 1 rightdecplaces ((decpos strpos (num.)) False). 0. strlen (substr (num. Decpos 1)) obtenha o número de casas decimais para a esquerda do ponto decimal (ou o comprimento do número inteiro se não houver ponto dec), por exemplo, 1,6 gt 1 leftdecplaces (decpos falso). Strlen (num). Strlen (substr (num. 0. decpos)) calcula o número de zeros de exp, exp sign e dec places, e. Exp 6, sinal de exp, dec places 1 gt num zeros 5 se (expsign) numzeros exp - rectificações de direito else numzeros exp - leftdecplaces cria uma string com numzeros zeros, p. Ex. 0 5 vezes gt 00000 zeros strpad (. Numzeros. 0) tira decimal de num, e. 1,6 gt 16 se (decpos false) num strreplace (... Num) se o expoente positivo, retornar como 1600000 se (expsign) retornar numsign. Num. Zeros se expoente negativo, retornar como 0.0000016 mais retornar numsign. 0 .. zeros. Num de outra forma, assumir já em notação decimal e retornar novamente return floatstr gt Converter string local em flutuante número ltphp função str2num (str) if (strpos (str..) Lt strpos (str.,)) Str strreplace (... str) Str str (str., ...) mais str strreplace (, ... str) return (float) str str2num (25,01) 25,01 str2num (2,5,01) 25,01 str2num (25,01) 25,01 str2num (2,5,01) 25,01 gt

No comments:

Post a Comment