결정적 방식으로 부동 소수점 숫자 처리
부동 소수점은 결정적입니다. 글쎄요. 복잡하다.
부동 소수점 숫자에 대한 많은 문헌이 있습니다.
그리고 그들이 어떻게 문제가되는지 :
초록. 적어도 단일 스레드에서 동일한 순서로 발생하는 동일한 데이터를 가진 동일한 작업은 결정 론적이어야합니다. 따라서 입력에 대한 걱정과 재정렬로 시작할 수 있습니다.
문제를 일으키는 그러한 입력 중 하나는 시간입니다.
우선, 항상 같은 타임 스텝을 계산해야합니다. 시간을 측정하지 말라고 말하는 것이 아닙니다. 시간의 변화는 시뮬레이션의 노이즈 소스이기 때문에 물리 시뮬레이션에 시간을 보내지 않을 것이라고 말하고 있습니다.
물리 시뮬레이션에 시간을 전달하지 않으면 왜 시간을 측정합니까? 시뮬레이션 단계를 언제 호출해야하는지 알기 위해 경과 시간을 측정하려고합니다 (잠자기를 사용한다고 가정 할 경우).
그러므로:
- 측정 시간 : 예
- 시뮬레이션에서 시간 사용 : 아니오
이제 명령 순서 변경.
컴파일러는와 f * a + b
같은 것을 결정할 수 b + f * a
있지만 결과가 다를 수 있습니다. 또한 fmadd로 컴파일 하거나 SIMD를 사용 하여 작성하는 것과 같은 여러 줄을 취 하거나 현재 생각할 수없는 다른 최적화를 결정할 수 있습니다. 그리고 동일한 작업이 동일한 순서로 발생하기를 원한다는 것을 기억하십시오. 이는 어떤 작업이 수행되는지 제어하려는 이유입니다.
그리고 아니요, double을 사용해도 저장되지 않습니다.
특히 네트워크에서 부동 소수점 숫자를 동기화하려면 컴파일러와 해당 구성에 대해 걱정해야합니다. 동일한 작업을 수행하려면 빌드를 가져와야합니다.
틀림없이 글쓰기 어셈블리가 이상적 일 것입니다. 그렇게하면 어떤 작업을 수행할지 결정할 수 있습니다. 그러나 이는 여러 플랫폼을 지원하는 데 문제가 될 수 있습니다.
그러므로:
고정 소수점 수의 경우
플로트가 메모리에 표시되는 방식으로 인해 큰 값은 정밀도를 잃게됩니다. 값을 작게 (클램프) 유지하면 문제가 완화 될 수 있습니다. 따라서 큰 속도와 방이 없습니다. 또한 터널링의 위험이 적기 때문에 이산 물리학을 사용할 수 있습니다.
반면에 작은 오류가 누적됩니다. 자르십시오. 나는 정수형으로 스케일하고 캐스트하는 것을 의미합니다. 그렇게하면 아무것도 구축되지 않는다는 것을 알 수 있습니다. 정수 유형으로 머무를 수있는 작업이 있습니다. 부동 소수점으로 돌아 가야 할 때 스케일링을 캐스팅하고 실행 취소합니다.
나는 스케일이라고 말합니다. 아이디어는 1 단위가 실제로 2의 거듭 제곱으로 표시된다는 것입니다 (예 : 16384). 그것이 무엇이든, 그것을 일정하게 만들고 사용하십시오. 기본적으로 고정 소수점 숫자로 사용하고 있습니다. 사실, 신뢰할 수있는 라이브러리의 적절한 고정 소수점 수를 훨씬 더 잘 사용할 수 있다면.
나는 자르고있다. 반올림 문제에 대해, 이는 캐스트 후 얻은 값의 마지막 비트를 신뢰할 수 없음을 의미합니다. 따라서 캐스트 스케일이 필요하기 전에 1 비트 이상을 확보 한 후 나중에 잘립니다.
그러므로:
- 값을 작게 유지하십시오 : 예
- 주의해서 반올림 : 예
- 가능한 경우 고정 소수점 수 : 예
잠깐, 왜 부동 소수점이 필요한가요? 정수 유형으로 만 작업 할 수 없습니까? 아 맞다 삼각법 및 복사. 삼각법 및 복사에 대한 테이블을 계산하여 소스에서 구워 낼 수 있습니다. 또는 고정 소수점 숫자를 대신 사용하는 것을 제외하고 부동 소수점 숫자로 알고리즘을 계산하는 데 사용되는 알고리즘을 구현할 수 있습니다. 예, 메모리, 성능 및 정밀도의 균형을 유지해야합니다. 그러나 부동 소수점 숫자를 피하고 결정론을 유지할 수 있습니다.
오리지널 PlayStation에서 그런 것들을했다는 것을 알고 있습니까? 제발 , 패치를 만나 내 개 .
그건 그렇고, 나는 그래픽에 부동 소수점을 사용하지 말라고 말하지 않습니다. 물리학을 위해서만 물리학에 따라 위치가 달라집니다. 그러나 알다시피 충돌체가 모델과 일치하지 않아도됩니다. 모델이 잘린 결과를보고 싶지 않습니다.
따라서 : 고정 소수점 숫자를 사용하십시오.
분명히 말하면, 부동 소수점의 작동 방식을 지정할 수있는 컴파일러를 사용할 수 있고 그 정도면 충분합니다. 항상 옵션은 아닙니다. 게다가, 우리는 결정론을 위해 이것을하고 있습니다. 고정 소수점 숫자는 정밀도가 제한되어 있어도 오류가 없음을 의미하지 않습니다.
나는 "고정 포인트 번호가 어렵다"고 생각하지 않는 것이 좋은 이유라고 생각합니다. 그리고 당신이 그것들을 사용해야 할 좋은 이유를 원한다면, 그것은 결정론, 특히 플랫폼 간 결정론입니다.
또한보십시오:
부록 : 나는 세상의 크기를 작게 유지할 것을 제안하고 있습니다. 그러나 두 OP ans Jibb Smart는 원점 수레에서 멀어지면 정확도가 떨어집니다. 그것은 물리학에 영향을 미치며, 이는 세계의 가장자리보다 훨씬 일찍 보일 것입니다. 고정 소수점 숫자는 고정 정밀도를 가지며 어디에서나 동일하게 좋을 것입니다. 결정론을 원한다면 좋습니다. 또한 우리가 일반적으로 물리를하는 방식에는 작은 변형을 증폭시키는 성질이 있다고 언급하고 싶습니다. Incredible Machine and Contraption Maker의 버터 플라이 효과 결정적 물리를 참조하십시오 .
물리를 수행하는 또 다른 방법
부동 소수점 숫자의 정밀도에서 작은 오류가 증폭되는 이유는 그 숫자에 대해 반복을 수행하기 때문입니다. 각 시뮬레이션 단계는 마지막 시뮬레이션 단계의 결과를 가져 와서 수행합니다. 오류 발생시 오류를 누적합니다. 그것은 당신의 나비 효과입니다.
동일한 머신에서 단일 스레드를 사용하는 단일 빌드가 동일한 입력으로 다른 출력을 생성한다고 생각하지 않습니다. 그러나 다른 컴퓨터에서는 또는 다른 빌드에서 가능합니다.
거기에서 테스트 할 논증이 있습니다. 작업 방식을 정확하게 결정하고 대상 하드웨어를 테스트 할 수 있다면 다른 동작을 가진 빌드를 작성해서는 안됩니다.
그러나 너무 많은 오류가 누적되는 작동하지 않는 것에 대한 주장도 있습니다. 아마도 이것은 다른 방식으로 물리학을 할 수있는 기회 일 것입니다.
아시다시피, 연속적이고 이산적인 물리학이 있습니다. 둘 다 각 단계에서 각 물체가 얼마나 많은 양으로 진행되는지에 관한 연구입니다. 그러나 연속 물리학은 충돌이 발생했는지 확인하기 위해 서로 다른 가능한 순간을 조사하는 대신 충돌 순간을 파악할 수있는 수단을 가지고 있습니다.
따라서, 나는 다음을 제안하고있다 : 연속적인 물리학 기법을 사용하여 각 물체의 다음 충돌이 언제 일어날 지 알아 내고, 단일 시뮬레이션 단계보다 훨씬 더 큰 시간 간격을두고. 그런 다음 가장 가까운 충돌 순간을 가져 와서 그 순간의 모든 위치를 알아냅니다.
그렇습니다. 이는 단일 시뮬레이션 단계의 많은 작업입니다. 즉, 시뮬레이션이 즉시 시작되지 않습니다.
... 그러나 다음 충돌이 언제 발생할지 이미 알고 있기 때문에 (또는 큰 타임 스텝에서 충돌이 발생하지 않음) 매번 충돌을 확인하지 않고 다음 몇 개의 시뮬레이션 단계를 시뮬레이션 할 수 있습니다. 더욱이, 시뮬레이션이 큰 타임 스텝에 도달하면, 우리는 미리 계산 한 위치를 배치하기 때문에 시뮬레이션에 축적 된 오류는 무의미합니다.
이제 각 시뮬레이션 단계에서 충돌을 확인하는 데 사용한 시간 예산을 사용하여 발견 된 충돌 이후의 다음 충돌을 계산할 수 있습니다. 즉, 큰 시간 단계를 사용하여 미리 시뮬레이션 할 수 있습니다. 범위가 제한된 월드 (거대한 게임에서는 작동하지 않음)를 가정하면 시뮬레이션을위한 미래 상태 대기열이 있어야합니다. 그런 다음 각 프레임은 마지막 상태에서 다음 상태로 보간됩니다.
보간을 주장합니다. 그러나 가속이 있기 때문에 모든 것을 같은 방식으로 보간 할 수는 없습니다. 대신 각 개체의 가속도를 고려하여 보간해야합니다. 그 문제에 대해 우리는 큰 시간 단계와 같은 방식으로 위치를 업데이트 할 수 있습니다 (또한 동일한 움직임에 대해 두 가지 다른 구현을 사용하지 않기 때문에 오류가 덜 발생합니다).
참고 :이 부동 소수점 숫자를 수행하는 경우이 방법으로 객체가 원점에서 멀어 질수록 다르게 동작하는 문제를 해결할 수 없습니다. 그러나 원점에서 멀어 질수록 정밀도가 손실되는 것은 사실이지만 여전히 결정적입니다. 사실, 그것은 원래 그것을 제기하지 않은 이유입니다.
추가
의견의 OP에서 :
아이디어는 플레이어가 자신의 머신을 xml 또는 json과 같은 일부 형식으로 저장하여 각 조각의 위치와 회전을 기록 할 수 있다는 것입니다. 그런 다음 해당 xml 또는 json 파일을 사용하여 다른 플레이어의 컴퓨터에서 컴퓨터를 재생성합니다.
따라서 이진 형식이 없습니다. 즉, 복구 된 부동 소수점 숫자가 원본과 일치하는지 걱정할 필요가 없습니다. 참고 : Float Precision Revisited : 9 Digit Float Portability