कैसे "या" तार्किक रूप से परिभाषित करने के लिए


36

हाल ही में, मुझे एक समस्या आई, जिसने मुझे तार्किक "या" ऑपरेटर को प्रोग्रामेटिक रूप से परिभाषित करने की आवश्यकता थी, लेकिन ऑपरेटर का उपयोग किए बिना।

मैं इसके साथ आया हूं:

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

क्या यह तर्क सही है, या मुझे कुछ याद आया?


10
@gnat: निष्पक्ष होने के लिए, एक सत्य तालिका इनपुट के प्रत्येक संयोजन के लिए आउटपुट को सूचीबद्ध करती है और विकिपीडिया लेख फ़ंक्शन का विवरण देता है। मुझे लगता है कि ओपी वास्तव में क्या पूछ रहा है कि ऑपरेटर के उपयोग के बिना तार्किक या प्रोग्राम को कैसे परिभाषित किया जाए।
ब्लरफाल

6
@ user3687688 क्या आप कृपया उन प्राथमिकताओं को स्पष्ट कर सकते हैं, जिनका हम उपयोग करने की अनुमति देते हैं?
fredoverflow

4
इस सवाल ने माइक्रो-ऑप्टिमाइज़ेशन का एक सामूहिक ऐंठन शुरू कर दिया है;)
रोब

8
आप टर्निरी ऑपरेटर का उपयोग कर सकते हैंreturn arg1 ? arg1 : arg2;
मैथ्यू

4
मुझे पता चल गया है कि आपको orऑपरेटर को फिर से परिभाषित करने की आवश्यकता क्यों है ।
काइल स्ट्रैंड

जवाबों:


102

मैं कहूंगा कि यह सही है, लेकिन क्या आप इसे इस तरह से निंदा नहीं कर सकते?

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

    return false

चूंकि आप एक या तुलना कर रहे हैं, मुझे नहीं लगता कि आपको वास्तव में संयोजन की जांच करने की आवश्यकता है। यह सिर्फ मायने रखता है अगर उनमें से एक सच लौटना सही है। अन्यथा हम झूठे लौटना चाहते हैं।

यदि आप एक छोटे संस्करण की तलाश कर रहे हैं जो कि कम क्रिया है, तो यह भी काम करेगा:

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

6
आप लाइन 4 पर "और" को भी हटा सकते हैं (बस छोड़कर if arg2 == true)।
डॉसन टूथ

1
@DawsonToth आप इसे स्पिन कर सकते हैं कई अलग-अलग तरीके हैं, यह निर्भर करता है कि क्या आप वास्तव में क्रिया या संघनित होना चाहते हैं। मैं इसके साथ खुश होऊंगा, लेकिन अगर ऐसा लगता है कि यह एक छद्म कोड प्रश्न है तो मैं इसे स्पष्टता के लिए इस तरह छोड़ दूंगा। हालांकि बहुत सच है!
इलियट ब्लैकबर्न

@BlueHat यह एक और का उपयोग करने के लिए थोड़ा असंगत लगता है अगर, लेकिन अंत में एक और नहीं।
SBoss 8:17

1
@ मेहरदाद धन्यवाद! मैंने पुराने उत्तर को सिर्फ इसलिए शामिल किया है क्योंकि मुझे लगता है कि यह थोड़ा अधिक क्रिया है और समाधान को थोड़ा स्पष्ट करता है। लेकिन आपका समाधान बहुत छोटा है और वही काम करता है।
इलियट ब्लैकबर्न

1
इससे भी बेहतर (बदतर):or(a, b): a ? a : b
सारा

149

यहाँ एक समाधान के बिना या, और, तुलना और बूलियन शाब्दिक है:

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

यह शायद उससे अधिक मौलिक नहीं मिलता है;)


32
खदान से थोड़ा कम जवाब के लिए +1। हालाँकि मुझे "और" और साथ ही लालित्य के लिए भी लुभाया जाएगा।
इलियट ब्लैकबर्न

10
@BlueHat लेकिन फिर दोनों रिटर्न अलग-अलग हो जाएंगे;)
fredoverflow

5
मैं हर बार किसी के खिलाफ तुलना trueया किसी की तुलना में एक EUR प्राप्त करना चाहूंगा false
जेन्सजी

1
@ जेन्स जी, आपको क्या लगता है कि बिल गेट्स की आय कहां से आती है?
क्रोल्टन

1
जावास्क्रिप्ट ||ऑपरेटर संक्षेप में (जब एक गतिशील रूप से टाइप की गई भाषा में लागू किया जाता है)।
रीनो

108

कोड की एक पंक्ति:

return not (not arg1 and not arg2)

कोई शाखा, नहीं OR।

सी-आधारित भाषा में, यह होगा:

return !(!arg1 && !arg2);

यह बस डी मॉर्गन के कानूनों का एक आवेदन है :(A || B) == !(!A && !B)


6
मुझे लगता है कि यह दृष्टिकोण सबसे अच्छा समाधान है क्योंकि (मेरी राय में) एक if/elseनिर्माण एक ही नाम के साथ ओआर का उपयोग करने के समान है।
निक

2
@ निक का उपयोग ifसमानता के बराबर है। आम तौर पर मशीन कोड में एक ifअंकगणितीय के रूप में लागू किया जाता है और एक छलांग के साथ शून्य की तुलना की जाती है।

6
संदर्भ के लिए: en.wikipedia.org/wiki/De_Morgan%27s_laws
Mephy

1
मुझे यह दृष्टिकोण पसंद है क्योंकि यह शॉर्ट-सर्किट IFF andशॉर्ट सर्किट, इस प्रकार ऑपरेटरों के बीच स्थिरता प्रदान करता है।
काइल स्ट्रैंड

1
@Snowman यह सच है। मेरा मतलब था कि if (a) return true; else if (b) return true;कम या ज्यादा नैतिक रूप से इसके बराबर लगता है if (a OR b) return true;, लेकिन यह दृश्य विवाद के लिए अच्छी तरह से खुला हो सकता है।
निक

13

यदि आपके पास केवल andऔर not, आप फ्लिप करने के लिए DeMorgan के नियम का उपयोग कर सकते हैं and:

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

... या (और भी सरल)

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

...

और जब से हम सब स्पष्ट रूप से कुछ है कि लगभग हमेशा एक मशीन निर्देश के रूप में उपलब्ध है पर अनुकूलन करने पर तय हो जाते हैं, कि नीचे उबलता है:

return not(not arg1 and not arg2)

return arg1 ? true : arg2

आदि आदि आदि।

चूंकि अधिकांश भाषाएं सशर्त प्रदान करती हैं, और, "और" ऑपरेटर वैसे भी एक शाखा का अर्थ है।

...

यदि आपके पास सब कुछ है nand( विकिपीडिया देखें ):

वापसी नंद (नंद 1 (arg1, arg1), नंद (arg2, arg2))


7
return not (not arg1 and not arg2)

@Snowman आपको वास्तव में यह उत्तर देना चाहिए ताकि मैं इसे बढ़ा सकूं। आप यहां (वर्तमान में) केवल एक हैं जो ब्रांचिंग के साथ नहीं गए थे।
Lawtonfogle

4
NAND समाधान जोड़ने जा रहा था, लेकिन आपने मुझे इसमें हरा दिया। सब कुछ नंद के संदर्भ में लागू किया जाना चाहिए।
एंडी

2
@Andy: दरअसल, NOR के संदर्भ में सब कुछ परिभाषित किया जाना चाहिए। ;-)
पीटर गेकर्न्स

1
शुद्ध nandसमाधान के साथ अच्छा काम ।
एएटी

13

कार्य (ECMAScript)

आपको केवल फ़ंक्शन परिभाषा और फ़ंक्शन कॉल की आवश्यकता है। आप किसी भी शाखाओं, सशर्त, ऑपरेटरों या बिलिन कार्यों की आवश्यकता नहीं है। मैं ECMAScript का उपयोग करके एक कार्यान्वयन प्रदर्शित करूंगा।

सबसे पहले, चलो नामक दो कार्यों को परिभाषित करते हैं trueऔर false। हम उन्हें किसी भी तरह से परिभाषित कर सकते हैं जो हम चाहते हैं, वे पूरी तरह से मनमाना हैं, लेकिन हम उन्हें बहुत ही विशेष तरीके से परिभाषित करेंगे जिसके कुछ फायदे हैं जैसा कि हम बाद में देखेंगे:

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

truएक ऐसा कार्य है जो दो मापदंडों के साथ होता है जो केवल इसके दूसरे तर्क को अनदेखा करता है और पहला लौटाता है। flsदो मापदंडों के साथ एक फ़ंक्शन भी है जो केवल इसके पहले तर्क को अनदेखा करता है और दूसरे को लौटाता है।

हमने क्यों truऔर flsइस तरह से एनकोड किया ? खैर, इस तरह से, दो कार्य केवल के दो अवधारणाओं का प्रतिनिधित्व नहीं trueऔर false, नहीं, एक ही समय में, वे भी "विकल्प" की अवधारणा का प्रतिनिधित्व करते हैं, दूसरे शब्दों में, वे भी एक हैं if/ then/ elseअभिव्यक्ति! हम ifस्थिति का मूल्यांकन करते हैं और इसे तर्क के रूप में thenब्लॉक और ब्लॉक पास करते हैं else। यदि स्थिति का मूल्यांकन truकरता thenहै, तो यह ब्लॉक को लौटा देगा , यदि यह मूल्यांकन करता है, तो यह ब्लॉक flsको वापस कर देगा else। यहाँ एक उदाहरण है:

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

यह रिटर्न 23, और यह:

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

42जैसा आप उम्मीद करेंगे, वैसा ही रिटर्न ।

एक शिकन है, हालांकि:

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

यह दोनों प्रिंट then branchऔर else branch! क्यूं कर?

ठीक है, यह पहले तर्क का रिटर्न मूल्य देता है, लेकिन यह दोनों तर्कों का मूल्यांकन करता है, क्योंकि ECMAScript सख्त है और फ़ंक्शन को कॉल करने से पहले एक फ़ंक्शन के सभी तर्कों का हमेशा मूल्यांकन करता है। IOW: यह पहले तर्क का मूल्यांकन करता है console.log("then branch"), जो कि केवल रिटर्न करता है undefinedऔर then branchकंसोल पर प्रिंटिंग का साइड-इफेक्ट होता है , और यह दूसरे तर्क का मूल्यांकन करता है, जो undefinedकंसोल पर साइड-इफेक्ट के रूप में रिटर्न और प्रिंट भी करता है। फिर, यह पहला रिटर्न देता है undefined

Λ-पथरी में, जहां इस एन्कोडिंग का आविष्कार किया गया था, यह कोई समस्या नहीं है: λ-पथरी शुद्ध है , जिसका अर्थ है कि इसका कोई दुष्प्रभाव नहीं है; इसलिए आप कभी भी नोटिस नहीं करेंगे कि दूसरे तर्क का भी मूल्यांकन किया जाता है। इसके अलावा, λ-पथरी आलसी है (या कम से कम, यह अक्सर सामान्य आदेश के तहत मूल्यांकन किया जाता है), जिसका अर्थ है, यह वास्तव में उन तर्कों का मूल्यांकन नहीं करता है जिनकी आवश्यकता नहीं है। तो, IOW: λ-पथरी में दूसरे तर्क का मूल्यांकन कभी नहीं किया जाएगा, और यदि यह होता तो हम नोटिस नहीं करते।

हालाँकि, ECMAScript सख्त है , अर्थात यह हमेशा सभी तर्कों का मूल्यांकन करता है। ठीक है, वास्तव में, हमेशा नहीं: if/ then/ else, उदाहरण के लिए, केवल thenशाखा का मूल्यांकन करता है यदि स्थिति है trueऔर केवल elseशाखा का मूल्यांकन करता है यदि स्थिति है false। और हम इस व्यवहार को अपने साथ दोहराना चाहते हैं iff। शुक्र है, भले ही ECMAScript आलसी न हो, लेकिन कोड के टुकड़े के मूल्यांकन में देरी करने का एक तरीका है, उसी तरह लगभग हर दूसरी भाषा करती है: इसे किसी फ़ंक्शन में लपेटें, और यदि आप उस फ़ंक्शन को कभी नहीं कहते हैं, तो कोड होगा कभी अमल नहीं किया।

इसलिए, हम एक फ़ंक्शन में दोनों ब्लॉक लपेटते हैं, और अंत में दिए गए फ़ंक्शन को कॉल करते हैं:

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

प्रिंट then branchऔर

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

प्रिंट करता है else branch

हम पारंपरिक if/ then/ elseइस तरह से लागू कर सकते हैं :

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

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

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

फिर से, हमें फ़ंक्शन को कॉल करते समय कुछ अतिरिक्त फ़ंक्शन रैपिंग की आवश्यकता iffहोती है और अतिरिक्त फ़ंक्शन कॉल को परिभाषा में कोष्ठक कहते हैं iff, उसी कारण से:

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

अब जबकि हमारे पास वे दो परिभाषाएँ हैं, हम लागू कर सकते हैं or। सबसे पहले, हम इसके लिए सत्य सारणी को देखते हैं or: यदि पहला संकार्य सत्य है, तो अभिव्यक्ति का परिणाम पहले कैंडिड के समान है। अन्यथा, अभिव्यक्ति का परिणाम दूसरे ऑपरेंड का परिणाम है। संक्षेप में: यदि पहला ऑपरेंड है true, तो हम पहला ऑपरेंड वापस करते हैं, अन्यथा हम दूसरा ऑपरेंड वापस करते हैं:

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

आइए देखें कि यह काम करता है:

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

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

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

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

महान! हालाँकि, वह परिभाषा थोड़ी बदसूरत लग रही है। याद रखें, truऔर flsपहले से ही अपने आप से एक सशर्त की तरह कार्य करते हैं, इसलिए वास्तव में इसकी कोई आवश्यकता नहीं है iff, और इस प्रकार सभी उस फ़ंक्शन को सभी पर लपेटते हैं:

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

आपके पास यह है: or(और अन्य बूलियन ऑपरेटर) केवल कुछ ही पंक्तियों में फ़ंक्शन परिभाषाओं और फ़ंक्शन कॉल के साथ कुछ भी परिभाषित नहीं करते हैं:

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)();

दुर्भाग्य से, यह कार्यान्वयन बेकार है: ECMAScript में कोई फ़ंक्शंस या ऑपरेटर नहीं हैं जो वापस आते हैं truया fls, वे सभी वापस लौटते हैं trueया false, इसलिए हम उन्हें अपने कार्यों के साथ उपयोग नहीं कर सकते हैं। लेकिन अभी भी बहुत कुछ है जो हम कर सकते हैं। उदाहरण के लिए, यह एक एकल-लिंक्ड सूची का कार्यान्वयन है:

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

ऑब्जेक्ट्स (स्काला)

आपने कुछ अजीबोगरीब देखा होगा: truऔर flsदोहरी भूमिका निभाते हुए, वे डेटा मानों के रूप में कार्य करते हैं trueऔर falseसाथ ही, वे एक सशर्त अभिव्यक्ति के रूप में भी कार्य करते हैं। वे डेटा और व्यवहार कर रहे हैं , एक में बँधा हुआ ... उह ... "बात" ... या (मुझे कहने की हिम्मत है) वस्तु !

वास्तव में, truऔर flsवस्तुएं हैं। और, यदि आपने कभी स्मॉलटाक, सेल्फ, न्यूजक या अन्य ऑब्जेक्ट-ओरिएंटेड भाषाओं का उपयोग किया है, तो आपने देखा होगा कि वे बिल्कुल उसी तरह से बूलियन को लागू करते हैं। मैं यहां स्काला में इस तरह के कार्यान्वयन का प्रदर्शन करूंगा:

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 यही कारण है कि पॉलीमॉर्फ़िज्म रिफ्लेक्टिंग के साथ कंडिशनल रिप्लेसमेंट हमेशा काम करता है: आप हमेशा अपने प्रोग्राम में किसी भी और हर कंडीशनल को पॉलीमॉर्फिक मैसेज प्रेषण के साथ बदल सकते हैं, क्योंकि जैसा कि हमने अभी दिखाया है, पॉलीमॉर्फिक मैसेज चेक बस लागू करके सशर्त की जगह ले सकता है। स्मॉलटाक, सेल्फ और न्यूजक जैसी भाषाएं इस बात का अस्तित्व प्रमाण हैं, क्योंकि उन भाषाओं में भी सशर्त नहीं हैं। (उनके पास लूप्स, BTW या वास्तव में किसी भी प्रकार की भाषा में निर्मित नियंत्रण संरचना नहीं है, सिवाय बहुरूपिक संदेश के लिए उर्फ ​​वर्चुअल मेथड कॉल्स प्रेषण।)


पैटर्न मिलान (हास्केल)

आप orपैटर्न मिलान, या हास्केल की आंशिक फ़ंक्शन परिभाषा जैसी किसी चीज़ का उपयोग करके भी परिभाषित कर सकते हैं :

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

बेशक, पैटर्न मिलान सशर्त निष्पादन का एक रूप है, लेकिन फिर फिर से, वस्तु-उन्मुख संदेश प्रेषण है।


2
कैसे False ||| False = Falseऔर _ ||| _ = Trueइसके बजाय? :)
fredoverflow

3
@FredOverflow: इसके लिए हमेशा सही ऑपरेंड का मूल्यांकन करना होगा। आमतौर पर बूलियन ऑपरेटरों को उनके सही तर्क उर्फ ​​"शॉर्ट-सर्कुइंग" में गैर-सख्त होने की उम्मीद है।
जोर्ग डब्ल्यू मित्तग

आह, बिल्कुल। मुझे पता था कि इसका गहरा कारण होना था :)
fredoverflow

पहले भाग ने मुझे निरंतर उत्तीर्ण शैली के बारे में एरिक लिपर्ट की महान श्रृंखला की याद दिला दी । विशुद्ध रूप से संयोग लेकिन फिर भी मज़ेदार :)
Voo

1
@ JörgWMittag फ्रेड ऑवरफ्लो की परिभाषा उचित रूप से कम-परिचालित है। True ||| undefinedदेखने के लिए अपने आप को ghci में आज़माएं !
डेनियल वैगनर

3

इसे परिभाषित करने के सबसे पारंपरिक तरीके का उपयोग करते हुए, या वास्तव में किसी भी तार्किक ऑपरेटर को परिभाषित करने का एक और तरीका है: एक सत्य तालिका का उपयोग करें।

यह उच्च स्तरीय भाषाओं जैसे जावास्क्रिप्ट या पर्ल में करने के लिए निश्चित रूप से काफी तुच्छ है, लेकिन मैं सी में यह उदाहरण लिख रहा हूं कि यह दिखाने के लिए कि तकनीक उच्च स्तरीय भाषा सुविधाओं पर निर्भर नहीं करती है:

#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");
    }
}

आप AND, NOR, NAND, NOT और XOR के साथ भी ऐसा कर सकते हैं। कोड सिंटैक्स की तरह दिखने के लिए पर्याप्त साफ है ताकि आप इस तरह से सामान बना सकें:

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

मुझे लगता है कि यह कुछ गणितीय अर्थों में "शुद्धतम" दृष्टिकोण है। OR- ऑपरेटर सब के बाद एक फ़ंक्शन है, और सत्य तालिका वास्तव में एक संबंध और एक सेट के रूप में उस फ़ंक्शन का सार है। बेशक यह एक मनोरंजक OO तरीके से भी लिखा जा सकता है:BinaryOperator or = new TruthTableBasedBinaryOperator(new TruthTable(false, true, true, true));
COME FROM

3

तार्किक ऑपरेटरों को पूर्णांक अंकगणितीय अभिव्यक्तियों (जहां संभव है) के रूप में व्यक्त करने का दूसरा तरीका। इस तरह से कई विधेय की एक बड़ी अभिव्यक्ति के लिए बहुत सारे ब्रांचिंग से बचा जा सकता है।

सच होने दो 1 झूठी होने दो

यदि दोनों का योग 1 से अधिक है तो लौटाया जाना सही या गलत है।

boolean isOR(boolean arg1, boolean arg2){

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

   return (L+R) > 0;

}

6
booleanExpression ? true : falseतुच्छ के बराबर है booleanExpression
कीन

मुझे आपकी कार्यप्रणाली पसंद है लेकिन एक साधारण गलती यह है कि दोनों तर्कों का योग ZERO से बड़ा होना चाहिए, एक से अधिक नहीं।
धीरे

1
return (arga+argb)>0
Grantly

1
मैं केवल आपके पाठ को सही कर रहा था। आपका कोड सही है, लेकिन एक पंक्ति में हो सकता है: return (((arg1 ? 1 : 0)+(arg2 ? 1 : 0)) > 0); :)
धीरे से

1
@SenthuSivasambu मुझे आपके इस्तेमाल पर कोई आपत्ति नहीं है arg1 ? 1 : 0;। बुलियन को एक संख्या में बदलने के लिए वे विश्वसनीय अभिव्यक्ति हैं। यह केवल रिटर्न स्टेटमेंट है जिसे तुच्छ रूप से दर्शाया जा सकता है।
कीन

1

दो रूप:

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

या

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

कोड के साथ-साथ अन्य सुझावों की तुलना में थोड़ा छोटा होने का लाभ उठाएं, जो कि एक कम शाखा है। यह भी मूर्खतापूर्ण नहीं है कि अगर हम एक आदिम के निर्माण पर विचार कर रहे हैं तो शाखाओं की संख्या को कम करने के लिए एक माइक्रो-ऑप्ट होता है जो कि बहुत भारी उपयोग किया जाएगा।

जावास्क्रिप्ट की परिभाषा ||इस के समान है, जो अपनी ढीली टाइपिंग के साथ संयुक्त है इसका मतलब है कि अभिव्यक्ति false || "abc"का मूल्य है "abc"और 42 || "abc"मूल्य है 42

यद्यपि यदि आपके पास पहले से ही अन्य तार्किक ऑपरेटर हैं, तो पसंद nand(not(arg1), not(arg2))को बिना किसी शाखा के फायदा हो सकता है।


पूर्व उत्तर को दोहराने की बात क्या है ( जैसा आपने स्वीकार किया है )?
gnat

@ लगन काफी करीब है जिसे मैंने परेशान नहीं किया होगा मैंने उस उत्तर को देखा था, लेकिन यह अभी भी इसके बारे में कुछ भी उनमें से किसी में नहीं मिला है, इसलिए मैं इसे छोड़ रहा हूं।
जॉन हैना

@gnat, वास्तव में "हम लंबे जवाब की तलाश कर रहे हैं जो कुछ स्पष्टीकरण और संदर्भ प्रदान करते हैं।" मैं अब इस जवाब से खुश हूं।
जॉन हन्ना

1

यदि निर्माण का उपयोग करते हुए सभी प्रोग्राम किए गए समाधानों के अलावा, तीन नंद फाटकों को मिलाकर OR गेट का निर्माण करना संभव है। यदि आप देखना चाहते हैं कि यह विकिपीडिया में कैसे किया जाता है, तो यहाँ क्लिक करें

इससे, अभिव्यक्ति,

नहीं [नहीं (ए और ए) और नहीं (बी और बी)]

जो नहीं का उपयोग करता है और OR के समान उत्तर देता है। ध्यान दें कि NOT और AND दोनों का उपयोग नंद को व्यक्त करने का एक अस्पष्ट तरीका है।


नहीं (ए और ए) == नहीं (ए)?
चार्ली

हाँ बिल्कुल। एक ही विकिपीडिया लेख में, आप देख सकते हैं कि वे नंद द्वार के लिए एक गेट नहीं कैसे कम करते हैं। एक और गेट के लिए भी। मैंने OR फाटक के लिए उनके द्वारा प्रस्तुत किए गए सूत्र को संपादित नहीं करने का विकल्प चुना।
वाल्टर मिटी

1

सभी अच्छे उत्तर पहले ही दिए जा चुके हैं। लेकिन मैं ऐसा नहीं होने दूंगा।

// 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)

वैकल्पिक रूप से:

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

मुझे उम्मीद है कि कोई भी वास्तव में इन जैसे दृष्टिकोण का उपयोग नहीं करेगा। वे यहां केवल विकल्पों की जागरूकता को बढ़ावा देने के लिए हैं।

अद्यतन करें:

चूंकि नकारात्मक संख्याएं उपरोक्त दोनों दृष्टिकोणों को तोड़ सकती हैं, इसलिए यहां एक और भयानक सुझाव है:

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

यह केवल का उपयोग करता DeMorgan के नियम और गाली तथ्य यह है कि *के समान है &&जब trueऔर falseकी तरह व्यवहार कर रहे हैं 1और 0क्रमशः। (रुको, आप कह रहे हैं यह कोड गोल्फ नहीं है ?)

यहाँ एक सभ्य जवाब है:

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

लेकिन यह अनिवार्य रूप से पहले से दिए गए अन्य उत्तरों के समान है।


3
ये दृष्टिकोण मूलभूत रूप से त्रुटिपूर्ण हैं। आदि के arg1+arg2लिए -1 + 1 , -1 और 0 पर विचार करेंmax(arg1,arg2)
शराबी

@fluffy यह दृष्टिकोण बूलियन तर्कों को मानता है, और फिर यह अधिकांश प्रकार के कचरा इनपुट के साथ सही ढंग से काम करने के लिए होता है। आपको यह बताने के लिए अच्छा है कि अभी भी कुछ कचरा है जो मुद्दों को पैदा करता है। इस तरह की बात वास्तव में है कि हमें वास्तविक समस्या डोमेन को यथासंभव सीधे मॉडल करना चाहिए (और अपनी खुद की चतुराई से दूर रखने से) अभ्यास में।
कीन

यदि आप शुद्ध 1-बिट बूलियन मान कर रहे हैं, तो इसके अलावा अभी भी काम नहीं करता है, क्योंकि 1 + 1 = 0. :)
शराबी

@fluffy वह जगह है जहाँ स्पष्ट रूपांतरण आते हैं। चाहे उनकी आवश्यकता हो या नहीं, कार्यान्वयन के विवरण पर निर्भर करता है (जो कि वास्तव में यह एक मूर्खतापूर्ण विचार है)।
कीन

0

परिभाषित करने orका एक तरीका लुकअप टेबल है। हम इसे स्पष्ट कर सकते हैं:

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

हम मानों के साथ एक सरणी बनाते हैं जो कि वापसी मूल्य के आधार पर होना चाहिए a। फिर हम एक खोज करते हैं। C ++ में भाषाओं की तरह, boolएक वैल्यू इंडेक्स के रूप में उपयोग किए जा सकने वाले मान को बढ़ावा देता है, और trueहोने के साथ1false किया जा रहा है 0

इसके बाद हम इसे अन्य तार्किक परिचालनों तक बढ़ा सकते हैं:

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];
}

अब इन सब में एक नकारात्मक पहलू यह है कि इसके लिए उपसर्ग संकेतन की आवश्यकता है।

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];
}

और अब आप टाइप कर सकते हैं true *OR* false और यह काम करता है।

उपरोक्त तकनीक के लिए एक भाषा की आवश्यकता होती है जो तर्क पर निर्भर लुकअप और टेम्प्लेट का समर्थन करती है। आप शायद इसे जेनेरिक और ADL वाली भाषा में कर सकते हैं।

एक तरफ के रूप में, आप *OR*सेट के साथ काम करने के लिए ऊपर का विस्तार कर सकते हैं । बस के invokeरूप में एक ही नाम स्थान में एक नि: शुल्क समारोह बनाएँ 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;
}

और अब set *OR* setदोनों का मिलन लौटाता है।


0

यह मुझे वर्णनात्मक कार्यों को याद करता है:

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

यह केवल उन भाषाओं पर लागू होता है, जो बुलियन का इलाज कर सकते हैं (1, 0)। स्मॉलटाक या पायथन पर लागू नहीं होता है क्योंकि बूलियन एक वर्ग है। स्मालटाक में वे और भी आगे जाते हैं (यह एक छद्मकोश की तरह लिखा जाएगा):

False::or(a)
    return a

True::or(a)
    return self

और दोहरे तरीके मौजूद हैं:

False::and(a)
    return self

True::and(a)
    return a

तो ओपी के बयान में "तर्क" पूरी तरह से मान्य है, इसके लिए यह क्रिया है। खबरदार, यह बुरा नहीं है। यह सही है अगर आपको एक फ़ंक्शन की आवश्यकता होती है जो एक गणितीय ऑपरेटर की तरह काम करता है, जैसे, मैट्रिक्स का एक प्रकार। अन्य लोग एक वास्तविक क्यूब को लागू करेंगे (जैसे कि क्वीन-मैकलुस्की कथन):

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

और आप मूल्यांकन करेंगे या [a] [b]

तो हाँ, यहाँ हर तर्क वैध है (सिवाय इसके कि कोई इन-लैंग्वेज या ऑपरेटर xDDDDDDDD का उपयोग करके पोस्ट किया जाए)।

लेकिन मेरा पसंदीदा एक डेमोरोन का नियम है: !(!a && !b)


0

स्विफ्ट मानक पुस्तकालय को देखें और शॉर्टकट या शॉर्टकट और संचालन के उनके कार्यान्वयन की जांच करें, जो आवश्यक या अनुमति नहीं होने पर दूसरे ऑपरेंड का मूल्यांकन नहीं करते हैं


-2

तर्क पूरी तरह से सही है, लेकिन सरलीकृत किया जा सकता है:

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

और संभवतः आपकी भाषा में OR ऑपरेटर है - जब तक कि यह प्रश्न की भावना के विरुद्ध नहीं है - क्यों नहीं

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 }बेहतर अभी तक return arg1 = True or arg2 = True,। if condition then true else falseबेमानी है।
डोभाल

4
प्रश्नकर्ता विशेष रूप से कहा कि उनकी आवश्यकता थी "ऑपरेटर खुद का उपयोग किए बिना"
कुटकी

2
उम, मैंने कुछ भी नहीं कहा। यह मेरा मतलब था, लेकिन यह ऐसा नहीं था जब तक कि इसे संपादित नहीं किया गया था, और उसने इस तरह से जवाब दिया, उस तरह से मेरी गलती थी।
लॉजिकन्यूब
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.