Foro de elhacker.net

Programación => .NET (C#, VB.NET, ASP) => Mensaje iniciado por: z3nth10n en 22 Enero 2015, 14:29 pm



Título: Duda sobre la precisión en comas/puntos flotantes en .NET
Publicado por: z3nth10n en 22 Enero 2015, 14:29 pm
Después de tanto tiempo, ¡Hola a todos!

Bueno, pues estoy aprendiendo Unity desde hace tiempo.

El caso es que bueno, como gamer que soy, he jugado a Minecraft y se lo que son las Farlands (para el que no lo sepa, una zona muy alejada del spawn donde las cosas se generan parcial o incorrectamente debido a la gran cantidad de digitos que dicha posición tiene (esto causa que las aproximaciones matemáticas no selleven acabo correctamente causando bugs y demás)).

Estas "Farlands" están en todos los juegos que sean de mundo abierto.

Con Unity puedes probar a alcanzar dichos limites donde todo comienza a ser extraño y un poco escalofriante. Para poner un ejemplo, cuando mueves un objeto a posiciones mayores de 100,000 unidades el editor de la IDE te avisa de que pueden haber problemas referentes a punto flotante. He probado a mover un jugador a más de 1 millón de unidades de (0, 0, 0) en los ejes X y Z y la verdad es que es bastante curioso, todo comienza a vibrar y apenas si puedes moverte y saltar correctaente sin que el personaje no te vaya a tirones.

Estoy intentando entender el concepto sobre estos errores de precisión, para ello he leido los limites de los siguientes tipos: floats, doubles y decimal; con este enlace: http://www.blackwasp.co.uk/CSharpNumericDataTypes.aspx

He estado leyendo página en inglés, pero no me he enterado de mucho (refente a Unity).

En este post: http://answers.unity3d.com/questions/240456/strange-shaking-or-mystery-far-lands.html el usuario que respondió dijo lo siguiente:

Citar
The further you are from 0.0 the worse it gets where over 10 000 you'll start to see anomalies where the floating point imprecision will be about 0.1.

No entiendo porque la imprecisión es de 0.1, es decir, la cantidad máxima de digitos que tiene el tipo float (el que usa Unity por defecto), este según la página de arriba tiene 7 digitos decimales de precisión es decir, que 10 000 o 10^4 tendría que mover 4 digitos nada más, haciendo que por ejemplo:

1/ 9 = 0.1111112 + 10 000 = 10000.112, y luego tomando solo la parte decimal 0.112 - 0.111 = 0.001 no??

Necesito que alguien me aclare esa duda...

EDITO: La duda ya la tengo resuelta ;) Más abajo dejé un link, por si alguien quiere revisar un sitio donde se explica de forma muy sencilla

Tengo otra consulta, y la pregunta es la siguiente, Unity usa floats (32 bits) por defecto y Java doubles (64 bits), mi pregunta es, porque no usa Unity doubles también, tienen más precisión, y es mejor, tengo tres posibles candidatos como posibles razón:

- Floats son más rápidos de procesar
- Unity solo está dedicado a una plataforma (Windows), mientras que java es multiplataforma, Unity en principio también lo es, pero al usar .NET tiene sus limitaciones...
- Las GPUs operan en single foating-points según este post: http://answers.unity3d.com/questions/667069/oculus-rift-camera-shaking-when-far-away-from-000.html (pero no creo que sea la razón)

Cual creéis que pueda ser la posible razón?

Un saludo.


Título: Re: Precisión y comas/puntos flotantes en .NET
Publicado por: Oblivi0n en 22 Enero 2015, 14:40 pm
El problema viene dado porque los numeros son representados mendiante el standard IEEE-754, al pasar un numero de decimal a IEE-754 se genera una pequeña variación de precisión ( que aumenta a medida que el numero aumenta de valor o de precisión). Además a esto habría que sumarle el epsilon de maquina , que es el menor numero que puede ser representado dada una precisión ( en caso de 32 bits 1,19*10^-7)


Título: Re: Precisión y comas/puntos flotantes en .NET
Publicado por: z3nth10n en 22 Enero 2015, 15:12 pm
Muchas gracias Oblivi0n...

Iba a editar el post, porque recién salí del instituto y no pude terminar el post,

http://www.davenewson.com/dev/unity-notes-on-rendering-the-big-and-the-small

En este documento, se explica también un poco más sobre la duda que tenía más arriba:

Citar
An object at 1.234567 has a floating point accuracy to 6 decimal places (a micrometer), while an object at 76543.21 can only have two decimal places (a centimeter), and is thus less accurate.

Lo explica exactamente como yo necesitaba saberlo :P



Esto es un problema, porque, si yo hago un juego, y doy la posibilidad de poner explosivos, y que estos tengan knockback (retroceso), entonces si un usuario inventa esto:

https://www.youtube.com/watch?v=iDcYnAzwV0E

Y lo prueba, puede que cuando llegue a la zona de 160 km vea todo como yo dije al principio?  :laugh:

Estaría bien...

También se puede probar a escalar las cosas a un tamaño más pequeño, para poder conseguir más terreno de juego, pero esto puede ser peor, porque dados unos limites, las cosas pueden dejar de renderizarse o directamente, no se... xD

Sin doubles un juego a mundo abierto no tiene gracia, porque entonces que, si pongo que un personaje pueda recorrer 3 m/s andando normal, los 100km (que es la zona, donde los usuarios pueden comenzar a notar los efectos de la lejanía) los puede alcanzar a ritmo constante en unas 9 horas 15 minutos y 33 segundos :P

Algo tendré que hacer al respecto... :/