Toán tử Boolean && và ||


252

Theo định nghĩa ngôn ngữ R , sự khác biệt giữa &&&(tương ứng |||) là cái trước được vector hóa trong khi cái sau thì không.

Theo văn bản trợ giúp , tôi đọc sự khác biệt gần giống với sự khác biệt giữa "Và" và "AndAlso" (tương ứng là "Hoặc" và "OrElse") ... Có nghĩa là: Không phải tất cả các đánh giá nếu chúng không phải là (tức là A hoặc B hoặc C luôn luôn đúng nếu A đúng, vì vậy hãy ngừng đánh giá nếu A đúng)

Ai đó có thể làm sáng tỏ ở đây? Ngoài ra, có AndAlso và OrElse trong R không?


Đồng thời xem các câu hỏi tương tự tại stackoverflow.com/q/6933598/210673stackoverflow.com/q/7953833/210673 (hiện đã đóng dưới dạng trùng lặp).
Aaron rời Stack Overflow

3
Tôi nghĩ && và || được triển khai kém trong R. Trong các ngôn ngữ khác, chúng là toán tử AND và OR có điều kiện, chúng thực hiện một phép toán boolean logic hoặc OR, nhưng chỉ đánh giá toán hạng thứ hai của nó nếu cần. Trong R không làm gì hữu ích.
skan

Câu trả lời:


340

Những cái ngắn hơn được vector hóa, có nghĩa là chúng có thể trả về một vectơ, như thế này:

((-2:2) >= 0) & ((-2:2) <= 0)
# [1] FALSE FALSE  TRUE FALSE FALSE

Biểu mẫu dài hơn đánh giá từ trái sang phải chỉ kiểm tra phần tử đầu tiên của mỗi vectơ, do đó, phần trên cho

((-2:2) >= 0) && ((-2:2) <= 0)
# [1] FALSE

Như trang trợ giúp nói, điều này làm cho dạng dài hơn "thích hợp cho luồng điều khiển lập trình và [được] thường được ưu tiên trong các mệnh đề."

Vì vậy, bạn muốn sử dụng các hình thức dài chỉ khi bạn chắc chắn các vectơ có độ dài một.

Bạn nên tuyệt đối chắc chắn các vectơ của bạn chỉ có độ dài 1, chẳng hạn như trong trường hợp chúng là các hàm chỉ trả về độ dài 1 booleans. Bạn muốn sử dụng các hình thức ngắn nếu các vectơ có thể dài> 1. Vì vậy, nếu bạn không hoàn toàn chắc chắn, bạn nên kiểm tra trước hoặc sử dụng biểu mẫu ngắn rồi sử dụng allanygiảm nó xuống độ dài để sử dụng trong các câu lệnh điều khiển, như if.

Các hàm allanythường được sử dụng trên kết quả của phép so sánh véc tơ để xem liệu tất cả hoặc bất kỳ phép so sánh nào là đúng, tương ứng. Các kết quả từ các hàm này chắc chắn có độ dài 1 vì vậy chúng phù hợp để sử dụng trong các mệnh đề, trong khi các kết quả từ so sánh véc tơ thì không. (Mặc dù những kết quả đó sẽ thích hợp để sử dụng trong ifelse.

Một điểm khác biệt cuối cùng: &&||chỉ đánh giá bao nhiêu thuật ngữ mà họ cần (dường như đó là ý nghĩa của ngắn mạch). Ví dụ: đây là một so sánh sử dụng một giá trị không xác định a; nếu nó không bị đoản mạch, vì &|không, nó sẽ báo lỗi.

a
# Error: object 'a' not found
TRUE || a
# [1] TRUE
FALSE && a
# [1] FALSE
TRUE | a
# Error: object 'a' not found
FALSE & a
# Error: object 'a' not found

Cuối cùng, xem phần 8.2.17 trong The R Inferno , có tiêu đề "and andand".


Tôi đang so sánh logic của độ dài 1. Tài liệu không rõ ràng về lý do tại sao nó được ưa thích cho luồng điều khiển. Có phải vì nó sử dụng "ngắn mạch" từ câu trả lời của @ Theo và do đó có hiệu suất tốt hơn?
SFun28

không Chỉ cần sử dụng mẫu ngắn '&' - các câu trả lời ngắn mạch là không chính xác.
M. Tibbits

1
Không, bởi vì nó đảm bảo chỉ có một câu trả lời TRUE / FALSE duy nhất. Các hình thức ngắn hơn có thể dẫn đến c(TRUE, FALSE), và iftuyên bố sẽ không rõ ràng. Nếu bạn chắc chắn mọi thứ đều có độ dài 1, thì có, hoặc là sẽ làm được, và bạn đã đúng rằng "ngắn mạch" là lý do để thích một cái. Mặc dù vậy, một lời cảnh báo, hãy chắc chắn rằng bạn chắc chắn 100% rằng chúng chỉ có thể dài một. Bạn có thể nhận được lỗi thực sự ngớ ngẩn khác.
Aaron rời Stack Overflow

9
@ SFun28: Có, ngắn mạch là lý do nó được ưa thích để kiểm soát dòng chảy. Cũng như hiệu suất tốt hơn, bạn có thể không muốn đánh giá tất cả các đối số. Ví dụ chính tắc được đưa ra ?is.Rđể kiểm tra xem bạn đang chạy R hay S-Plus. if(exists("is.R") && is.function(is.R) && is.R()). Nếu is.Rkhông tồn tại, thì bạn không muốn đánh giá is.function(is.R)vì nó sẽ gây ra lỗi. Tương tự như vậy nếu is.Rkhông phải là một chức năng, bạn không muốn gọi nó như thể nó là.
Richie Cotton

2
Trong phiên bản hiện tại của R địa ngục, phần có liên quan hiện là 8.2,17 "và andand"
Silverfish

34

Câu trả lời về "đoản mạch" có khả năng gây hiểu lầm, nhưng có một số sự thật (xem bên dưới). Trong ngôn ngữ R / S &&||chỉ đánh giá phần tử đầu tiên trong đối số đầu tiên. Tất cả các yếu tố khác trong một vectơ hoặc danh sách được bỏ qua bất kể giá trị đầu tiên. Những nhà điều hành được thiết kế để làm việc với if (cond) {} else{}xây dựng và kiểm soát chương trình trực tiếp chứ không phải là xây dựng vectơ mới .. Các &và các |nhà khai thác được thiết kế để làm việc trên vectơ, vì vậy họ sẽ được áp dụng "song song", có thể nói, dọc theo chiều dài của cuộc tranh luận dài nhất. Cả hai vectơ cần được đánh giá trước khi so sánh được thực hiện. Nếu các vectơ không có cùng độ dài, thì việc tái chế đối số ngắn hơn được thực hiện.

Khi các đối số đến &&hoặc ||được ước tính, sẽ có "đoản mạch" trong đó nếu bất kỳ giá trị nào liên tiếp từ trái sang phải là xác định, thì các đánh giá sẽ dừng lại và giá trị cuối cùng được trả về.

> if( print(1) ) {print(2)} else {print(3)}
[1] 1
[1] 2
> if(FALSE && print(1) ) {print(2)} else {print(3)} # `print(1)` not evaluated
[1] 3
> if(TRUE && print(1) ) {print(2)} else {print(3)}
[1] 1
[1] 2
> if(TRUE && !print(1) ) {print(2)} else {print(3)}
[1] 1
[1] 3
> if(FALSE && !print(1) ) {print(2)} else {print(3)}
[1] 3

Ưu điểm của ngắn mạch sẽ chỉ xuất hiện khi các đối số mất nhiều thời gian để đánh giá. Điều đó thường xảy ra khi các đối số là các hàm xử lý các đối tượng lớn hơn hoặc có các phép toán phức tạp hơn.


"Đoản mạch" là một thuật ngữ mới đối với tôi, nhưng dường như với tôi rằng câu trả lời mô tả nó đồng ý với những gì bạn nói &&||.
Aaron rời Stack Overflow

@DWin - trong trường hợp toán tử có độ dài 1 logic, chúng tương đương nhau phải không? Tôi đang cố gắng hiểu lý do tại sao chúng được ưa thích trong luồng điều khiển như các tài liệu trạng thái. Ngoài ra, R có cấu trúc "ngắn mạch" không?
SFun28

Chúng KHÔNG tương đương với các vectơ có độ dài> 1
M. Tibbits

2
Đúng là nếu các đối số &&là hàm và đối số thứ nhất là sai, thì đối số thứ hai sẽ không được đánh giá. Điều đó không đúng với một trong hai &hoặc ifelsesẽ đánh giá cả hai đối số.
IRTFM

Đó không phải là những gì câu trả lời của Theo về ngắn mạch nói sao?
Aaron rời Stack Overflow

25

&&||là những gì được gọi là "ngắn mạch". Điều đó có nghĩa là họ sẽ không đánh giá toán hạng thứ hai nếu toán hạng thứ nhất đủ để xác định giá trị của biểu thức.

Ví dụ: nếu toán hạng thứ nhất &&là sai thì không có điểm nào để đánh giá toán hạng thứ hai, vì nó không thể thay đổi giá trị của biểu thức ( false && truefalse && falsecả hai đều sai). Điều tương tự cũng xảy ra ||khi toán hạng đầu tiên là đúng.

Bạn có thể đọc thêm về điều này tại đây: http://en.wikipedia.org/wiki/Short-circuit_ev Assessment Từ bảng trên trang đó bạn có thể thấy nó &&tương đương với AndAlsoVB.NET, mà tôi giả sử bạn đang đề cập đến.


3
Điều này đủ để chứng minh rằng nó là ngắn mạch : f <- function() { print('hello'); TRUE }; FALSE && f(). Thay đổi &và nhận thấy rằng chức năng được đánh giá. QED.
Theo

2
Theo, vâng, bạn đúng đó &&||ngắn mạch. Nhưng đó thực sự là một điểm khá nhỏ khi so sánh giữa dạng ngắn và dạng dài; điều quan trọng hơn nhiều là phải hiểu những gì mỗi người làm khi đầu vào là vectơ.
Aaron rời Stack Overflow

2
@MTibbits Trên thực tế đây không phải là một câu trả lời hoàn chỉnh, nhưng tuyên bố về ngắn mạch là chính xác . Hãy thử F & {message("Boo!");T}F && {message("Boo!");T}.
mbq
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.