Làm thế nào để xác định một cách hợp lý


36

Gần đây, tôi đã gặp một vấn đề yêu cầu tôi xác định toán tử "HOẶC" hợp lý theo chương trình, nhưng không sử dụng chính toán tử.

Những gì tôi nghĩ ra là đây:

OR(arg1, arg2)
  if arg1 = True and arg2 = True
     return True

  else if arg1 = True and arg2 = False
     return True

  else if arg1 = False and arg2 = True
     return True

  else:
     return False

Là logic này đúng, hoặc tôi đã bỏ lỡ một cái gì đó?


10
@gnat: Công bằng mà nói, một bảng chân lý liệt kê các đầu ra cho mỗi kết hợp của các đầu vào và bài viết Wikipedia đưa ra mô tả về chức năng. Tôi nghĩ những gì OP thực sự yêu cầu là làm thế nào để xác định logic HOẶC lập trình mà không cần sử dụng toán tử.
Blrfl

6
@ user3687688 Bạn có thể vui lòng làm rõ các nguyên thủy chúng tôi được phép sử dụng không?
dòng chảy

4
câu hỏi này đã bắt đầu một cơn co thắt tối ưu hóa tập thể;)
Rob

8
Bạn có thể sử dụng toán tử ternaryreturn arg1 ? arg1 : arg2;
Matthew

4
Tôi phải biết lý do tại sao bạn cần xác định lại ortoán tử.
Kyle Strand

Câu trả lời:


102

Tôi muốn nói điều đó đúng, nhưng bạn có thể không cô đọng nó xuống một cái gì đó như thế này không?

or(arg1, arg2)
    if arg1 == true
        return true
    if arg2 == true
        return true

    return false

Vì bạn đang thực hiện hoặc so sánh, tôi không nghĩ bạn thực sự cần kiểm tra kết hợp. Nó chỉ quan trọng nếu một trong số chúng là đúng để trở về đúng. Nếu không, chúng tôi muốn trả lại sai.

Nếu bạn đang tìm kiếm một phiên bản ngắn hơn ít dài dòng hơn, thì điều này cũng sẽ hoạt động:

or(arg1, arg2)
    if arg1
        return arg1
    return arg2

6
Bạn cũng có thể xóa "khác" trên dòng 4 (chỉ để lại if arg2 == true).
Dawson Toth

1
@DawsonToth Có nhiều cách khác nhau để bạn có thể quay nó, tùy thuộc vào việc bạn muốn dài dòng hay cô đọng thực sự. Tôi sẽ hài lòng với người khác nếu nhưng có vẻ như đây là một câu hỏi mã giả vì vậy tôi có thể để nó như thế này cho rõ ràng. Mặc dù rất đúng!
Elliot Blackburn

@BlueHat Có vẻ hơi không nhất quán khi sử dụng một cái khác nếu, nhưng không phải là một cái khác ở cuối.
SBoss

1
@Mehrdad Cảm ơn! Tôi đã đưa câu trả lời cũ trở lại chỉ vì tôi cảm thấy nó dài dòng hơn một chút và giải thích giải pháp rõ ràng hơn một chút. Nhưng giải pháp của bạn nhỏ hơn nhiều và làm cùng một công việc.
Elliot Blackburn

1
thậm chí tốt hơn (tệ hơn):or(a, b): a ? a : b
sara

149

Đây là một giải pháp không có hoặc, và, không, so sánh và boolean nghĩa đen:

or(arg1, arg2)
  if arg1
    return arg1
  else
    return arg2

Nó có thể không nhận được nhiều cơ bản hơn thế;)


32
+1 cho câu trả lời ngắn hơn một chút so với của tôi. Tuy nhiên, tôi cũng muốn bỏ "cái khác" chỉ vì sự thanh lịch.
Elliot Blackburn

10
@BlueHat Nhưng sau đó, hai lợi nhuận sẽ được thụt lề khác nhau;)
fredoverflow 17/12/14

5
Tôi muốn nhận được EUR mỗi khi ai đó so sánh điều gì đó với truehoặc false.
JensG

1
@JensG Chà, bạn nghĩ thu nhập của Bill Gates đến từ đâu?
Kroltan 17/12/14

1
||Toán tử JavaScript một cách ngắn gọn (khi được triển khai bằng ngôn ngữ được gõ động).
tê giác

108

Một dòng mã:

return not (not arg1 and not arg2)

Không phân nhánh, không HOẶC.

Trong ngôn ngữ dựa trên C, nó sẽ là:

return !(!arg1 && !arg2);

Đây chỉ đơn giản là một ứng dụng của luật De Morgan :(A || B) == !(!A && !B)


6
Tôi nghĩ cách tiếp cận này là giải pháp tốt nhất vì (theo tôi) một if/elsecấu trúc giống như sử dụng OR, chỉ với một tên khác.
Nick

2
@Nick sử dụng iftương đương với bình đẳng. Thông thường trong mã máy, một số ifđược thực hiện dưới dạng số học, theo sau là so sánh với 0 với bước nhảy.


1
Tôi thích cách tiếp cận này vì nó ngắn mạch IFF andngắn mạch, do đó cung cấp sự thống nhất giữa các nhà khai thác.
Kyle Strand

1
@Snowman Đó là sự thật. Tôi có nghĩa là có if (a) return true; else if (b) return true;vẻ ít nhiều tương đương về mặt đạo đức if (a OR b) return true;, nhưng quan điểm đó có thể sẽ mở cho tranh chấp.
Nick

13

Nếu bạn chỉ có andnot, bạn có thể sử dụng luật của DeMorgan để lật lại and:

if not (arg1 = False and arg2 = False)
  return True
else
  return False

... hoặc (thậm chí đơn giản hơn)

if arg1 = False and arg2 = False
  return false
else
  return true

...

Và vì tất cả chúng ta rõ ràng đã trở nên cố định trong việc tối ưu hóa một cái gì đó hầu như luôn có sẵn như một hướng dẫn máy móc, điều đó có nghĩa là:

return not(not arg1 and not arg2)

return arg1 ? true : arg2

v.v ... v.v.

Vì hầu hết các ngôn ngữ cung cấp một điều kiện - và, tỷ lệ cược là toán tử "và" ngụ ý một nhánh.

...

Nếu tất cả những gì bạn có là nand(xem wikipedia ):

return nand (nand (arg1, arg1), nand (arg2, arg2))


7
Đơn giản hóa:return not (not arg1 and not arg2)

@Snowman bạn thực sự nên làm cho câu trả lời để tôi có thể nâng cao nó. Bạn (hiện tại) là người duy nhất ở đây không đi phân nhánh.
Lawtonfogle

4
Sẽ thêm giải pháp NAND, nhưng bạn đánh bại tôi với nó. Tất cả mọi thứ nên được thực hiện trong điều khoản của NAND.
Andy

2
@Andy: Trên thực tế, mọi thứ nên được định nghĩa theo thuật ngữ của NOR. ;-)
Pieter Geerkens

1
Làm việc tốt với các nandgiải pháp tinh khiết .
AAT

13

Hàm (ECMAScript)

Tất cả bạn cần là định nghĩa chức năng và các cuộc gọi chức năng. Bạn không cần bất kỳ chức năng phân nhánh, điều kiện, toán tử hoặc hàm dựng sẵn. Tôi sẽ chứng minh việc thực hiện bằng ECMAScript.

Đầu tiên, hãy xác định hai hàm được gọi truefalse. Chúng ta có thể định nghĩa chúng theo bất kỳ cách nào chúng ta muốn, chúng hoàn toàn tùy ý, nhưng chúng ta sẽ định nghĩa chúng theo một cách rất đặc biệt có một số lợi thế như chúng ta sẽ thấy sau:

const tru = (thn, _  ) => thn,
      fls = (_  , els) => els;

trulà một hàm có hai tham số đơn giản bỏ qua đối số thứ hai và trả về tham số thứ nhất. flscũng là một hàm có hai tham số đơn giản bỏ qua đối số thứ nhất và trả về tham số thứ hai.

Tại sao chúng ta mã hóa truflstheo cách này? Vâng, theo cách này, hai hàm không chỉ đại diện cho hai khái niệm truefalse, không, đồng thời, chúng còn đại diện cho khái niệm "sự lựa chọn", nói cách khác, chúng cũng là một if/ then/ elsebiểu thức! Chúng tôi đánh giá ifđiều kiện và truyền cho nó thenkhối và elsekhối làm đối số. Nếu điều kiện ước tính tru, nó sẽ trả về thenkhối, nếu nó ước lượng fls, nó sẽ trả về elsekhối. Đây là một ví dụ:

tru(23, 42);
// => 23

Điều này trả về 23, và điều này:

fls(23, 42);
// => 42

trả lại 42, như bạn mong đợi

Có một nếp nhăn, tuy nhiên:

tru(console.log("then branch"), console.log("else branch"));
// then branch
// else branch

Điều này in cả then branchelse branch! Tại sao?

Chà, nó trả về giá trị trả về của đối số đầu tiên, nhưng nó đánh giá cả hai đối số, vì ECMAScript rất nghiêm ngặt và luôn đánh giá tất cả các đối số cho một hàm trước khi gọi hàm. IOW: nó đánh giá đối số đầu tiên console.log("then branch"), đơn giản là trả về undefinedvà có tác dụng phụ của việc in then branchra bàn điều khiển, nó đánh giá đối số thứ hai, cũng trả về undefinedvà in ra bàn điều khiển như một hiệu ứng phụ. Sau đó, nó trả về đầu tiên undefined.

Trong calcul-compus, nơi mã hóa này được phát minh, đó không phải là vấn đề:-compus là thuần túy , có nghĩa là nó không có bất kỳ tác dụng phụ nào; do đó, bạn sẽ không bao giờ nhận thấy rằng đối số thứ hai cũng được đánh giá. Thêm vào đó,-compus là lười biếng (hoặc ít nhất, nó thường được đánh giá theo thứ tự thông thường), có nghĩa là, nó không thực sự đánh giá các đối số không cần thiết. Vì vậy, IOW: trong-tính toán, đối số thứ hai sẽ không bao giờ được đánh giá, và nếu có, chúng tôi sẽ không chú ý.

ECMAScript, tuy nhiên, là nghiêm ngặt , tức là nó luôn đánh giá tất cả các đối số. Vâng, trên thực tế, không phải lúc nào: sự if/ then/ else, ví dụ, chỉ đánh giá các thenchi nhánh nếu điều kiện là truevà chỉ đánh giá các elsechi nhánh nếu điều kiện là false. Và chúng tôi muốn nhân rộng hành vi này với iff. Rất may, mặc dù ECMAScript không lười biếng, nhưng có một cách để trì hoãn việc đánh giá một đoạn mã, giống như hầu hết mọi ngôn ngữ khác: bọc nó trong một hàm và nếu bạn không bao giờ gọi hàm đó, mã sẽ không bao giờ được thực hiện.

Vì vậy, chúng tôi bọc cả hai khối trong một hàm và cuối cùng gọi hàm được trả về:

tru(() => console.log("then branch"), () => console.log("else branch"))();
// then branch

in then branch

fls(() => console.log("then branch"), () => console.log("else branch"))();
// else branch

in else branch.

Chúng ta có thể thực hiện truyền thống if/ then/ elsetheo cách này:

const iff = (cnd, thn, els) => cnd(thn, els);

iff(tru, 23, 42);
// => 23

iff(fls, 23, 42);
// => 42

Một lần nữa, chúng ta cần một số gói chức năng bổ sung khi gọi iffhàm và hàm bổ sung gọi dấu ngoặc đơn trong định nghĩa của iff, với cùng lý do như trên:

const iff = (cnd, thn, els) => cnd(thn, els)();

iff(tru, () => console.log("then branch"), () => console.log("else branch"));
// then branch

iff(fls, () => console.log("then branch"), () => console.log("else branch"));
// else branch

Bây giờ chúng ta có hai định nghĩa đó, chúng ta có thể thực hiện or. Đầu tiên, chúng ta nhìn vào bảng chân lý cho or: nếu toán hạng đầu tiên là trung thực, thì kết quả của biểu thức giống như toán hạng đầu tiên. Mặt khác, kết quả của biểu thức là kết quả của toán hạng thứ hai. Tóm lại: nếu toán hạng thứ nhất là true, chúng ta trả về toán hạng thứ nhất, nếu không chúng ta trả về toán hạng thứ hai:

const orr = (a, b) => iff(a, () => a, () => b);

Hãy kiểm tra xem nó hoạt động:

orr(tru,tru);
// => tru(thn, _) {}

orr(tru,fls);
// => tru(thn, _) {}

orr(fls,tru);
// => tru(thn, _) {}

orr(fls,fls);
// => fls(_, els) {}

Tuyệt quá! Tuy nhiên, định nghĩa đó có vẻ hơi xấu xí. Hãy nhớ, truflsđã hành động như một điều kiện một mình, vì vậy thực sự không cần thiết iff, và do đó tất cả các chức năng đó bao gồm tất cả:

const orr = (a, b) => a(a, b);

Ở đó bạn có nó: or(cộng với các toán tử boolean khác) được định nghĩa không có gì ngoài các định nghĩa hàm và các hàm gọi chỉ trong một số dòng:

const tru = (thn, _  ) => thn,
      fls = (_  , els) => els,
      orr = (a  , b  ) => a(a, b),
      nnd = (a  , b  ) => a(b, a),
      ntt = a          => a(fls, tru),
      xor = (a  , b  ) => a(ntt(b), b),
      iff = (cnd, thn, els) => cnd(thn, els)();

Thật không may, việc triển khai này khá vô dụng: không có hàm hoặc toán tử nào trong ECMAScript trả về truhoặc fls, tất cả chúng đều trả về truehoặc false, vì vậy chúng ta không thể sử dụng chúng với các hàm của mình. Nhưng vẫn còn rất nhiều điều chúng ta có thể làm. Ví dụ: đây là một triển khai danh sách liên kết đơn:

const cons = (hd, tl) => which => which(hd, tl),
      car  = l => l(tru),
      cdr  = l => l(fls);

Đối tượng (Scala)

Bạn có thể nhận thấy một cái gì đó đặc biệt: truflsđóng một vai trò kép, chúng hoạt động cả hai như là các giá trị dữ liệu truefalse, nhưng đồng thời, họ cũng đóng vai trò như một biểu thức điều kiện. Chúng là dữ liệuhành vi , được kết hợp thành một đối tượng "điều" hay khác (tôi dám nói) !

Thật vậy, truflslà đối tượng. Và, nếu bạn đã từng sử dụng Smalltalk, Self, Drameak hoặc các ngôn ngữ hướng đối tượng khác, bạn sẽ nhận thấy rằng chúng thực hiện booleans theo cùng một cách chính xác. Tôi sẽ chứng minh một triển khai như vậy ở đây trong Scala:

sealed abstract trait Buul {
  def apply[T, U <: T, V <: T](thn: ⇒ U)(els: ⇒ V): T
  def &&&(other:Buul): Buul
  def |||(other:Buul): Buul
  def ntt: Buul
}

case object Tru extends Buul {
  override def apply[T, U <: T, V <: T](thn: ⇒ U)(els: ⇒ V): U = thn
  override def &&&(other:Buul) = other
  override def |||(other:Buul): this.type = this
  override def ntt = Fls
}

case object Fls extends Buul {
  override def apply[T, U <: T, V <: T](thn: ⇒ U)(els: ⇒ V): V = els
  override def &&&(other:Buul): this.type = this
  override def |||(other:Buul) = other
  override def ntt = Tru
}

object BuulExtension {
  import scala.language.implicitConversions
  implicit def boolean2Buul(b:Boolean) = if (b) Tru else Fls
}

import BuulExtension._

(2 < 3) { println("2 is less than 3") } { println("2 is greater than 3") }
// 2 is less than 3

BTW này là lý do tại sao Công cụ tái cấu trúc đa hình thay thế luôn hoạt động: bạn luôn có thể thay thế bất kỳ và mọi điều kiện trong chương trình của bạn bằng việc gửi tin nhắn đa hình, bởi vì như chúng tôi vừa trình bày, việc gửi tin nhắn đa hình có thể thay thế điều kiện bằng cách đơn giản thực hiện chúng. Các ngôn ngữ như Smalltalk, Self và Drameak là bằng chứng tồn tại cho điều đó, bởi vì những ngôn ngữ đó thậm chí không có điều kiện. (Họ cũng không có các vòng lặp, BTW hoặc thực sự là bất kỳ loại cấu trúc điều khiển tích hợp ngôn ngữ nào ngoại trừ việc gửi tin nhắn đa hình hay còn gọi là phương thức ảo.)


Kết hợp mẫu (Haskell)

Bạn cũng có thể xác định orbằng cách sử dụng khớp mẫu hoặc một cái gì đó như định nghĩa hàm một phần của Haskell:

True ||| _ = True
_    ||| b = b

Tất nhiên, khớp mẫu là một hình thức thực hiện có điều kiện, nhưng sau đó, một lần nữa, việc gửi thông điệp hướng đối tượng cũng vậy.


2
Làm thế nào về False ||| False = False_ ||| _ = Truethay vào đó? :)
dòng chảy

3
@FredOverflow: Điều đó đòi hỏi phải luôn luôn đánh giá toán hạng đúng. Thông thường các toán tử Boolean được dự kiến ​​là không nghiêm ngặt trong đối số đúng của họ hay còn gọi là "ngắn mạch".
Jörg W Mittag

À, tất nhiên rồi. Tôi biết rằng phải có một lý do sâu sắc hơn :)
dòng chảy

Phần đầu tiên làm tôi nhớ ngay đến loạt tuyệt vời của Eric Lippert về phong cách tiếp tục vượt qua . Hoàn toàn ngẫu nhiên nhưng vẫn vui vẻ :)
Voo

1
Định nghĩa của @ JörgWMittag FredOverflow là ngắn mạch thích hợp. Hãy thử True ||| undefinedmình trong ghci để xem!
Daniel Wagner

3

Đây là một cách khác để định nghĩa OR, hoặc thực sự là bất kỳ toán tử logic nào, sử dụng cách định nghĩa truyền thống nhất: sử dụng bảng chân lý.

Tất nhiên điều này khá đơn giản để thực hiện bằng các ngôn ngữ cấp cao hơn như Javascript hoặc Perl nhưng tôi đang viết ví dụ này bằng C để cho thấy rằng kỹ thuật này không phụ thuộc vào các tính năng ngôn ngữ cấp cao:

#include <stdio.h>

int main (void) {
    // Define truth table for OR:
    int OR[2][2] = {
        {0,   // false, false
         1},  // false, true
        {1,   // true, false
         1}   // true, true
    }

    // Let's test the definition
    printf("false || false = %d\n",OR[1==2]['b'=='a']);
    printf("true || false = %d\n",OR[10==10]['b'=='a']);

    // Usage:
    if (OR[ 1==2 ][ 3==4 ]) {
        printf("at least one is true\n");
    }
    else {
        printf("both are false\n");
    }
}

Bạn có thể làm tương tự với AND, NOR, NAND, NOT và XOR. Mã này đủ sạch để trông giống như cú pháp để bạn có thể làm những thứ như thế này:

if (OR[ a ][ AND[ b ][ c ] ]) { /* ... */ }

Tôi nghĩ rằng đây là cách tiếp cận "tinh khiết nhất" theo nghĩa toán học nhất định. Toán tử OR là một hàm sau tất cả, và bảng chân lý thực sự là bản chất của hàm đó như là một quan hệ và một tập hợp. Tất nhiên điều này cũng có thể được viết theo cách OO thú vị:BinaryOperator or = new TruthTableBasedBinaryOperator(new TruthTable(false, true, true, true));
ĐẾN TỪ

3

Một cách khác để biểu thị các toán tử logic dưới dạng biểu thức số học số nguyên (khi khả thi). Cách này có thể tránh được nhiều nhánh cho biểu thức lớn hơn của nhiều vị từ ..

Đặt True là 1 Đặt sai là 0

nếu tổng của cả hai lớn hơn 1 thì trả về đúng hay sai.

boolean isOR(boolean arg1, boolean arg2){

   int L = arg1 ? 1 : 0;
   int R = arg2 ? 1 : 0;

   return (L+R) > 0;

}

6
booleanExpression ? true : falselà tầm thường bằng booleanExpression.
Keen

Tôi thích phương pháp của bạn nhưng một lỗi đơn giản là tổng của cả hai đối số phải lớn hơn ZERO là đúng, không lớn hơn MỘT.
16/12/14

1
return (arga+argb)>0
17/12/14

1
Tôi chỉ sửa văn bản của bạn. Mã của bạn là hoàn hảo, nhưng có thể nằm trong một dòng: return (((arg1 ? 1 : 0)+(arg2 ? 1 : 0)) > 0); :)
17/12/14

1
@SenthuSivasambu Tôi không phản đối việc bạn sử dụng arg1 ? 1 : 0;. Đó là những biểu thức đáng tin cậy để chuyển đổi Boolean thành một số. Đó chỉ là tuyên bố trở lại có thể được tái cấu trúc tầm thường.
Keen

1

Hai hình thức:

OR(arg1, arg2)
  if arg1
     return True
  else:
     return arg2

HOẶC LÀ

OR(arg1, arg2)
  if arg1
     return arg1
  else:
     return arg2

Có lợi thế giống như mã golf nhỏ hơn một chút so với các đề xuất khác cho đến nay, một nhánh ít hơn. Thậm chí đó không phải là một lựa chọn vi mô ngớ ngẩn để giảm số lượng chi nhánh nếu chúng ta đang xem xét việc tạo ra một nguyên thủy do đó sẽ được sử dụng rất nhiều.

Định nghĩa của Javascript ||gần giống với điều này, kết hợp với việc gõ lỏng có nghĩa là biểu thức false || "abc"có giá trị "abc"42 || "abc"có giá trị 42.

Mặc dù nếu bạn đã có các toán tử logic khác thì việc thích nand(not(arg1), not(arg2))có thể có lợi thế là không có nhánh nào cả.


điểm lặp lại câu trả lời trước ( như bạn đã thừa nhận ) là gì?
gnat

@gnat nó đủ gần mà tôi sẽ không thấy phiền nếu tôi thấy câu trả lời đó, nhưng nó vẫn có một cái gì đó mà nó không tìm thấy ở bất kỳ ai trong số họ, vì vậy tôi sẽ bỏ nó.
Jon Hanna

@gnat, thực sự xem xét "Chúng tôi đang tìm kiếm câu trả lời dài cung cấp một số giải thích và bối cảnh." Tôi hạnh phúc hơn với câu trả lời này ngay bây giờ.
Jon Hanna

1

Ngoài tất cả các giải pháp được lập trình bằng cách sử dụng cấu trúc if, có thể xây dựng cổng OR bằng cách kết hợp ba cổng NAND. Nếu bạn muốn xem nó được thực hiện như thế nào trong wikipedia, bấm vào đây .

Từ đây, biểu thức,

KHÔNG [KHÔNG (A VÀ A) VÀ KHÔNG (B VÀ B)]

trong đó sử dụng KHÔNG và AND cho câu trả lời giống như OR. Lưu ý rằng việc sử dụng cả KHÔNG và AND chỉ là một cách khó hiểu để thể hiện NAND.


KHÔNG (A VÀ A) == KHÔNG (A)?
Charlie

Đúng chính xác. Trong cùng một bài viết trên wikipedia, bạn có thể thấy cách họ giảm một cổng KHÔNG thành cổng NAND. Tương tự cho một cổng AND. Tôi đã chọn không chỉnh sửa công thức họ đã trình bày cho cổng OR.
Walter Mitty

1

Tất cả các câu trả lời tốt đã được đưa ra. Nhưng tôi sẽ không để điều đó ngăn cản tôi.

// This will break when the arguments are additive inverses.
// It is "cleverness" like this that's behind all the most amazing program errors.
or(arg1, arg2)
    return arg1 + arg2
    // Or if you need explicit conversions:
    // return (bool)((short)arg1 + (short)arg2)

Cách khác:

// Since `0 > -1`, negative numbers will cause weirdness.
or(arg1, arg2)
    return max(arg1, arg2)

Tôi hy vọng không ai sẽ thực sự sử dụng các phương pháp như thế này. Họ ở đây chỉ để thúc đẩy nhận thức về các lựa chọn thay thế.

Cập nhật:

Vì các số âm có thể phá vỡ cả hai cách tiếp cận trên, đây là một gợi ý khủng khiếp khác:

or(arg1, arg2)
    return !(!arg1 * !arg2)

Điều này chỉ đơn giản là sử dụng Luật của DeMorgan và lạm dụng thực tế *tương tự như &&khi truefalseđược đối xử như thế nào 10tương ứng. (Đợi đã, bạn đang nói đây không phải là mã golf?)

Đây là một câu trả lời đúng:

or(arg1, arg2)
    return arg1 ? arg1 : arg2

Nhưng về cơ bản là giống hệt với các câu trả lời khác đã được đưa ra.


3
Những cách tiếp cận này về cơ bản là thiếu sót. Xem xét -1 + 1 cho arg1+arg2, -1 và 0 cho max(arg1,arg2), v.v.
fluffy

@fluffy Cách tiếp cận này giả định các đối số Boolean, và sau đó nó chỉ xảy ra để hoạt động chính xác với hầu hết các loại đầu vào rác. Tốt cho bạn để chỉ ra rằng vẫn còn một số rác thải gây ra vấn đề. Loại điều này chính xác là lý do tại sao chúng ta nên tìm cách mô hình hóa miền vấn đề thực tế một cách trực tiếp nhất có thể (và tránh bị cuốn theo sự thông minh của chính chúng ta) trong thực tế.
Keen

Nếu bạn đang thực hiện các giá trị boolean 1 bit thuần túy, thì bổ sung vẫn không hoạt động, vì 1 + 1 = 0. :)
fluffy

@fluffy Đó là nơi chuyển đổi rõ ràng đến. Việc chúng có cần hay không phụ thuộc vào chi tiết triển khai (đó chính xác là lý do tại sao đây là một ý tưởng ngớ ngẩn).
Keen

0

Một cách để xác định orlà thông qua bảng tra cứu. Chúng ta có thể làm rõ điều này:

bool Or( bool a, bool b } {
  bool retval[] = {b,true}; // or {b,a};
  return retval[a];
}

chúng ta tạo một mảng với các giá trị mà giá trị trả về nên có tùy thuộc vào giá trị nào a. Sau đó, chúng tôi làm một tra cứu. Trong C ++ như ngôn ngữ, boolthúc đẩy đến một giá trị có thể được sử dụng như một chỉ số mảng, với trueviệc 1falsetrở 0.

Sau đó chúng ta có thể mở rộng điều này sang các hoạt động logic khác:

bool And( bool a, bool b } {
  bool retval[] = {false,b}; // or {a,b};
  return retval[a];
}
bool Xor( bool a, bool b } {
  bool retval[] = {b,!b};
  return retval[a];
}

Bây giờ một nhược điểm của tất cả những điều này là nó yêu cầu ký hiệu tiền tố.

namespace operators {
  namespace details {
    template<class T> struct is_operator {};
    template<class Lhs, Op> struct half_expression { Lhs&& lhs; };
    template<class Lhs, class Op>
    half_expression< Lhs, Op > operator*( Lhs&&lhs, is_operator<Op> ) {
      return {std::forward<Lhs>(lhs)};
    }
    template<class Lhs, class Op, class Rhs>
    auto operator*( half_expression<Lhs, Op>&& lhs, Rhs&& rhs ) {
    return invoke( std::forward<Lhs>(lhs.lhs), Op{}, std::forward<Rhs>(rhs) );
    }
  }
  using details::is_operator;
}

struct or_tag {};
static const operators::is_operator<or_tag> OR;

bool invoke( bool a, or_tag, bool b ) {
  bool retval[] = {b,true};
  return retval[a];
}

và bây giờ bạn có thể gõ true *OR* falsevà nó hoạt động.

Kỹ thuật trên yêu cầu một ngôn ngữ hỗ trợ tra cứu phụ thuộc đối số và các mẫu. Bạn có thể có thể làm điều đó bằng một ngôn ngữ với thuốc generic và ADL.

Bên cạnh, bạn có thể mở rộng *OR*ở trên để làm việc với các bộ. Chỉ cần tạo một hàm miễn phí invoketrong cùng một không gian tên như or_tag:

template<class...Ts>
std::set<Ts...> invoke( std::set<Ts...> lhs, or_tag, std::set<Ts...> const& rhs ) {
  lhs.insert( rhs.begin(), rhs.end() );
  return lhs;
}

và bây giờ set *OR* settrả lại sự kết hợp của hai.


0

Điều này nhớ cho tôi các chức năng charasteristic:

or(a, b)
    return a + b - a*b

Điều này chỉ áp dụng cho các ngôn ngữ có thể coi booleans là (1, 0). Không áp dụng cho Smalltalk hoặc Python vì boolean là một lớp. Trong smalltalk họ còn đi xa hơn (điều này sẽ được viết bằng mã giả):

False::or(a)
    return a

True::or(a)
    return self

Và các phương thức kép tồn tại cho và:

False::and(a)
    return self

True::and(a)
    return a

Vì vậy, "logic" là hoàn toàn hợp lệ trong câu lệnh OP, mặc dù nó dài dòng. Coi chừng, nó không tệ. Thật hoàn hảo nếu bạn cần một hàm hoạt động như một toán tử toán học dựa trên một loại ma trận. Những người khác sẽ triển khai một khối thực tế (như câu lệnh Quine-McCluskey):

or = array[2][2] {
    {0, 1},
    {1, 1}
}

Và bạn sẽ đánh giá hoặc [a] [b]

Vì vậy, có, mọi logic ở đây là hợp lệ (ngoại trừ một logic được đăng dưới dạng sử dụng toán tử OR ngôn ngữ xDDDDDDDD).

Nhưng điều tôi thích nhất là luật của DeMorgan: !(!a && !b)


0

Nhìn vào thư viện chuẩn Swift và kiểm tra việc họ thực hiện các phím tắt HOẶC và các thao tác AND tắt, không đánh giá các toán hạng thứ hai nếu không cần thiết / cho phép.


-2

Logic là hoàn toàn chính xác, nhưng có thể được đơn giản hóa:

or(arg1, arg2)
  if arg1 = True
     return True
  else if arg2 = True
     return True
  else
     return False

Và có lẽ ngôn ngữ của bạn có toán tử OR - trừ khi nó trái với tinh thần của câu hỏi - tại sao không

or(arg1, arg2)
  if arg1 = True or arg2 = True
     return True
  else
     return False

if arg1 = True or arg2 = True { return true } else { return false }Hơn thế nữa, return arg1 = True or arg2 = True. if condition then true else falselà dư thừa.
Doval 16/12/14

4
Người hỏi đặc biệt chỉ ra rằng yêu cầu của họ là "không sử dụng chính người vận hành"
gnat

2
Ừm, tôi không nói gì cả. Đó là những gì tôi muốn nói, nhưng câu hỏi đã không nói như vậy cho đến khi nó được chỉnh sửa, và cô ấy đã trả lời như vậy, đó là lỗi của tôi về câu hỏi đó.
logicNoob
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.