Các thư viện chuẩn C cung cấp round
, lround
và llround
gia đình của các chức năng trong C99. Tuy nhiên, các chức năng này không tuân thủ IEEE-754, bởi vì chúng không thực hiện "làm tròn ngân hàng" của một nửa đến thậm chí theo yêu cầu của IEEE ...
Nó không có ý nghĩa để nói về việc liệu hoặc không phải là một chức năng riêng lẻ là "tuân thủ IEEE-754". Việc tuân thủ IEEE-754 yêu cầu phải có một tập hợp các hoạt động loại dữ liệu với ngữ nghĩa xác định. Nó không yêu cầu các loại hoặc hoạt động đó có tên cụ thể, cũng không yêu cầu chỉ các hoạt động đó có sẵn. Việc triển khai có thể cung cấp bất kỳ chức năng bổ sung nào mà nó muốn và vẫn tuân thủ.Nếu thực hiện muốn cung cấp vòng-lẻ, tròn ngẫu nhiên, vòng-đi-từ-zero, và bẫy-nếu-inexact, nó có thể làm như vậy.
gì IEEE-754 thực sự đòi hỏi cho làm tròn là sáu hoạt động sau đây là cung cấp:
convertToIntegerTiesToEven (x)
convertToIntegerTowardZero (x)
convertToIntegerTowardPositive (x)
convertToIntegerTowardNegative (x)
convertToIntegerTiesToAway (x)
convertToIntegerExact (x)
Trong C và C++, cuối cùng năm người các hoạt động này chắc chắn sẽ số trunc
, ceil
, floor
, round
và rint
chức năng, tương ứng. C11 và C++ 14 không có ràng buộc cho lần đầu tiên, nhưng các bản sửa đổi trong tương lai sẽ sử dụng roundeven
. Như bạn thấy, round
thực sự là một trong những hoạt động cần thiết.
Tuy nhiên, roundeven
không có sẵn trong việc triển khai hiện nay, trong đó đưa chúng ta đến phần tiếp theo của câu hỏi của bạn:
Cách ad-hoc thường lệ để thực hiện làm tròn trong C là biểu hiện (int)(x + 0.5f)
đó, mặc dù là không chính xác trong toán học IEEE-754 nghiêm ngặt, thường được dịch bởi các trình biên dịch thành đúng hướng dẫn cvtss2si
. Tuy nhiên, điều này chắc chắn không phải là một giả định di động.
Các vấn đề với biểu thức đó mở rộng vượt xa "toán học IEEE-754 nghiêm ngặt". Nó hoàn toàn không chính xác cho tiêu cực x
, đưa ra câu trả lời sai cho nextDown(0.5)
và chuyển tất cả các số nguyên lẻ trong 2 ** 23 binade thành số nguyên chẵn. Bất kỳ trình biên dịch dịch nó thành cvtss2si
là khủng khiếp, khủng khiếp bị hỏng. Nếu bạn có một ví dụ về điều đó xảy ra, tôi rất thích nhìn thấy nó.
Làm cách nào tôi có thể triển khai một hàm sẽ làm tròn bất kỳ giá trị dấu phẩy động nào với ngữ nghĩa nửa đến thậm chí?
Như njuffa ghi nhận trong một chú thích, bạn có thể đảm bảo rằng các chế độ làm tròn mặc định được thiết lập và sử dụng rint
(hoặc lrint
, vì nó có vẻ như bạn thực sự muốn có một kết quả số nguyên), hoặc bạn có thể thực hiện riêng của bạn chức năng làm tròn bằng cách gọi round
và sau đó sửa các trường hợp nửa chừng như gnasher729 gợi ý. Sau khi kết nối n1778 cho C được chấp nhận, bạn sẽ có thể sử dụng các chức năng roundeven
hoặc fromfp
để thực hiện thao tác này mà không cần phải kiểm soát chế độ làm tròn.
Chúng tuân thủ tiêu chuẩn nhưng không thực hiện tất cả."Vòng tới gần nhất, quan hệ từ số không" là một trong các chế độ làm tròn IEEE-754. –
IEEE-754 lưu ý rằng chế độ làm tròn sách giáo khoa tồn tại, nhưng chỉ dành cho các số thập phân. 'Việc thực hiện tiêu chuẩn này sẽ cung cấp roundTiesToEven và ba tham số làm tròn các thuộc tính. Việc triển khai định dạng thập phân của tiêu chuẩn này sẽ cung cấp roundTiesToAway làm thuộc tính làm tròn hướng đến người dùng có thể chọn . Thuộc tính làm tròn roundTiesToAway không cần thiết cho việc triển khai định dạng nhị phân . ’Làm tròn các mối quan hệ đến thậm chí là chế độ di động (và hợp lý) duy nhất. – 68ejxfcj5669
Thay vì 'round()' nhìn vào 'rint()' được sử dụng với chế độ làm tròn mặc định là "tròn đến gần nhất hoặc thậm chí". – njuffa