플로트를 사용하여 만들 수있는 가장 큰 “상대적인”수준은 무엇입니까? 것처럼 부동 소수점 작동 방식으로 인해 충분히

던전 포위 공격 및 KSP와 같은 게임에서 시연 한 것처럼 부동 소수점 작동 방식으로 인해 충분히 큰 레벨에서 글리치가 발생하기 시작합니다. 정확도를 잃지 않고 1e-20을 1e20에 추가 할 수 없습니다.

레벨의 크기를 제한하기로 한 경우, 물체가 고르기 시작할 때까지 물체가 움직일 수있는 최소 속도를 어떻게 계산합니까?



답변

32 비트 플로트에는 23 비트 가수가 있습니다. 있습니다.

즉, 각 숫자 1.xxx XXX XXX XXX XXX XXX XXX XX 배 일부 전력보다 매우 작은 수의 비정규 제외한 각 X는 이진수는 2, 0 또는 1 (의로서 표현되는

2126

-그들은 1 대신에 0으로 시작하지만 다음에 나오는 것들은 무시합니다.)

그래서의 범위에서

2나는

2(나는+1)

, 당신의 정확도 내에서 임의의 숫자를 나타낼 수 있습니다

±2(나는24)

예를 들어,

나는=0

경우이 범위에서 가장 작은 숫자는

(20)1=1

입니다. 다음으로 가장 작은 숫자는

(20)(1+223)

입니다. 당신이 표현하고 싶었다면

1+224

, 당신의 오류에 대한 아래로 라운드까지 또는를해야합니다

224

중 하나의 방법을.

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

따라서 단위가 미터라면 16 484-32 768 대역 (원점에서 약 16-33km)에서 밀리미터 정밀도를 잃게됩니다.

일반적으로 다른 기본 단위를 사용하여이 문제를 해결할 수 있다고 생각되지만, 상대적인 정밀도가 중요하기 때문에 사실이 아닙니다 .

  • 센티미터를 단위로 사용하면 1,048576-2 097152 밴드 (원점에서 10-21km)에서 밀리미터 정밀도를 잃게됩니다.

  • 우리가 단위로 헥타 미터를 사용하면 128-256 밴드 (원점에서 13-26km)에서 밀리미터 정밀도를 잃게됩니다.

… 단위를 4 배 이상으로 변경하면 수십 킬로미터의 밀리미터 정밀도가 손실됩니다. 우리가 이동하는 것은 연주 가능한 영역을 크게 확장시키지 않으면 서 정확히 그 밴드에서 (베이스 10과베이스 2 번호 매기기 사이의 불일치로 인해) 충돌하는 것입니다.

정확하게 게임이 허용 할 수있는 정확도는 게임 플레이의 세부 사항, 물리 시뮬레이션, 엔티티 크기 / 그리기 거리, 렌더링 해상도 등에 따라 달라 지므로 정확한 컷오프를 설정하기가 어렵습니다. 렌더링은 원점에서 50km 떨어진 곳에서 잘 보이지만 총알이 벽을 통해 순간 이동하거나 민감한 게임 플레이 스크립트가 엉망입니다. 또는 게임이 잘 진행되는 것을 알 수 있지만 모든 것은 카메라 변형의 부정확성으로 인해 거의 인식 할 수없는 진동이 있습니다.

필요한 정확도 수준을 알고있는 경우 (예 : 0.01 단위의 범위가 일반적인보기 / 상호 작용 거리에서 약 1 픽셀로 매핑되고 더 작은 오프셋은 보이지 않음) 위의 표를 사용하여 해당 위치를 잃는 위치를 찾을 수 있습니다 손실 된 작업의 경우 안전을 위해 몇 배의 수준으로 거슬러 올라갑니다.

그러나 거리가 너무 멀다고 생각한다면 플레이어가 움직일 때 세상 을 최근 에 풀어서이 모든 것을 회피하는 것이 좋습니다 . 원점 주위에 보수적으로 작은 정사각형 또는 큐브 모양의 영역을 선택합니다. 플레이어가이 지역 밖으로 이동할 때마다 플레이어를 내부에 유지하면서이 지역의 너비의 절반만큼 다시 세계의 모든 것을 번역합니다. 모든 것이 함께 움직이므로 플레이어는 변화를 볼 수 없습니다. 부정확성은 여전히 ​​먼 지역에서 발생할 수 있지만 일반적으로 발밑에서 발생하는 것보다 눈에 띄지 않으며 플레이어 근처에서 항상 높은 정밀도를 보장합니다.


답변

물리학의 규모에 따라 대답하기가 어렵습니다. 허용 되지 않는 최소 이동 속도는 얼마입니까? 제로로 반올림은?

큰 세계와 일관된 물리가 필요한 경우 고정 소수점 클래스를 사용하는 것이 좋습니다.

예를 들어, 세계 어느 곳에서나 대포를 쏘면 동일한 결과를 얻을 수 있으며 64 비트 고정 소수점 (32.32)은 대부분의 게임에서 인식 할 수있는 것보다 훨씬 정밀하고 정밀합니다. 단위가 1 미터 인 경우 여전히 원점에서 2147483km 떨어진 232 피코 미터 정밀도입니다.

프로그래밍 작업을 줄이고 상용 물리 엔진을 사용하기 위해 로컬 셀 내 부동 소수점에서 로컬 물리를 수행 할 수 있습니다. 그것은 모든 실제적인 목적에 대해 여전히 합리적 일 것입니다.

보너스의 광범위한 단계와 AABB는 FPU 대기 시간으로 인해 고정 소수점에서 더 빠른 경향이 있습니다. 간단한 비트 마스킹을 수행 할 수 있으므로 고정 소수점을 옥트리 (또는 쿼드 트리) 인덱스로 변환하는 것이 더 빠릅니다.

이러한 작업은 일반적으로 FPU 대기 시간을 숨기는 SIMD 명령 및 파이프 라이닝의 이점을 크게 얻지 못합니다.

고정 된 위치에서 카메라의 위치를 ​​빼면 모든 위치를 렌더링 한 후 위치를 부동 소수점으로 변환 할 수있어 큰 세계에서 부동 소수점 문제를 피하고 여전히 부동 소수점을 사용하는 일반 렌더러를 사용할 수 있습니다.


답변

곱셈으로 피할 수 있습니다.
float를 사용하는 대신 10 ^ (x)를 곱한 다음 저장하고 필요할 때 다시 10 ^ (-x)를 곱하십시오.
그로부터 사용하려는 int 유형에 따라 다릅니다.


답변