Nếu người dùng muốn "so sánh hai phao sử dụng một số tập hợp các điểm thập phân (con số đáng kể)" và điều này thực sự có nghĩa là chúng ta có một chức năng
AlmostEquals (14.3XXXXXXXX, 14.3YYYYYYY, 1) == true cho tất cả XXX và YYY có thể và thông số cuối cùng là vị trí thập phân sau dấu thập phân.
có một câu trả lời đơn giản nhưng không may:
KHÔNG thể lập trình chức năng này sẽ thực hiện hợp đồng này. Có thể lập trình một cái gì đó mà thường cho kết quả chính xác, nhưng bạn không thể thấy trước khi điều này xảy ra, vì vậy chức năng này là vô giá trị.
Các giải pháp đưa ra ở đây phá vỡ đã có AlmostEquals (0.06f, 0.14f, 1) = true nhưng 0! = 1.
Tại sao? Lý do đầu tiên là độ nhạy cực đoan. Ví dụ: 0.0999999999 .... và 0.100000 ... 1 có các chữ số khác nhau ở vị trí đầu tiên, nhưng chúng gần như không thể phân biệt được trong sự khác biệt, chúng hầu như giống hệt nhau. Bất kể chức năng thần thoại nào, nó không thể cho phép ngay cả những khác biệt nhỏ trong tính toán.
Lý do thứ hai là chúng tôi muốn thực sự tính toán với các con số. Tôi đã sử dụng VC 2008 với C# để in ra các giá trị chính xác của hàm Math.pow. Đầu tiên là tham số chính xác, giá trị hex thứ hai của phao thu được và giá trị thứ hai là giá trị thập phân chính xác là .
1 3dcccccd 0,100000001490116119384765625
2 3c23d70a 0,00999999977648258209228515625
3 3a83126f 0,001000000047497451305389404296875
4 38d1b717 0,0000999999974737875163555145263671875
5 3727c5ac 0.00000999999974737875163555145263671875
6 358637bd 9.999999974752427078783512115478515625E-7
Như bạn thấy, trình tự 0,1, 0,01, 0,001, vv tạo ra con số đó là xấp xỉ tuyệt vời, nhưng là một trong hai hơi quá nhỏ hoặc quá lớn.
Điều gì sẽ xảy ra nếu chúng tôi thực thi rằng địa điểm đã cho phải có chữ số chính xác? Cho phép liệt kê 16 giá trị nhị phân cho 4 bit
0.0
0.0625
0.125
0.1875
0.25
0.3125
0.375
0.4375
0.5
0.5625
0.625
0.6875
0.75
0.8125
0.875
0.9375
16 số nhị phân khác nhau nên có thể đủ cho 10 số thập phân, nếu chúng ta muốn tính chỉ với một nơi sau dấu thập phân. Trong khi 0,5 là chính xác bằng nhau, thực thi cùng một chữ số thập phân có nghĩa là 0,4 nhu cầu 0,4375 và 0,9 nhu cầu 0,99375, giới thiệu các lỗi nghiêm trọng.
Vi phạm điều kiện đầu tiên cực kỳ nhạy cảm có nghĩa là bạn không thể làm bất cứ điều gì hợp lý với những con số như vậy. Nếu bạn biết rằng vị trí thập phân của một số có giá trị nhất định, bạn sẽ không cần phải tính toán ở vị trí đầu tiên.
CáC# tài liệu C thậm chí trích dẫn một ví dụ: http://msdn.microsoft.com/en-us/library/75ks3aby.aspx
Thuyết Người gọi
Do mất độ chính xác có thể là kết quả của đại diện giá trị thập phân như số dấu chấm động hoặc thực hiện số học hoạt động trên các giá trị dấu phẩy động, trong một số trường hợp, phương thức Round (Double, Int32) có thể không xuất hiện để làm tròn giá trị trung điểm đến giá trị gần nhất ở các chữ số thập phân. Điều này được minh họa trong ví dụ sau , trong đó 2.135 được làm tròn thành 2,13 thay vì 2,14. Điều này xảy ra vì nội bộ phương pháp nhân giá trị bằng 10 chữ số và thao tác nhân trong trường hợp này bị mất chính xác .
Tôi sẽ viết một nhóm Kiểm tra đơn vị để kiểm tra xem thuật toán của bạn có phù hợp với nhu cầu của bạn hay không. –
Tôi thích tên phương thức này: ** AlmostEquals ** ... – gdoron
Tôi đã viết một số bài kiểm tra đơn vị và họ vượt qua với các giá trị mà tôi đã cung cấp, nhưng tôi muốn lời khuyên của khán giả hiểu sâu hơn về phao thực hiện/hành vi. – Kim