Un flottant de 32 bits a une mantisse de 23 bits .
Cela signifie que chaque nombre est représenté par 1.xxx xxx xxx xxx xxx xxx xxx xx fois une puissance de 2, où chaque x est un chiffre binaire, soit 0 ou 1. (À l'exception des nombres dénormalisés extrêmement petits inférieurs à 2- 126 - ils commencent par 0. au lieu de 1., mais je les ignorerai pour ce qui suit)
Ainsi, dans la plage de 2je et 2( i + 1 ) , vous pouvez représenter n'importe quel nombre avec une précision de ± 2( i - 24 )
Par exemple, pour i = 0 , le plus petit nombre dans cette plage est ( 20) ⋅ 1 = 1 . Le plus petit nombre suivant est ( 20) ⋅ ( 1 + 2- 23) . Si vous vouliez représenter 1 + 2- 24 , vous devrez arrondir vers le haut ou vers le bas, pour une erreur de2- 24 deux cas.
In this range: You get accuracy within:
-----------------------------------------------
0.25 - 0.5 2^-26 = 1.490 116 119 384 77 E-08
0.5 - 1 2^-25 = 2.980 232 238 769 53 E-08
1 - 2 2^-24 = 5.960 464 477 539 06 E-08
2 - 4 2^-23 = 1.192 092 895 507 81 E-07
4 - 8 2^-22 = 2.384 185 791 015 62 E-07
8 - 16 2^-21 = 4.768 371 582 031 25 E-07
16 - 32 2^-20 = 9.536 743 164 062 5 E-07
32 - 64 2^-19 = 1.907 348 632 812 5 E-06
64 - 128 2^-18 = 0.000 003 814 697 265 625
128 - 256 2^-17 = 0.000 007 629 394 531 25
256 - 512 2^-16 = 0.000 015 258 789 062 5
512 - 1 024 2^-15 = 0.000 030 517 578 125
1 024 - 2 048 2^-14 = 0.000 061 035 156 25
2 048 - 4 096 2^-13 = 0.000 122 070 312 5
4 096 - 8 192 2^-12 = 0.000 244 140 625
8 192 - 16 384 2^-11 = 0.000 488 281 25
16 384 - 32 768 2^-10 = 0.000 976 562 5
32 768 - 65 536 2^-9 = 0.001 953 125
65 536 - 131 072 2^-8 = 0.003 906 25
131 072 - 262 144 2^-7 = 0.007 812 5
262 144 - 524 288 2^-6 = 0.015 625
524 288 - 1 048 576 2^-5 = 0.031 25
1 048 576 - 2 097 152 2^-4 = 0.062 5
2 097 152 - 4 194 304 2^-3 = 0.125
4 194 304 - 8 388 608 2^-2 = 0.25
8 388 608 - 16 777 216 2^-1 = 0.5
16 777 216 - 33 554 432 2^0 = 1
Donc, si vos unités sont en mètres, vous perdrez une précision millimétrique autour de la bande 16 484 - 32 768 (à environ 16-33 km de l'origine).
On pense généralement que vous pouvez contourner ce problème en utilisant une unité de base différente, mais ce n'est pas vraiment vrai, car c'est la précision relative qui compte.
Si nous utilisons les centimètres comme unité, nous perdons la précision millimétrique dans la bande de 1 048 576-2 097 152 (10-21 km de l'origine)
Si nous utilisons des hectamètres comme unité, nous perdons une précision millimétrique dans la bande 128-256 (13-26 km de l'origine)
... donc changer l'unité sur quatre ordres de grandeur se termine toujours par une perte de précision millimétrique quelque part dans la gamme de dizaines de kilomètres. Tout ce que nous changeons, c'est où exactement dans cette bande il frappe (en raison de l'inadéquation entre la numérotation base-10 et base-2), n'allongeant pas considérablement notre zone de jeu.
La précision exacte de votre jeu dépendra des détails de votre gameplay, de la simulation physique, de la taille de l'entité / des distances de tirage, de la résolution de rendu, etc., il est donc difficile de définir une limite exacte. Il se peut que votre rendu semble bien à 50 km de l'origine, mais vos balles se téléportent à travers les murs, ou un script de gameplay délicat se détraque. Ou vous pouvez trouver que le jeu se déroule bien, mais tout a une vibration à peine perceptible due à des inexactitudes dans la transformation de la caméra.
Si vous connaissez le niveau de précision dont vous avez besoin (par exemple, une plage de 0,01 unité correspond à environ 1 px à votre distance de visualisation / interaction typique, et tout décalage plus petit est invisible), vous pouvez utiliser le tableau ci-dessus pour trouver où vous perdez précision, et reculer de quelques ordres de grandeur pour la sécurité en cas d'opérations avec perte.
Mais si vous pensez à des distances énormes, il peut être préférable de contourner tout cela en recentrant votre monde pendant que le joueur se déplace. Vous choisissez une région de forme carrée ou cubique conservativement petite autour de l'origine. Chaque fois que le joueur se déplace en dehors de cette région, traduisez-les, ainsi que tout ce qui se trouve dans le monde, recule de la moitié de la largeur de cette région, en gardant le joueur à l'intérieur. Puisque tout bouge ensemble, votre joueur ne verra pas de changement. Des inexactitudes peuvent encore se produire dans des régions éloignées du monde, mais elles sont généralement beaucoup moins visibles là-bas que sous vos pieds, et vous êtes assuré d'avoir toujours une haute précision disponible près du joueur.
Il est difficile de répondre car cela dépend de l'échelle de votre physique: Quelle est la vitesse de mouvement minimale acceptable qui ne doit PAS être arrondie à zéro?
Si vous avez besoin d'un monde vaste et d'une physique cohérente, il est préférable d'utiliser une classe à points fixes.
Par exemple, tirer une balle de canon de n'importe où dans le monde vous donnera le même résultat et un point fixe 64 bits (32,32) vous donne une énorme quantité de précision et plus que tout ce qui est perceptible dans la plupart des jeux. Si votre unité mesure 1 mètre, vous êtes toujours à une précision de 232 picomètres à 2147483 km de l'origine.
Vous pouvez toujours effectuer la physique locale en virgule flottante dans la cellule locale pour économiser sur le travail de programmation et utiliser un moteur physique standard. Il restera raisonnablement cohérent à toutes fins pratiques.
En bonus, la phase large et l'AABB ont tendance à être plus rapides en virgule fixe en raison de la latence du FPU. Il est également plus rapide de convertir un point fixe en index octree (ou quadtree) car vous pouvez effectuer un masquage de bits simple.
Ces opérations ne bénéficient pas autant des instructions SIMD et du pipelining qui masqueraient normalement la latence des FPU.
Vous pouvez convertir les positions en virgule flottante APRÈS avoir soustrait la position de la caméra en virgule fixe pour tout rendre, en évitant les problèmes de virgule flottante dans un grand monde et en utilisant toujours un moteur de rendu classique utilisant des virgules flottantes.
la source
Vous pouvez l'éviter complètement par multiplication.
Au lieu de travailler avec des flotteurs, multipliez-les simplement par 10 ^ (x), stockez-les et, si nécessaire, multipliez-les à nouveau par 10 ^ (- x).
De cela, cela dépend du type d'int que vous souhaitez utiliser.
la source