Từ ngôn ngữ tự nhiên đến biểu thức C ++


9

Bài tập:

Dịch các biểu thức ngôn ngữ tự nhiên sau đây sang các biểu thức C ++. Giả sử rằng tất cả các biến là số không âm hoặc boolean (có giá trị đúng hoặc sai).

Tiếng mẹ đẻ:

Cả a và b đều sai hoặc c đều đúng, nhưng không phải cả hai.

Giải pháp của tôi:

(a==0 && b==0)xor(c==1)

Giải pháp giáo sư:

(!a && !b) != c

Câu hỏi:

  1. Tôi nghĩ rằng tôi hơi hiểu khung đầu tiên, bằng cách nói "không-a" và "không-b" Tôi nghĩ rằng a và b sau đó phải sai, với điều kiện ab được coi là khác không ngay từ đầu. Đúng?

  2. Nhưng còn phần nói "không bằng c" thì sao?

  3. Tôi không hiểu giải pháp Giáo sư, có ai có thể chia sẻ nó cho tôi không?

Cảm ơn bạn vì sự giúp đỡ!


nói chung tôi sẽ cẩn thận với việc dịch các biểu thức boolean của ngôn ngữ nói sang mã. Một lỗi phổ biến là dịch "A bằng B hoặc C" sang a == b or cthay vì a == b or a ==c. Vấn đề là lanuage nói không chính xác và thực sự cả hai cách giải thích đều có thể hợp lệ
idclev 463035818

Câu trả lời:


5

Tôi sẽ cho rằng a, bcbool.

Hãy vẽ một số bảng sự thật:

| a | !a | a==1 | a==0 |
| 0 |  1 |   0  |   1  |
| 1 |  0 |   1  |   0  |

Như bạn thấy, aa==1là tương đương, và !aa==0cũng là tương đương, vì vậy chúng ta có thể viết lại (a==0 && b==0)xor(c==1)như(!a && !b) xor c .

Bây giờ một số bảng chân lý hơn:

| a | b | a xor b | a != b |
| 0 | 0 |    0    |    0   |
| 0 | 1 |    1    |    1   |
| 1 | 0 |    1    |    1   |
| 1 | 1 |    0    |    0   |

Vì thế a!=b tương đương với a xor b, vì vậy chúng ta có thể viết lại (!a && !b) xor cđể (!a && !b)!=c. Như bạn thấy, các giải pháp của bạn hoàn toàn tương đương, chỉ được viết với các 'dấu hiệu' khác nhau.


CẬP NHẬT : Quên đề cập đến. Có nhiều lý do tại sao giải pháp của giáo sư trông chính xác theo cách đó.

Giải pháp của giáo sư là thành ngữ hơn. Mặc dù giải pháp của bạn là chính xác về mặt kỹ thuật, đó không phải là mã C ++ thành ngữ.

Vấn đề nhỏ đầu tiên là việc sử dụng các loại. Giải pháp của bạn dựa trên chuyển đổi giữa intboolkhi bạn so sánh giá trị boolean với một số hoặc sử dụng xor, đó là một toán tử 'độc quyền bit-khôn ngoan' cũng hoạt động trên ints. Trong C ++ hiện đại, việc sử dụng các giá trị của các loại chính xác sẽ không được đánh giá cao và không phụ thuộc vào các chuyển đổi như vậy vì đôi khi chúng không quá rõ ràng và khó lý luận. Đối với boolcác giá trị như vậy là truefalsethay vì10tương ứng. Cũng !=thích hợp hơn xorvì trong khi về mặt kỹ thuậtbool được lưu trữ dưới dạng số, nhưng về mặt ngữ nghĩa, bạn không có bất kỳ số nào, chỉ là các giá trị logic.

Vấn đề thứ hai là về thành ngữ quá. Nó nằm ở đây : a == 0. Nó không được coi là một thực hành tốt để so sánh các biểu thức boolean với các hằng số boolean. Như bạn đã biết, a == truehoàn toàn tương đương với chỉ a, và a == falsechỉ!a hoặc not a(tôi thích cái sau). Để hiểu lý do tại sao việc so sánh không tốt chỉ cần so sánh hai đoạn mã và quyết định, điều này rõ ràng hơn:

if (str.empty() == false) { ... }

đấu với

if (not str.empty()) { ... }

1
Mặc dù về mặt kỹ thuật, câu trả lời này hoàn toàn tránh nói về các loại và C ++ thành ngữ, có lẽ là điểm chính của bài tập này.
Konrad Rudolph

@KonradRudolph, oh, vâng, tôi đã hoàn toàn quên đề cập đến điều đó. Có lẽ tôi sẽ chỉnh sửa câu trả lời của mình, cảm ơn
Yuri Kovalenko

3

Hãy suy nghĩ booleans, không phải bit

Tóm lại, giải pháp của giáo sư của bạn tốt hơn (nhưng vẫn sai, nói đúng ra, xem thêm) vì nó sử dụng toán tử boolean thay vì toán tử bitwise và coi booleans là số nguyên. Biểu thức c==1để biểu thị "c là đúng" là không chính xác bởi vì nếu c có thể là một số (theo sự phân công đã nêu) thì mọi giá trị khác không của c sẽ được coi là đại diệntrue .

Xem câu hỏi này về lý do tại sao không nên so sánh booleans với 0 hoặc 1, ngay cả khi an toàn để làm như vậy.

Một lý do rất tốt để không sử dụng xorlà đây là độc quyền hoặc hoạt động bit-khôn ngoan . Nó xảy ra để làm việc trong ví dụ của bạn bởi vì cả phía bên trái và bên phải là các biểu thức boolean chuyển đổi thành 1 hoặc 0 (xem lại 1 ).

Boolean độc quyền - hoặc trên thực tế !=.

Phá vỡ biểu thức

Để hiểu rõ hơn về giải pháp của giáo sư của bạn, dễ dàng nhất để thay thế các toán tử boolean bằng các mã tương đương "mã thông báo thay thế" của chúng, biến nó thành mã có thể chuyển đổi tốt hơn (imho) và mã C ++ hoàn toàn tương đương: Sử dụng 'không' cho '!' và 'và' cho '&&' bạn nhận được

    (not a and not b) != c

Thật không may, không có exclusive_ortoán tử logic nào khác not_eq, không hữu ích trong trường hợp này.

Nếu chúng ta phá vỡ biểu thức ngôn ngữ tự nhiên:

Cả a và b đều sai hoặc c đều đúng, nhưng không phải cả hai.

đầu tiên vào một câu về các mệnh đề boolean A và B:

Hoặc A hoặc B, nhưng không phải cả hai.

điều này chuyển thành A != B(chỉ dành cho booleans, không phải cho bất kỳ loại A và B).

Sau đó, mệnh đề A là

a và b đều sai

có thể được nêu là

a là sai và b là sai

dịch ra (not a and not b), và cuối cùng

c là đúng

Mà đơn giản là dịch thành c. Kết hợp chúng bạn lại nhận được (not a and not b) != c.

Để giải thích thêm về cách thức biểu hiện này hoạt động, tôi trì hoãn các bảng chân lý mà những người khác đã đưa ra trong câu trả lời của họ.

Cả hai bạn đều sai

Và nếu tôi có thể nitpick: Bài tập ban đầu nói rằng a, b và c có thể là các số không âm, nhưng không rõ ràng rằng nếu chúng là các số, chúng nên được giới hạn ở các giá trị 0 và 1. Nếu bất kỳ số nào là không phải là 0 đại diện true, theo thông lệ, thì đoạn mã sau sẽ mang lại một câu trả lời đáng ngạc nhiên :

    auto c = 2; // "true" in some way
    auto a = 0; // "false"
    auto b = 0; // "false"

    std::cout << ((!a && !b) != c);

// this will output: 1 (!)
// fix by making sure that != compares booleans:

    std::cout << ((!a && !b) != (bool)c);

Cũng hy vọng a, bcđược tuyên bố là bool, trong trường hợp c == 1này là chính xác , mặc dù mã tàn bạo. Dù sao, đây là câu trả lời tôi đã viết: mã của OP có thể tương đương với giáo sư, nhưng đó là C ++ xấu.
Konrad Rudolph

1
@KonradRudolph Từ văn bản chuyển nhượng của OP : variables are non-negative numbers or boolean. Vì vậy, +1 cho @dhavenith từ tôi vì đã nắm bắt được một chi tiết mà hầu hết những người khác ở đây đã bỏ lỡ (bao gồm cả tôi, ban đầu).
Frodyne

Tuyệt vời, Isee. Cảm ơn bạn! Nhưng sau đó bạn có thể giải thích cho tôi giải pháp của Giáo sư của tôi vì tôi không hiểu nó.
limonade

Tôi đã thêm một cách viết thay thế cho giải pháp của giáo sư của bạn. Điều này sẽ giúp làm rõ các biểu hiện. Để giải thích chi tiết hơn, tôi nghĩ các bảng sự thật trong câu trả lời của @YuriKovalenko là cách tốt nhất để tiếp cận biểu thức.
dithith

2

Tôi sẽ cố gắng giải thích với một số từ nữa: Các số có thể được chuyển đổi hoàn toàn thành các giá trị boolean:

Giá trị 0 (cho phép liệt kê tích phân, dấu phẩy động và không được lọc) và con trỏ null và các giá trị con trỏ thành viên null trở thành sai. Tất cả các giá trị khác trở thành sự thật.

Nguồn trên cppreference

Điều này dẫn đến các kết luận sau:

  • a == 0là giống như !a, bởi vì ađược chuyển đổi thành boolean và sau đó đảo ngược, bằng !(a != 0). Cũng vậy với b.

  • c==1sẽ chỉ trở thành đúng khi c bằng 1. Sử dụng chuyển đổi (bool)csẽ mang lại truekhi c != 0không chỉ là nếu c == 1. Vì vậy, nó có thể hoạt động, bởi vì người ta thường sử dụng giá trị 1 để biểu diễn true, nhưng nó không được kiểm soát.

  • a != blà giống như biểu thức boolean a xor bkhi abar. Điều đó đúng, khi giá trị này hay giá trị kia là đúng, nhưng không phải cả hai. Trong trường hợp này, phía bên trái (a==0 && b==0)là boolean, do đó phía bên phải ccũng được chuyển đổi thành boolean, do đó, cả hai bên được hiểu là biểu thức boolean, do đó, !=giống như xortrong trường hợp này.

Bạn có thể tự kiểm tra tất cả những điều này với các sự thật mà các câu trả lời khác đã cung cấp.


2

Như chúng ta có thể thấy từ các bảng sự thật:

  • !( not) và ==0đưa ra kết quả tương tự.
  • !=xorcho kết quả tương tự.
  • c==1 giống như chỉ c

Vì vậy, cái này nằm dưới cái kia, cho thấy tại sao 2 biểu thức này cho cùng một kết quả:

(a==0 && b==0) xor (c==1)
(!a   && !b)   !=   c

Bảng chân lý:

không phải

    |   | ! |
    | 0 | 1 |
    | 1 | 0 |

== 0

    |   |==0|
    | 0 | 1 |
    | 1 | 0 |

== 1

    |   |==1|
    | 0 | 0 |
    | 1 | 1 |

   | a | b | && |
   | 0 | 0 |  0 |
   | 0 | 1 |  0 |
   | 1 | 0 |  0 |
   | 1 | 1 |  1 |

Không công bằng

   | a | b | != |
   | 0 | 0 |  0 |
   | 0 | 1 |  1 |
   | 1 | 0 |  1 |
   | 1 | 1 |  0 |

XOR

   | a | b |xor|
   | 0 | 0 | 0 |
   | 0 | 1 | 1 |
   | 1 | 0 | 1 |
   | 1 | 1 | 0 |
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.