Vấn đề này không phải do chuyển đổi từ dài gấp đôi thành gấp đôi. Nó có thể là do thiếu chính xác trong thói quen sin
trong thư viện toán học.
Hướng dẫn fsin
được chỉ định để tạo kết quả trong vòng 1 ULP (ở định dạng kép dài) cho các toán hạng trong phạm vi của nó (theo Hướng dẫn của nhà phát triển phần mềm kiến trúc Intel 64 và IA-32, tháng 10 năm 2011, tập 1, 8.3.10), ở chế độ từ tròn đến gần nhất. Trên Intel Core i7, fsin
giá trị của người hỏi, −5.07121364272633190495298549649305641651153564453125 hoặc -0x1.448ec3aaa278dp + 2, tạo ra 0xe.fb206c69b0ba402p-4. Chúng ta có thể dễ dàng nhìn thấy từ hệ thập lục phân này mà 11 bit cuối cùng là 100 0000 0010. Đó là các bit sẽ được làm tròn khi chuyển đổi từ dài gấp đôi. Nếu chúng lớn hơn 100 0000 0000, số sẽ được làm tròn lên. Chúng lớn hơn. Do đó, kết quả của việc chuyển đổi giá trị gấp đôi này thành gấp đôi là 0xe.fb206c69b0ba8p-4, bằng 0x1.df640d8d36175p-1 và 0,93631021832247418590355891865328885614871978759765625. Cũng lưu ý rằng ngay cả khi kết quả là một ULP thấp hơn, 11 bit cuối cùng vẫn sẽ lớn hơn 100 0000 0000 và vẫn sẽ tròn lên. Do đó kết quả này không nên thay đổi trên CPU Intel phù hợp với tài liệu trên.
So sánh điều này để tính toán sin có độ chính xác gấp đôi, sử dụng quy trình sin
lý tưởng để tạo kết quả được làm tròn chính xác. Sin của giá trị là khoảng 0,93631021832247413051857150785044253634581268961333520518023697738674775240815140702992025520721336793516756640679315765619707343171517531053811196321335899848286682535203710849065933755262347468763562 (được tính bằng Maple 10). Đôi gần nhất với điều này là 0x1.df640d8d36175p-1. Đó là cùng một giá trị chúng tôi thu được bằng cách chuyển đổi kết quả fsin
thành gấp đôi.
Do đó, sự khác biệt không được gây ra bởi việc chuyển đổi dài gấp đôi thành gấp đôi; chuyển đổi kết quả dài gấp đôi fsin
thành gấp đôi tạo ra chính xác kết quả tương tự như lý tưởng chính xác gấp đôi chính xác sin
.
Chúng tôi không có đặc điểm kỹ thuật về độ chính xác của quy trình sin
được sử dụng bởi gói Visual Studio của người hỏi. Trong thư viện thương mại, cho phép lỗi của 1 ULP hoặc một số ULP là phổ biến. Quan sát cách đóng sine là một điểm mà giá trị chính xác kép được làm tròn: Nó là .498864 ULP (độ chính xác gấp đôi ULP) cách xa gấp đôi, do đó, nó là 0,001136 ULP cách xa điểm làm tròn thay đổi. Do đó, ngay cả một sự thiếu chính xác rất nhỏ trong quy trình sin
sẽ khiến nó trả về 0x1.df640d8d36174p-1 thay vì 0x1.df640d8d36175p-1 gần hơn.
Vì vậy, tôi phỏng đoán nguồn sai lệch là một sự thiếu chính xác rất nhỏ trong quy trình sin
.
Nguồn
2012-09-01 12:23:22
Một hoạt động có thể diễn ra hoàn toàn trong thanh ghi điểm động. Cái còn lại đòi hỏi sự mất chính xác khi thanh ghi 80 bit được ghi vào địa chỉ bộ nhớ 64 bit. Tài liệu FSTP nói rằng "khi lưu trữ giá trị trong bộ nhớ, giá trị được chuyển đổi thành định dạng đơn hoặc kép." –
Cách tiếp cận 'fsin' sử dụng FPU x87 với độ chính xác 80 bit, việc thực hiện' sin' trong MSVC (tôi đang sử dụng 2010) dường như sử dụng SSE với thanh ghi 128 x bit *. (Ngoài ra, hãy xem [câu hỏi này] (http://stackoverflow.com/questions/2284860/how-does-c-compute-sin-and-other-math-functions).) – DCoder