2012-01-22 41 views
6

Tôi đang cố gắng so sánh một mảng tăng gấp đôi với một vô hướng gấp đôi cho bình đẳng, nhưng bình đẳng không bao giờ được công nhận trong những trường hợp nhất định. Tôi nghi ngờ rằng điều này có liên quan đến cách nhân đôi được biểu diễn (ví dụ: 1.0 so với 1.00), nhưng tôi không thể hiểu được điều đó.matlab so sánh đôi

Ví dụ, tôi đã tạo ra một mảng gồm hàng ngàn các giá trị gấp đôi, vài cuối cùng trong đó có một số ngay lập tức trong thời gian được xác định bởi

10.6000 
-11.0000 
10.2000 
22.6000 
3.4000 

Nếu tôi thử nghiệm cho sự bình đẳng cho 10,2 (hoặc 10,2000) bởi lệnh array==10.2 (hoặc array=10.2000), tôi trả về một mảng 0s. Nếu tôi đặt các giá trị được hiển thị vào một mảng theo cách thủ công (ví dụ: array=[10.6000 -11.0000 10.2000 22.6000 3.4000]), thì lệnh thành công (tức là, array==10.2 trả về 0 0 1 0 0). Ai đó có thể vui lòng giải thích lý do tại sao bình đẳng thành công nếu tôi nhập các giá trị bằng tay, nhưng thất bại nếu mảng được tạo ra trong bối cảnh của một chương trình? Tôi có thể khắc phục lỗi so sánh bằng cách sử dụng gần đúng chứ không phải so sánh chính xác (ví dụ: (array<10.20001) & (array>10.19999)), nhưng điều này có vẻ không hài lòng.

Chỉnh sửa: Các giá trị trong mảng được tạo bằng phép cộng hoặc phép trừ lặp lại của số double không đổi (ví dụ: 0.2). Do đó, mô đun của mảng này theo số 0.2 nên ở mọi nơi bằng 0. Trong thực tế, các module của mỗi phần tử là tương đương với một trong hai 0 hoặc 0.2, như hình dưới đây cho chuỗi trên các số trong mảng:

mod(array,0.2) 
... 
0.2000 
    0 
0.2000 
0.2000 
    0 

lần nữa, nếu các giá trị được đặt trong một mảng bằng tay và các module được lấy, giá trị kỳ vọng của tất cả các 0 s được lấy.

Trả lời

6

Lý do là MATLAB cắt ngắn các số trong mảng để bảo toàn chỉ 4 chữ số sau dấu thập phân khi hiển thị. Nghĩa là, giá trị thực của mảng của bạn có thể là [10.600000000001, -10.99999999999, ...]. Bạn nói đúng, điều này là do biểu diễn nội bộ của các số dấu phẩy động trong máy tính, điều này có thể gây ra các lỗi nhỏ trong các tính toán.

Cá nhân tôi nghĩ có hai giải pháp, một giải pháp gần giống như bạn đã làm, còn cách khác là làm tròn mảng lên trước (ví dụ: this tool từ FileExchange) và sau đó thực hiện đối sánh chính xác.

+0

Rất hữu ích. Một câu hỏi tiếp theo là số của tôi được tạo ra bằng cách cộng hoặc trừ một số không đổi (ví dụ '0,2') qua nhiều chu kỳ trong một vòng lặp, do đó, các con số trong mảng phải bằng 0 khi modulo 0,2 (' mod (mảng) , 0,2) ') được áp dụng. Trong thực tế, họ không. Chúng bằng 0 hoặc 0,2. Tuy nhiên, khi tôi áp dụng modulo 0.2 cho bất kỳ số nào trong mảng bằng cách gõ chúng theo cách thủ công, giá trị kỳ vọng của 0 được cho. Bạn có thể giải thích hành vi này? Cảm ơn! – user001

+1

Điều này liên quan đến cách các số phảy động được thể hiện trong các máy tính. Một thực tế nổi tiếng là máy tính sử dụng nhị phân chứ không phải là số thập phân. Tuy nhiên, có một vấn đề xảy ra với nhị phân, tức là một phân số hữu hạn, nói 0,2 trong thập phân không thể được biểu diễn bằng các số hữu hạn trong nhị phân. Đó là, biểu diễn nhị phân của 0,2 trong máy tính thực sự là 0.001110011100111 ..., là vô tận. Tuy nhiên, MATLAB sử dụng 64 bit để biểu diễn một 'Single', có thể gây ra lỗi 2^(- 65). Lỗi này khá nhỏ, nhưng khi có khá nhiều lần lặp lại, nó có thể tích lũy. – grapeot

+0

Giải thích tuyệt vời. Cảm ơn bạn rất nhiều. – user001

2

Có thể có gì đó ở độ chính xác đơn lẻ ở đâu đó và tăng gấp đôi ở nơi khác. Biểu diễn nhị phân của ví dụ: 10,2 trong mỗi khác nhau khi chúng kết thúc sau một số bit khác nhau. Như vậy họ là khác nhau:

>> if (single(10.2) == 10.2) disp('honk'); end 
>> if (single(10.2) == single(10.2)) disp('honk'); end 
honk 

Bạn sẽ cần phải kiểm tra xem có sự bình đẳng trong một số khác biệt nhỏ:

eps = 0.001; 
result = abs(array-10.2) < eps; 

Bạn có thể tìm chính xác được sử dụng trong một mảng sử dụng whos:

>> whos A 
    Name  Size   Bytes Class  Attributes 

    A   1x2     8 single  
+0

Cảm ơn @Alex. Bạn có thể vui lòng xem bình luận của tôi dưới bài viết của grapeot. Nếu tôi lấy mảng của tôi, được tạo ra bởi một loạt phép cộng hoặc trừ 0,2 (gấp đôi) trong ngữ cảnh của một vòng lặp, thì modulo của mọi phần tử trong mảng là 0 hoặc 0,2, điều này không có nghĩa gì cả. Tôi đã kiểm tra độ chính xác của mảng bằng cách sử dụng lệnh 'whos' (cảm ơn), và nó gấp đôi, cũng như biến so sánh vô hướng của tôi. – user001

+1

0.2 không thể được biểu diễn chính xác như một phao nhị phân (xem http://www.h-schmidt.net/FloatApplet/IEEE754.html), nó là một phần tiếp tục 0.1001 [1001 ...]. Vì vậy, thêm 0,2 vào một cái gì đó có thể không làm chính xác những gì bạn nghĩ. Nếu tính chính xác là quan trọng, hãy làm việc trong các đơn vị tối thiểu của vấn đề của bạn, trong trường hợp này có lẽ là dễ nhất để làm việc ở mức 10x và thêm 2 vào số sau đó kiểm tra mod (num, 2), sau đó chia 10 ở cuối. – Alex

+0

Cảm ơn bạn rất nhiều. Vấn đề được giải quyết bằng cách cộng/trừ 0,25, và điều này có ý nghĩa bởi vì 0,25 có thể được biểu diễn chính xác như là một phao nhị phân theo applet bạn cung cấp. Tôi cho rằng nơi tốt nhất để tìm thêm thông tin sẽ là một bài viết về biểu diễn dấu phẩy động của các số. – user001

1

Tạo một tệp chức năng MATLAB sẽ chấp nhận một giá trị modulo (từ 3 đến 9; đó là Z3 đến Z9) và sẽ xuất ra giá trị ít nhất có thể được mô tả bởi các điều kiện modulo.

mẫu mô phỏng:

Z = [3 4 5]; % Modulo Z3, Z4 và Z5

r = [2 1 4]; % Còn lại Giá trị

Giá trị ít nhất có thể là 29.

Các đầu vào Z phải là một ma trận mảng ... nơi ở, bạn có thể gõ bất kỳ số 3-9 .... và bạn có thể gõ 3,4,5,6,7,8,9 trong bất kỳ thứ tự, trong bất kỳ cặp hoặc nhóm ...

các đầu vào r nên tương đương với số lượng đầu vào z quá ...

đầu ra sẽ mang lại giá trị ít nhất có thể mặc dù điều kiện modulo ...

Các vấn đề liên quan