Acerca de la precisión de coma flotante y por qué todavía la usamos


38

El punto flotante siempre ha sido problemático para la precisión en mundos grandes.

Este artículo explica detrás de escena y ofrece la alternativa obvia: números de punto fijo. Algunos hechos son realmente impresionantes, como:

"Bueno, 64 bits de precisión te llevan a la mayor distancia de Plutón desde el Sol (7,4 mil millones de km) con precisión submicrométrica".

Bueno, la precisión submicrométrica es más que cualquier necesidad de fps (para posiciones e incluso velocidades), y le permitiría construir mundos realmente grandes.

Mi pregunta es, ¿por qué todavía usamos coma flotante si el punto fijo tiene tales ventajas? La mayoría de las API de renderizado y las bibliotecas de física usan coma flotante (y sufren sus desventajas, por lo que los desarrolladores deben evitarlas).

¿Son mucho más lentos?

Además, ¿cómo crees que los motores planetarios escalables como outerra o infinity manejan a gran escala? ¿Utilizan puntos fijos para las posiciones o tienen algún algoritmo de división de espacio?


3
El último bit "adicionalmente" probablemente debería ser una pregunta separada para que la principal no se desvíe.
Tetrad

Quiero averiguar cómo forzar el punto fijo ... Mi juego tiene todo tipo de errores extraños porque Lua usa la FPU, y DirectX también juega con FPU ... He visto cosas como 2 * 9000 = 17995 o 500 * 10 = 4897 es realmente tonto. Pero el peor error probablemente es uno que se discute en los foros de Ogre3D, donde 1 + 5 = 4.
deslizador

3
No justificó un comentario; pero si decides usar Q-Floats de punto fijo ( en.wikipedia.org/wiki/Q_(number_format) ) eres tu amigo; son ridículamente rápidos y fáciles de implementar.
Jonathan Dickinson el

Entonces, para resumir, ¿debo seguir con los puntos flotantes (si estoy trabajando en Java o Python)? - Gastón hace 26 minutos
Gastón

Respuestas:


20

Si me permites un complemento descarado, te daré un ejemplo de un juego real en el que estoy trabajando (enlace de video de YouTube).

El juego tiene un mundo infinito generado por procedimientos en un motor de física. Utiliza punto flotante de precisión simple. Después de unos pocos cientos de metros de espacio de juego, comienzan a surgir problemas de precisión (y empeoran progresivamente a medida que te alejas del origen).

¿Mi solución? Cada 200 m aproximadamente, muevo el mundo entero 200 m hacia el origen (si te interesa encontrar y probar uno de los prototipos en mi sitio y aparece la superposición de depuración [w] orld, puedes ver que esto sucede).

¿Por qué no usar punto fijo? ¿O doble precisión? En lugar de precisión simple? ¡Porque todo lo demás está usando un punto flotante de precisión simple!

El motor de física que estoy usando lo usa, XNA lo usa, los datos que se cargan en la tarjeta gráfica están formateados como punto flotante de precisión simple. Incluso el lenguaje en sí está diseñado para trabajar con números de punto flotante: escribir y (más importante) leer 0.5fes mucho más fácil que 0x80000000L.

Es simplemente una cuestión de lo que es más fácil en la práctica. Y el claro ganador es ser consciente de los problemas de precisión del punto flotante y escribir funciones bastante simples de "mover el mundo de regreso a cero" (o implementar la partición del espacio o lo que se adapte a su juego).

Y finalmente otro ejemplo: Orbiter es un juego (simulación, realmente) que realmente necesita preocuparse por la precisión. No solo en el espacio sino también en el tiempo (aceleración del tiempo más cuerpos en órbita, no quiero que se caigan del cielo, ahora). También utiliza números de coma flotante y emplea un truco para mantener la estabilidad.


Siempre me pregunté si sería más fácil para algunas aplicaciones mover todo lo demás y mantener al "jugador" en el origen. ¡Es interesante ver que no soy el único!
dash-tom-bang

Me gusta tu razonamiento. Solo me gustaría señalar que cuando se trata de juegos que involucran redes, el punto fijo parece tener menos peculiaridades / desviaciones (la predicción del cliente es más precisa).
Jonathan Dickinson

No entiendo muy bien tu argumento. Y por cierto, ¿por qué los idiomas aún no han implementado el punto fijo? Por supuesto, esa parece ser una razón para utilizar flotadores, pero eso no explica por qué el punto fijo no se ha implementado en todas partes.
jokoon

@jokoon, pensé que mi respuesta era bastante clara. ¿Por qué el punto fijo no se implementa en todas partes? Basta con mirar a Wikipedia: "Muy pocos lenguajes de computadora incluyen soporte incorporado para valores de punto fijo, porque para la mayoría de las aplicaciones, las representaciones de punto flotante binario o decimal son generalmente más simples de usar y lo suficientemente precisas ". Un buen diseñador sabe qué omitir, y algo que duplica la funcionalidad de una manera que facilita realmente que un programador se dispare en el pie es un buen candidato.
Andrew Russell el

Convenido. Los procesadores de hoy ejecutan instrucciones de coma flotante muy fácilmente, las instrucciones tienen un rendimiento excelente y la mayoría son solo unos pocos ciclos más de latencia que las instrucciones enteras.
doug65536

11

Primero, sí, son significativamente más rápidos. Incluso si puede hacer que el punto fijo funcione tan rápido como una FPU "normal", el punto flotante real tiene instrucciones ventajosas como fsel para detener la ramificación o SIMD para trabajar en muchos flotadores a la vez. Las GPU también usan coma flotante, al menos en sus interfaces orientadas al usuario.

En segundo lugar, 64 bits también lo llevan bastante lejos en coma flotante: la mayoría de las personas todavía usan 32, pero la ventaja principal es que escala. Esa escala de punto fijo tiene una precisión fija. Ya sea que esté midiendo el sol a Plutón, o al otro lado de la calle, obtiene la misma precisión. El punto flotante le dará resultados mucho más precisos cuando todos los valores involucrados sean más pequeños. Dado que se espera que las bibliotecas de física genéricas funcionen, al menos de manera aceptable, con muchos juegos a diferentes escalas, y algunos juegos en sí pueden tener escalas muy diferentes, necesitan usar un tipo de número que funcione en muchas escalas.


5

Otro punto importante es que las carrozas no son tan imprecisas como parece pensar la gente de aquí. Un flotante de 32 bits tiene 24 bits de precisión entera completa. Esto significa que es al menos tan preciso como un valor de punto fijo de 24 bits para cualquier rango dado. Si bien los flotadores se vuelven menos precisos cuanto mayor sea el valor, un valor de punto fijo simplemente se desbordará y se ajustará en algún momento. Reducir la precisión es una mejor alternativa. Los flotadores también pueden desbordarse, pero mucho, mucho más tarde. Me gustaría ver tus caras cuando tu mundo de repente se envuelva a -2 ^ 31 debido al desbordamiento de punto fijo.

Los valores de coma flotante de 64 bits tienen una precisión entera de 53 bits, por lo que son realmente precisos.


Los valores de coma flotante en realidad no se desbordan; Si el resultado de un cálculo es demasiado grande para ser representado, entonces el resultado es Infinito positivo o negativo.
Piña

3

En un contexto de FPS, los valores de punto fijo en realidad podrían ser un pasivo. El punto flotante cercano a cero es más preciso. Es solo a grandes distancias, el punto fijo se vuelve más preferible. La respuesta es simplemente que depende del contexto.

En algo así como una galaxia, puedes usar marcos de referencia. Use una escala enorme para los sistemas solares y luego use el centro del Sol (o un punto similar) como punto de origen para cualquier cosa dentro del sistema. Usando este sistema puedes tener tu pastel y comértelo, por así decirlo, y no es difícil de imaginar.

IIRC, el desarrollador de Infinity declaró que estaba continuamente iterando sobre problemas de escala en una de sus entrevistas.


Es poco probable que en cualquier juego necesites la precisión "cercana a cero" del punto flotante. Si tiene una unidad de un metro, 10 bits de precisión le brindan una precisión submilimétrica y aún le permiten modelar más de 4000 km en cada dirección si está atascado con valores de 32 bits. Si necesita más precisión que un milímetro, puede cambiar algunos bits más, seguro. Pasar a valores de 64 bits en un juego espacial te daría un sistema solar (¿o más?) Con precisión constante en todo el volumen.
dash-tom-bang

En efecto. ¡Y es por eso que usarías el Sol de un sistema solar como punto de referencia en un mundo del tamaño de una galaxia! El punto es que el método elegido para manejar la precisión no aporta nada a la mesa de ninguna manera. Es discutible, por lo que también podría usar el que está sintonizado con su biblioteca / hardware.
Rushyo

Por cierto, trabajé en un juego en el que tuvimos que modelar más de 4000 km en cada dirección. Para la compatibilidad con el código en otros proyectos, tuvo que usar 32 bits para las posiciones. No es un problema teórico, dadas las demandas comerciales impuestas a la reutilización de códigos y el tamaño de los mundos de los juegos de hoy.

1

Si aún no lo hiciste, definitivamente deberías consultar el tutorial de Planet Rendering en GameDev.net. En cuanto a la división espacial, una solución es mantener dos variables de posición separadas: una macroescala y una microescala. Esto funciona bastante bien (probado).

La solución exacta depende de cómo planea manejar distancias extremas en el motor: ¿planea puertas de salto o compresión de tiempo?


1

Una de las razones es que la aritmética de coma flotante es "suficientemente buena" (o al menos lo ha sido), produce resultados bastante precisos rápidamente.

Siempre y cuando conozca las limitaciones de la aritmética de coma flotante y cambie sus algoritmos para hacerles frente (ver la respuesta de Andrew Russell), producirá un código que "funciona".


-1

Estoy escribiendo un juego En mi juego / programa, dibujo una nave espacial en el origen usando una cámara bastante fija y mi planeta dibujo con una cámara separada. Y estas dos cosas se encargan del problema para mí, pero mi planeta aún no está muy detallado. En cuanto a la solución que Andrew Russell mencionó sobre mover el mundo (y supongo que la cámara y sus habitantes volverán al origen), realmente no lo intentaría si alguna vez planea hacer del juego un juego en red. Si movió el mundo en la aplicación del servidor en función de los movimientos de cada cliente, el mundo terminaría luchando por un puesto. Y tomaría su posición todo el tiempo de todos los que juegan, lo que sería un gran problema.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.