2011-09-27 23 views
6

Tôi đang bối rối. Đây là testcase của tôi.khẳng định không thành công khi nó không nên, trong thử nghiệm đơn vị Smalltalk

theTestArray := #(1.2 3 5.1 7). 
self assert: theTestArray squareOfAllElements = #(1.44 9 26.01 49). 

Xác nhận không nên thất bại. Khi tính bình phương của mỗi phần tử là chính xác. Vì vậy, tôi đã "bước vào thử nghiệm", cho thấy rằng kết quả của phương thức squareOfAllElements và # (1.44 9 26.01 49) đều giống nhau nhưng khẳng định đánh giá sai. tại sao? Tôi làm gì sai ở đây? Bất kỳ trợ giúp được đánh giá cao.

Trả lời

8

Bạn đang xử lý các số dấu phẩy động ở đây. Số dấu chấm động không chính xác theo định nghĩa và bạn không bao giờ nên so sánh chúng bằng cách sử dụng # =.

Để biết chi tiết kiểm tra mục 1.1 của dự thảo chương về số điểm của Pharo nổi by Example: http://stephane.ducasse.free.fr/Web/Draft/Float.pdf

0

Tuy nhiên, thông điệp bình đẳng so sánh, # =, được gửi đến các bộ sưu tập có lẽ được trả về bởi #squareOfAllElements.

Bạn có thể viết lại tuyên bố thử nghiệm của bạn như:

theTestArray := #(1.2 3 5.1 7). 
theSquaredArray := theTestArray collect: [:each | each squared]. 
theTestArray with: theSquaredArray do: [:a :b | self assert: (a equals: b) ]. 

Điều đó sẽ kiểm tra giống như trước đó, nhưng sẽ chạy một #assert: mỗi phần tử.

Tùy chọn khác sẽ là triển khai biến thể của #hasEqualElements: dưới dạng Float >> # bằng: thay vì # =.

0

Như đã nói trong các câu trả lời khác, Float không chính xác. Ngoài ra hãy nhớ rằng Visualworks Float mặc định với độ chính xác đơn (khoảng 7 chữ số thập phân), nếu bạn đặt số float của bạn bằng chữ d, như 5.1d bạn sẽ nhận được độ chính xác gấp đôi (khoảng 15 chữ số thập phân), ít chính xác hơn, nhưng vẫn không chính xác.

Một nguồn gây nhầm lẫn bổ sung là hai Float khác nhau có thể in với cùng biểu diễn thập phân tương tự trong Visualworks.

5.1 squared printString 
-> '26.01' 

nhưng

5.1 squared = 26.01 
-> false 

Lưu ý rằng Squeak gần đây hoặc in Pharo vừa đủ số thập phân để phân biệt nổi khác nhau (và diễn giải chúng không thay đổi)

5.1 squared 
->26.009999999999998 

Ngoài ra, bạn có thể sử dụng cái gọi là FixedPoint (trong VisualWorks hoặc ScaledDecimals trong các hương vị khác) để thực hiện các hoạt động chính xác:

theTestArray := #(1.2s 3 5.1s 7). 
self assert: theTestArray squareOfAllElements = #(1.44s 9 26.01s 49). 

Cũng hãy cẩn thận với cái bẫy khác này: một FixedPoint (ScaledDecimals) chỉ in được nhiều số thập phân sau điểm thập phân như đã nói, nhưng bên trong nó có thể chứa nhiều (vô hạn nhiều).

5.1s1 squared printString 
-> '26.0s1' 

nhưng

5.1s1 squared = 26.01s2 
-> true