Sobre a precisão do ponto flutuante e por que ainda a usamos

38

O ponto flutuante sempre foi problemático em termos de precisão em grandes mundos.

Este artigo explica os bastidores e oferece a alternativa óbvia - números de pontos fixos. Alguns fatos são realmente impressionantes, como:

"Bem, 64 bits de precisão levam você à distância mais distante de Plutão do Sol (7,4 bilhões de quilômetros) com precisão subimétrica".

Bem, a precisão do sub-micrômetro é mais do que qualquer necessidade de fps (para posições e até velocidades) e permitiria que você construa mundos realmente grandes.

Minha pergunta é: por que ainda usamos ponto flutuante se o ponto fixo tem essas vantagens? A maioria das APIs de renderização e bibliotecas de física usa ponto flutuante (e sofre suas desvantagens, portanto os desenvolvedores precisam contorná-las).

Eles são muito mais lentos?

Além disso, como você acha que os motores planetários escaláveis, como outerra ou infinito, lidam com a grande escala? Eles usam ponto fixo para posições ou possuem algum algoritmo de divisão de espaço?

system_is_b0rken
fonte
3
O último bit "adicionalmente" provavelmente deve ser uma pergunta separada, para que a principal não seja desviada.
Tetrad
Eu quero descobrir como forçar o ponto fixo ... Meu jogo tem todos os tipos de erros estranhos porque Lua usa a FPU, e o DirectX mexe com a FPU também ... Eu vi coisas como 2 * 9000 = 17995 ou 500 * 10 = 4897 é realmente bobo. Mas o pior erro provavelmente é aquele que é discutido em fóruns Ogre3D, onde 1 + 5 = 4.
speeder
3
Não justificou um comentário; mas se você decidir usar Q-Floats de ponto fixo ( pt.wikipedia.org/wiki/Q_(number_format) ) é seu amigo; eles são ridiculamente rápidos e fáceis de implementar.
Jonathan Dickinson
Então, para resumir, devo ficar com pontos flutuantes (se estou trabalhando em Java ou Python)? - Gastón 26 mins atrás
Gastón

Respostas:

20

Se você me permitir uma ficha descarada, darei um exemplo de um jogo real em que estou trabalhando (link do vídeo do YouTube).

O jogo tem um mundo infinito e processualmente gerado em um mecanismo de física. Ele usa ponto flutuante de precisão única. Depois de algumas centenas de metros de espaço no jogo, problemas de precisão começam a surgir (e pioram progressivamente à medida que você começa).

Minha solução? A cada 200m ou mais, movo o mundo inteiro de volta em 200m em direção à origem (se você deseja encontrar e experimentar um dos protótipos no meu site e exibir a sobreposição de depuração [w] antiga, pode ver isso acontecer).

Por que não usar ponto fixo? Ou precisão dupla? Em vez de precisão única? Porque todo o resto está usando um ponto flutuante de precisão única!

O mecanismo de física que estou usando o usa, o XNA usa, os dados que são carregados na placa de vídeo são formatados como ponto flutuante de precisão única. Até a própria linguagem é projetada para funcionar com números de ponto flutuante - escrever e (mais importante) ler 0.5fé muito mais fácil do que 0x80000000L.

É simplesmente uma questão do que é mais fácil na prática. E o vencedor claro é estar ciente dos problemas de precisão do ponto flutuante e escrever funções bastante simples "mover o mundo de volta ao zero" (ou implementar o particionamento de espaço ou o que melhor se adequar ao seu jogo).

E, finalmente, outro exemplo - Orbiter é um jogo (simulação, na verdade) que realmente precisa se preocupar com precisão. Não apenas no espaço, mas também no tempo (aceleração do tempo mais corpos em órbita - não quero que caiam do céu agora). Ele também usa números de ponto flutuante e emprega um hack para manter a estabilidade.

Andrew Russell
fonte
Eu sempre me perguntei se seria mais fácil para alguns aplicativos mover todo o resto e manter o "player" na origem. Interessante ver que eu não sou o único!
Dash-tom-bang
Eu gosto do seu raciocínio. Gostaria apenas de salientar que, quando se trata de jogos que envolvem ponto fixo de rede, parece ter menos peculiaridades / desvios (a previsão do cliente é mais precisa).
Jonathan Dickinson
Não entendo muito bem seu argumento. E, a propósito, por que as línguas ainda não implementaram ponto fixo? É claro que isso parece ser um motivo para o uso de carros alegóricos, mas isso não explica por que o ponto fixo não foi implementado em todos os lugares.
jokoon
@jokoon Eu pensei que minha resposta era bastante clara. Por que o ponto fixo não é implementado em todos os lugares? Veja a Wikipedia: "Pouquíssimas linguagens de computador incluem suporte embutido para valores de pontos fixos, porque para a maioria dos aplicativos, as representações de ponto flutuante binário ou decimal são geralmente mais simples de usar e precisas o suficiente ". Um bom designer sabe o que omitir - e algo que duplica a funcionalidade de uma maneira que torna realmente fácil para um programador dar um tiro no pé é um bom candidato.
Andrew Russell
Acordado. Os processadores de hoje executam instruções de ponto flutuante com muita facilidade, as instruções têm excelente taxa de transferência e a maioria tem apenas alguns ciclos de latência maior que as instruções inteiras.
Doug65536
11

Primeiro - sim, eles são significativamente mais rápidos. Mesmo que você consiga que o ponto fixo trabalhe tão rápido quanto uma FPU "normal", o ponto flutuante real tem instruções vantajosas, como fsel para interromper a ramificação, ou o SIMD para trabalhar em vários flutuadores ao mesmo tempo. As GPUs também usam ponto flutuante, pelo menos em suas interfaces voltadas para o usuário.

Em segundo lugar, 64 bits também te levam muito longe no ponto flutuante - a maioria das pessoas ainda usa 32, mas a principal vantagem é que ele é escalável. Essa escala de pontos fixos tem uma precisão fixa. Seja medindo o sol em Plutão ou do outro lado da rua, você obtém a mesma precisão. O ponto flutuante fornecerá resultados muito mais precisos quando todos os valores envolvidos forem menores. Como é esperado que as bibliotecas de física genéricas funcionem pelo menos de maneira passável com muitos jogos em escalas diferentes - e alguns jogos em si podem ter escalas muito diferentes -, eles precisam usar um tipo de número que funcione em várias escalas.


fonte
5

Outro ponto importante a destacar é que os carros alegóricos não são tão imprecisos quanto as pessoas aqui parecem pensar. Um flutuador de 32 bits possui 24 bits de precisão inteira. Isso significa que ele é pelo menos tão preciso quanto um valor de ponto fixo de 24 bits para um determinado intervalo. Enquanto os flutuadores se tornam menos precisos quanto maior o valor, um valor de ponto fixo simplesmente transborda e quebra em algum momento. Reduzir a precisão é uma alternativa melhor. Os carros alegóricos também podem transbordar, mas muito, muito mais tarde. Eu gostaria de ver seus rostos quando seu mundo repentinamente se aproxima de -2 ^ 31 devido ao estouro de pontos fixos.

Os valores de ponto flutuante de 64 bits têm precisão de 53 bits, portanto são realmente precisos.

rasmus
fonte
Na verdade, os valores dos pontos flutuantes não transbordam; se o resultado de uma computação é muito grande em magnitude para ser representado, então o resultado é infinito positivo ou negativo.
Abacaxi
3

Em um contexto de FPS, os valores de ponto fixo podem realmente ser um passivo. Perto de zero ponto flutuante é mais preciso. É somente em grandes distâncias que o ponto fixo se torna mais preferível. A resposta é simplesmente que depende do contexto.

Em algo como uma galáxia, você pode usar quadros de referência. Use uma escala enorme para os sistemas solares e, em seguida, use o centro do Sol (ou ponto similar) como ponto de origem para qualquer coisa dentro do sistema. Usando este sistema, você pode comer seu bolo e comê-lo, por assim dizer, e não é difícil de imaginar.

No IIRC, o desenvolvedor do Infinity afirmou que ele estava continuamente interagindo em torno de questões de escala em uma de suas entrevistas.

Rushyo
fonte
É improvável que, em qualquer jogo, você precise da precisão "quase zero" do ponto flutuante. Se você possui uma unidade de um metro, 10 bits de precisão fornecem precisão sub-milimétrica e ainda permitem modelar mais de 4000 km em cada direção, se você estiver com valores de 32 bits. Se você precisar de mais precisão do que um milímetro, poderá mudar mais alguns bits, com certeza. Mover para valores de 64 bits em um jogo espacial daria a você um sistema solar (ou mais?) Com precisão constante em todo o volume.
Dash-tom-bang
De fato. E é por isso que você usaria o Sol de um sistema solar como ponto de referência em um mundo do tamanho de uma galáxia! O ponto é que o método escolhido para lidar com precisão não traz nada para a tabela de qualquer maneira. É discutível, então você também pode usar aquele com o qual sua biblioteca / hardware está sintonizado.
Rushyo 31/08/10
Aliás, trabalhei em um jogo em que tivemos que modelar mais de 4000 km em cada direção. Para compatibilidade com código em outros projetos, ele teve que usar 32 bits para posições. Não é um problema teórico, dadas as demandas comerciais impostas à reutilização de código e o tamanho dos mundos dos jogos atualmente.
1

Se ainda não o fez, deve consultar definitivamente o tutorial Planet Rendering no GameDev.net. Quanto à divisão espacial, uma solução é manter duas variáveis ​​de posição separadas - uma macro escala e uma micro escala. Isso funciona muito bem (testado).

A solução exata depende de como você planeja lidar com distâncias extremas no motor - você planeja portões de salto ou compressão de tempo?

Kornel Kisielewicz
fonte
1

Uma das razões é que a aritmética de ponto flutuante é "boa o suficiente" (ou pelo menos tem sido), produz resultados razoavelmente precisos rapidamente.

Desde que você esteja ciente das limitações da aritmética de ponto flutuante e altere seus algoritmos para lidar com eles (consulte a resposta de Andrew Russell), você produzirá um código que "funcionará".

ChrisF
fonte
-1

Eu estou escrevendo um jogo No meu jogo / programa, eu desenho uma nave espacial na origem usando uma câmera bastante fixa e meu planeta eu desenho usando uma câmera separada. E essas duas coisas resolvem o problema para mim, mas meu planeta ainda não está muito detalhado. Quanto à solução que Andrew Russell mencionou sobre mudar o mundo (e suponho que a câmera e seus habitantes voltem à origem), eu realmente não tentaria isso se você planeja tornar o jogo um jogo em rede. Se você movesse o mundo no aplicativo de servidor com base nos movimentos de cada cliente, o mundo acabaria lutando por uma posição. E tomaria sua posição o tempo todo de todos os jogadores, o que seria uma enorme falha.

user1727819
fonte