Về độ chính xác của dấu phẩy động và tại sao chúng ta vẫn sử dụng nó


38

Điểm nổi luôn gây rắc rối cho độ chính xác trên các thế giới rộng lớn.

Bài viết này giải thích hậu trường và đưa ra giải pháp thay thế rõ ràng - số điểm cố định. Một số sự thật thực sự ấn tượng, như:

"Độ chính xác 64 bit đưa bạn đến khoảng cách xa nhất của Sao Diêm Vương từ Mặt trời (7,4 tỷ km) với độ chính xác dưới micromet."

Độ chính xác dưới micromet tốt hơn bất kỳ nhu cầu fps nào (đối với các vị trí và thậm chí cả vận tốc), và nó sẽ cho phép bạn xây dựng những thế giới thực sự lớn.

Câu hỏi của tôi là, tại sao chúng ta vẫn sử dụng dấu phẩy động nếu điểm cố định có lợi thế như vậy? Hầu hết các API kết xuất và thư viện vật lý sử dụng dấu phẩy động (và chịu những nhược điểm của nó, vì vậy các nhà phát triển cần phải khắc phục chúng).

Có phải họ chậm hơn rất nhiều?

Ngoài ra, làm thế nào để bạn nghĩ rằng động cơ hành tinh có thể mở rộng như ngoài hoặc vô cực xử lý quy mô lớn? Họ có sử dụng điểm cố định cho các vị trí hay họ có một số thuật toán phân chia không gian?


3
Bit "bổ sung" cuối cùng có lẽ nên là một câu hỏi riêng biệt để câu hỏi chính không bị bỏ qua.
Tetrad

Tôi muốn tìm cách buộc điểm cố định ... Trò chơi của tôi có tất cả các loại lỗi lạ vì Lua sử dụng FPU và các câu đố DirectX với FPU nữa ... Tôi đã thấy những thứ như 2 * 9000 = 17995 hoặc 500 * 10 = 4897 thật là ngớ ngẩn. Nhưng lỗi tồi tệ nhất có lẽ là lỗi được thảo luận trong các diễn đàn của Ogre3D, trong đó 1 + 5 = 4.
speeder

3
Không biện minh cho một bình luận; nhưng nếu bạn quyết định sử dụng Q-Floats điểm cố định ( en.wikipedia.org/wiki/Q_(number_format) ) là bạn của bạn; chúng rất nhanh và dễ thực hiện.
Jonathan Dickinson

Vì vậy, để tổng hợp, tôi có nên gắn bó với các dấu chấm động (nếu tôi đang làm việc trong Java hoặc Python)? - Gastón 26 phút trước
Gastón

Câu trả lời:


20

Nếu bạn cho phép tôi cắm không biết xấu hổ, tôi sẽ cho bạn một ví dụ từ một trò chơi thực sự tôi đang làm việc (liên kết video YouTube).

Trò chơi có một thế giới vô tận, được tạo theo thủ tục trên một động cơ vật lý. Nó sử dụng điểm nổi chính xác duy nhất. Sau vài trăm mét không gian trò chơi, các vấn đề chính xác bắt đầu nảy sinh (và càng ngày càng tệ hơn từ nguồn gốc bạn nhận được).

Giải pháp của tôi? Cứ sau 200m, tôi di chuyển toàn bộ thế giới trở lại 200m về phía gốc (nếu bạn quan tâm tìm và thử một trong các nguyên mẫu trên trang web của tôi và đưa lên lớp phủ gỡ lỗi [w] orld, bạn có thể thấy điều này xảy ra).

Tại sao không sử dụng điểm cố định? Hoặc chính xác gấp đôi? Thay vì chính xác đơn? Bởi vì mọi thứ khác đang sử dụng điểm nổi chính xác duy nhất!

Công cụ vật lý tôi đang sử dụng sử dụng nó, XNA sử dụng nó, dữ liệu được tải vào card đồ họa được định dạng là điểm nổi chính xác đơn. Ngay cả ngôn ngữ cũng được thiết kế để làm việc với các số dấu phẩy động - viết và (quan trọng hơn) việc đọc 0.5fdễ dàng hơn nhiều 0x80000000L.

Nó đơn giản chỉ là vấn đề dễ dàng hơn trong thực tế. Và người chiến thắng rõ ràng đang nhận thức được các vấn đề chính xác về dấu phẩy động và viết các hàm "di chuyển từ thế giới trở về không" khá đơn giản (hoặc thực hiện phân vùng không gian hoặc bất cứ điều gì phù hợp với trò chơi của bạn).

Và cuối cùng là một ví dụ khác - Quỹ đạo là trò chơi (mô phỏng, thực sự) thực sự cần quan tâm đến độ chính xác. Không chỉ trong không gian mà cả thời gian (gia tốc thời gian cộng với các vật thể quay quanh - bây giờ không muốn chúng rơi khỏi bầu trời). Nó cũng sử dụng số dấu phẩy động và sử dụng hack để duy trì sự ổn định.


Tôi luôn tự hỏi liệu một số ứng dụng có thể di chuyển mọi thứ khác dễ dàng hơn và giữ "trình phát" ở gốc. Thật thú vị khi thấy tôi không phải là người duy nhất!
dash-tom-bang

Tôi thích lý luận của bạn. Tôi chỉ muốn chỉ ra rằng khi nói đến các trò chơi liên quan đến điểm cố định mạng dường như có ít điểm kỳ quặc / sai lệch hơn (dự đoán của khách hàng chính xác hơn).
Jonathan Dickinson

Tôi không hiểu rõ lý lẽ của bạn. Và nhân tiện, tại sao ngôn ngữ chưa thực hiện điểm cố định? Tất nhiên đó dường như là một lý do được rút ra để sử dụng phao, nhưng điều đó không giải thích tại sao điểm cố định không được thực hiện ở mọi nơi.
jokoon

@jokoon Tôi nghĩ câu trả lời của tôi khá rõ ràng. Tại sao điểm cố định không được thực hiện ở mọi nơi? Chỉ cần nhìn vào Wikipedia: "Rất ít ngôn ngữ máy tính bao gồm hỗ trợ tích hợp cho các giá trị điểm cố định, bởi vì đối với hầu hết các ứng dụng, biểu diễn dấu phẩy động nhị phân hoặc thập phân thường đơn giản hơn để sử dụng và đủ chính xác ." Một nhà thiết kế giỏi biết những gì cần bỏ qua - và thứ gì đó sao chép chức năng theo cách giúp lập trình viên thực sự dễ dàng tự bắn vào chân mình là một ứng cử viên sáng giá.
Andrew Russell

Đã đồng ý. Các bộ xử lý ngày nay thực hiện các lệnh dấu phẩy động rất dễ dàng, các hướng dẫn có thông lượng tuyệt vời và hầu hết chỉ có một vài chu kỳ độ trễ dài hơn các hướng dẫn số nguyên.
doug65536

11

Đầu tiên - vâng, chúng nhanh hơn đáng kể. Ngay cả khi bạn có thể khiến điểm cố định hoạt động nhanh như một FPU "bình thường", điểm nổi thực sự có các hướng dẫn có lợi như fsel để ngừng phân nhánh hoặc SIMD để hoạt động trên nhiều phao cùng một lúc. GPU cũng sử dụng điểm nổi, ít nhất là trong các giao diện hướng tới người dùng của họ.

Thứ hai, 64 bit cũng giúp bạn đạt được khá nhiều điểm nổi - hầu hết mọi người vẫn sử dụng 32, nhưng lợi thế chính là nó có tỷ lệ. Đó là thang điểm cố định có độ chính xác cố định. Cho dù bạn đang đo mặt trời tới Sao Diêm Vương hay bên kia đường, bạn đều có cùng độ chính xác. Điểm nổi sẽ cho bạn kết quả chính xác hơn nhiều khi tất cả các giá trị liên quan đều nhỏ hơn. Vì các thư viện vật lý chung dự kiến ​​sẽ hoạt động ít nhất là rất nhiều với nhiều trò chơi ở các quy mô khác nhau - và một số trò chơi có thể có quy mô rất khác nhau - chúng cần sử dụng một loại số hoạt động ở nhiều quy mô.


5

Một điểm quan trọng khác cần làm là phao không quá chính xác như mọi người ở đây dường như nghĩ. Một float 32 bit có độ chính xác đầy đủ 24 bit. Điều này có nghĩa là ít nhất chính xác như giá trị điểm cố định 24 bit cho bất kỳ phạm vi nào. Trong khi các số float trở nên kém chính xác hơn, giá trị trở nên lớn hơn, một giá trị điểm cố định sẽ chỉ đơn giản là tràn và bao quanh tại một số điểm. Giảm độ chính xác là một dự phòng tốt hơn. Phao cũng có thể tràn, nhưng xa, rất xa. Tôi muốn nhìn thấy khuôn mặt của bạn khi thế giới của bạn đột nhiên bao quanh -2 ^ 31 do tràn điểm cố định.

Các giá trị dấu phẩy động 64 bit có độ chính xác nguyên là 53 bit, vì vậy chúng thực sự chính xác.


Các giá trị dấu phẩy động không thực sự tràn; nếu kết quả tính toán quá lớn không được biểu diễn thì kết quả là Vô cực dương hoặc âm.
Dứa

3

Trong ngữ cảnh FPS, các giá trị điểm cố định thực sự có thể là một trách nhiệm pháp lý. Gần điểm nổi là chính xác hơn. Nó chỉ là khoảng cách lớn hơn điểm cố định trở nên thích hợp hơn. Câu trả lời đơn giản là nó phụ thuộc vào bối cảnh.

Trong một cái gì đó giống như một thiên hà, bạn có thể sử dụng các khung tham chiếu. Sử dụng quy mô khổng lồ cho các hệ mặt trời và sau đó sử dụng trung tâm của Mặt trời (hoặc điểm tương tự) làm điểm xuất phát cho mọi thứ bên trong hệ thống. Sử dụng hệ thống này, bạn có thể có bánh của bạn và ăn nó, có thể nói, và nó không khó để hình dung.

IIRC, nhà phát triển trên Infinity nói rằng anh ta liên tục lặp lại các vấn đề quy mô trong một trong các cuộc phỏng vấn của mình.


Không chắc là trong bất kỳ trò chơi nào, bạn sẽ cần độ chính xác "gần bằng không" của điểm nổi. Nếu bạn có đơn vị một mét, độ chính xác 10 bit mang lại cho bạn độ chính xác dưới milimet và vẫn cho phép bạn mô hình hơn 4000km theo mỗi hướng nếu bạn bị mắc kẹt với các giá trị 32 bit. Nếu bạn cần độ chính xác cao hơn một milimet thì chắc chắn bạn có thể dịch chuyển thêm một vài bit. Di chuyển đến các giá trị 64 bit trong trò chơi không gian sẽ cung cấp cho bạn một hệ mặt trời (hoặc nhiều hơn?) Với độ chính xác không đổi trong toàn bộ âm lượng.
dash-tom-bang

Thật. Và đó là lý do tại sao bạn sử dụng Mặt trời của hệ mặt trời làm điểm tham chiếu trong một thế giới có kích thước thiên hà! Vấn đề là, phương pháp xử lý chính xác mà bạn đã chọn không mang lại điều gì cho bàn. Đó là tranh luận, vì vậy bạn cũng có thể sử dụng thư viện / phần cứng của bạn.
Rushyo

Tình cờ, tôi làm việc trong một trò chơi mà chúng tôi phải tạo mô hình hơn 4000km cho mỗi hướng. Để tương thích với mã trong các dự án khác, nó đã phải sử dụng 32 bit cho các vị trí. Đây không phải là một vấn đề lý thuyết, do các yêu cầu thương mại được đặt vào việc tái sử dụng mã và quy mô của thế giới trò chơi ngày nay.

1

Nếu bạn chưa làm, bạn chắc chắn nên xem hướng dẫn Kết xuất hành tinh trên GameDev.net. Đối với phân chia không gian, một giải pháp là giữ hai biến vị trí riêng biệt - một thang đo vĩ mô và một thang đo vi mô. Điều này hoạt động khá tốt (thử nghiệm).

Giải pháp chính xác phụ thuộc vào cách bạn lên kế hoạch xử lý khoảng cách cực xa trong động cơ - bạn có kế hoạch cổng nhảy hay nén thời gian không?


1

Một trong những lý do là số học dấu phẩy động là "đủ tốt" (hoặc ít nhất là như vậy), nó tạo ra kết quả khá chính xác một cách nhanh chóng.

Miễn là bạn nhận thức được các hạn chế của số học dấu phẩy động và thay đổi thuật toán của bạn để đối phó với chúng (xem câu trả lời của Andrew Russell) thì bạn sẽ tạo ra mã "hoạt động".


-1

Tôi đang viết một trò chơi. Trong trò chơi / chương trình của tôi, tôi vẽ một con tàu vũ trụ ở điểm gốc bằng một camera khá cố định và hành tinh của tôi tôi vẽ bằng một camera riêng. Và hai điều này giải quyết vấn đề cho tôi, nhưng hành tinh của tôi chưa thật chi tiết. Đối với giải pháp Andrew Russell đã đề cập về việc di chuyển thế giới (và tôi cho rằng máy ảnh và cư dân của nó quay trở lại nguồn gốc) Tôi thực sự sẽ không thử nếu bạn có kế hoạch biến trò chơi thành một trò chơi nối mạng. Nếu bạn di chuyển thế giới trên ứng dụng máy chủ dựa trên từng chuyển động của khách hàng thì thế giới cuối cùng sẽ phải vật lộn để giành lấy một vị trí. Và sẽ chiếm vị trí của nó mọi lúc từ mọi người đang chơi, đó sẽ là một trục trặc lớn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.