Mantıksal olarak “veya” nasıl tanımlanır


36

Son zamanlarda, mantıksal "OR" operatörünü programlı olarak tanımlamamı gerektiren, ancak operatörün kendisini kullanmamamı gerektiren bir sorunla karşılaştım.

Benim geldiğim şey şuydu:

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

Bu mantık doğru mu, yoksa bir şey mi kaçırdım?


10
@gnat: Adil olmak gerekirse, doğruluk tablosu girdilerin her bir birleşiminin çıktılarını listeler ve Wikipedia makalesi işlevin bir açıklamasını verir. OP'nin asıl sorduğu şeyin , operatörün kendisini kullanmadan mantıksal bir OR'yi programlı olarak nasıl tanımlayacağını düşünüyorum .
Blrfl

6
@ user3687688 Kullanmamıza izin veren ilkelleri açıklayabilir misiniz?
fredoverflow

4
bu soru kollektif bir mikro-optimizasyon spazmı başlattı;)
Rob,

8
Üçlü operatörreturn arg1 ? arg1 : arg2;
Matthew

4
orOperatörü neden yeniden tanımlamanız gerektiğini bilmek zorundayım .
Kyle Strand,

Yanıtlar:


102

Bunun doğru olduğunu söyleyebilirim, ama böyle bir şeye yoğunlaşamaz mısın?

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

    return false

Bir karşılaştırma veya karşılaştırma yaptığınız için, kombinasyonu gerçekten kontrol etmeniz gerekmiyor. Sadece bir tanesi doğru dönmek için doğruysa önemlidir. Aksi takdirde yanlış döndürmek istiyoruz.

Daha az ayrıntılı olan daha kısa bir sürüm arıyorsanız, bu da işe yarayacaktır:

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

6
4. satırdaki "else" i de kaldırabilirsiniz (sadece bırakarak if arg2 == true).
Dawson Toth,

1
@DawsonToth Onu döndürmenin birçok farklı yolu var, gerçekten ayrıntılı ya da yoğunlaştırılmak isteyip istemediğinize bağlı. Başka bir şeyle mutlu olurum ama kulağa öyle geliyorsa, sahte bir kod sorusuysa, açıklık için muhtemelen bu şekilde bırakacağım. Yine de çok doğru!
Elliot Blackburn,

@BlueHat Bir başkasını kullanmak, ancak sonunda bir başkasını kullanmak için biraz tutarsız görünüyor.
SBoss

1
@Mehrdad Teşekkürler! Eski cevabı geri aldım, çünkü bunun biraz daha ayrıntılı olduğunu düşünüyorum ve çözümü biraz daha net olarak açıkladım. Ancak çözümünüz çok daha küçük ve aynı işi yapıyor.
Elliot Blackburn

1
daha da iyisi (daha kötüsü):or(a, b): a ? a : b
sara

149

Karşılaştırmalar ve boolean değişmezler olmadan veya olmasın bir çözüm:

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

Muhtemelen bundan daha temel olamaz;)


32
Benimkinden biraz daha kısa bir cevap için +1. Ancak, sadece zerafet için "öteki" yi de bırakmaya özendirilirim.
Elliot Blackburn,

10
@BlueHat Ama sonra iki dönüş farklı girintili olacaktır;)
fredoverflow

5
Birisi trueveya aleyhinde bir şey karşılaştırdığında bir EUR almak istiyorum false.
JensG

1
@JensG Peki, sence Bill Gates'in geliri nereden geliyor?
Kroltan

1
||Özetle JavaScript operatörü (dinamik olarak yazılmış bir dilde uygulandığında).
gergedan

108

Bir kod satırı:

return not (not arg1 and not arg2)

Dallanma yok, OR yok.

C tabanlı bir dilde şöyle olurdu:

return !(!arg1 && !arg2);

Bu sadece De Morgan yasalarının bir uygulamasıdır :(A || B) == !(!A && !B)


6
Bu yaklaşımın bence en iyi çözüm olduğunu düşünüyorum çünkü bence bir if/elseyapı sadece farklı bir isimle OR kullanmakla aynı.
Nick,

2
@Nick kullanarak ifeşitlik eşdeğerdir. Normalde makine kodunda bir ifaritmetik olarak uygulanır ve bunu sıfıra bir atlama ile karşılaştırır.


1
Bu yaklaşımı seviyorum, çünkü IFF andkısa devrelerini kısa devre yapıyor, böylece operatörler arasında tutarlılık sağlıyor.
Kyle Strand,

1
@Snowman Bu doğru. Demek istediğim, if (a) return true; else if (b) return true;aşağı yukarı ahlaki açıdan eşdeğer görünüyor if (a OR b) return true;, ancak bu görüş tartışmaya açık olabilir.
Nick

13

Eğer sadece sahipseniz andve notbunu yapmak için DeMorgan yasasını kullanabilirsiniz and:

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

... veya (daha da basit)

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

...

Ve görünüşe göre hepimiz hemen hemen her zaman bir makine talimatı olarak mevcut olan bir şeyi optimize etmeye karar verdik, bu da:

return not(not arg1 and not arg2)

return arg1 ? true : arg2

vb. vb. vb.

Çoğu dil koşullu sağladığından ve, oranlar "ve" işleci, zaten bir şube anlamına gelir.

...

Eğer sahip olduğunuz tek şeysenand (bkz. Wikipedia ):

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


7
Basitleştirin:return not (not arg1 and not arg2)

@Snowman bunu cevaplayabilmeniz için onu cevaplamalısınız. (Şu anda) burada, dallanma ile gitmeyen tek kişisiniz.
Lawtonfogle

4
NAND çözümünü ekleyecektim, ama beni yendin. Her şey NAND açısından uygulanmalıdır.
Andy

2
@Andy: Aslında, her şey NOR açısından tanımlanmalıdır. ;-)
Pieter Geerkens

1
Saf nandçözümle iyi iş çıkardınız .
AAT

13

İşlevler (ECMAScript)

Tek ihtiyacınız olan fonksiyon tanımları ve fonksiyon çağrıları. Dallara, koşullara, operatörlere veya yerleşik işlevlere ihtiyacınız yoktur. ECMAScript kullanarak bir uygulama göstereceğim.

İlk önce trueve adlı iki işlevi tanımlayalım false. Onları istediğimiz şekilde tanımlayabiliriz, tamamen keyfidirler, ancak daha sonra göreceğimiz gibi bazı avantajları olan çok özel bir şekilde tanımlayacağız:

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

trusadece ikinci argümanını görmezden gelen ve ilkini döndüren iki parametreli bir işlevdir. flsAynı zamanda ilk argümanını görmezden gelen ve ikincisini döndüren iki parametreli bir işlevdir.

Neden kodlamak vermedi truve flsbu şekilde? Peki, bu şekilde, iki işlev yalnızca iki kavramı temsil etmiyor trueve falsehayır, aynı zamanda “seçim” kavramını da temsil ediyor, başka bir deyişle, aynı zamanda bir if/ then/ elseifadesidir! ifDurumu değerlendiririz ve thenbloğu ve elsebloğu argüman olarak iletiriz. Koşul değerlendirirse tru, thenbloğu döndürür, değerlendirirse bloğu flsdöndürür else. İşte bir örnek:

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

Bu döner 23ve bu:

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

42tam beklediğiniz gibi döner .

Ancak, bir kırışıklık var:

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

Bu yazdırır hem then branch ve else branch! Neden?

Eh, o döndüren birinci argüman dönüş değeri, ancak değerlendirir ECMAScript sıkı ve her zaman işlevini çağırmadan önce bir işleve tüm argümanları değerlendirir beri, her iki argüman. IOW: o ilk argüman değerlendirir console.log("then branch")sadece döner undefinedve baskı yan etkisi vardır then branchkonsola, ve ikinci bir argüman, değerlendirir aynı zamanda, döner undefinedbir yan etki olarak konsola ve baskılar. Ardından, ilk döndürür undefined.

Bu kodlamanın icat edildiği cal-hesapta, bu bir problem değil: λ-hesap, saftır , yani herhangi bir yan etkisi yoktur; bu nedenle ikinci argümanın da değerlendirildiğini asla farketmezsiniz. Artı, λ-calculus tembeldir (veya en azından normal sıralar altında değerlendirilir), yani aslında gerekli olmayan argümanları değerlendirmez. Öyleyse, IOW: λ-calculus'ta ikinci argüman asla değerlendirilmeyecekti ve öyle olsaydı farketmezdik.

Ancak ECMAScript katıdır , yani her zaman tüm argümanları değerlendirir. Eh, aslında, her zaman değil: if/ then/ else, örneğin, thenkoşul trueyalnızca elsebu durumda dalı değerlendirir ve yalnızca koşul olduğunda dalı değerlendirir false. Ve biz bu davranışı kopyalamak istiyoruz iff. Neyse ki, ECMAScript tembel olmasa da, bir kod parçasının değerlendirmesini geciktirmenin bir yolu var, neredeyse her dilin yaptığı gibi: onu bir işleve sarın ve bu işlevi çağırmazsanız, kod asla idam edilme.

Böylece, her iki bloğu bir fonksiyona sardık ve sonunda döndürülen fonksiyonu çağırıyoruz:

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

yazdırır then branchve

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

yazdırır else branch.

Geleneksel if/ then/ elsebu şekilde uygulayabiliriz :

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

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

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

Yine, işlevi çağırırken bazı ekstra işlev sargısına iffve iffyukarıdaki gibi aynı işlev için ekstra işlev çağrısı parantezine ihtiyacımız var :

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

Şimdi bu iki tanımı yaptık, uygulayabiliyoruz or. İlk olarak, doğruluk tablosuna bakarız or: eğer ilk operand truthy ise, ifadenin sonucu ilk operand ile aynıdır. Aksi takdirde, ifadenin sonucu ikinci işlenenin sonucudur. Kısacası: eğer ilk işlenen ise trueilk işleneni geri veririz, aksi takdirde ikinci işleneni geri döndürürüz:

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

İşe yaradığını kontrol edelim:

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

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

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

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

Harika! Ancak, bu tanım biraz çirkin görünüyor. Unutmayın truve flszaten kendi başlarına şartlı gibi davranıyorlar, bu yüzden gerçekten gerek yok iff, ve böylece tüm bu fonksiyonların tamamının sarılmasına gerek yok :

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

İşte burada: or(artı diğer boolean operatörleri) sadece bir avuç satırda fonksiyon tanımları ve fonksiyon çağrıları dışında hiçbir şey tanımlanmamış:

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

Ne yazık ki, bu uygulama oldukça işe yaramaz: ECMAScript'te geri dönen truya flsda hepsi dönen trueya da falsebu nedenle işlevlerimizle kullanamadığımız hiçbir işlev ya da işleç yok . Ama hala yapabileceğimiz çok şey var. Örneğin, bu tek başına bağlı bir listenin bir uygulamasıdır:

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

Nesneler (Scala)

Sen fark şey Peculiar olabilir: truve flsbir çift rolü, bunlar veri değerleri olarak hem hareket trueve falsefakat aynı zamanda, aynı zamanda bir koşullu ifadesi olarak hareket ederler. Onlar veri ve davranışlardır , bir… uhm… “şey”… veya (söylemeye cüret eder) nesnesine toplanırlar !

Gerçekten truve flsnesnelerdir. Ve eğer Smalltalk, Self, Newspeak veya diğer nesne yönelimli dilleri kullandıysanız, aynı şekilde booleans uyguladığını fark etmişsinizdir. Böyle bir uygulamayı Scala'da göstereceğim:

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

Bu BTW'nin, Polimorfizmi Yeniden Düzenlemeyle Koşullu Değiştirme'nin daima işe yaramasının nedeni budur: programınızdaki her koşullu, polimorfik mesaj gönderme ile her zaman yerine geçebilir, çünkü az önce gösterdiğimiz gibi, polimorfik mesaj gönderme, koşulluları sadece uygulayarak değiştirebilir. Smalltalk, Self ve Newspeak gibi diller bunun varoluş kanıtıdır, çünkü bu dillerin şartsız bile olması şarttır. (Ayrıca, döngülere, BTW'ye ya da polimorfik mesaj gönderme, yani sanal yöntem çağrıları haricinde herhangi bir dilde yerleşik kontrol yapılarına sahip değillerdir .)


Desen Eşleştirme (Haskell)

orDesen eşleştirmeyi veya Haskell'in kısmi işlev tanımları gibi bir şey kullanarak da tanımlayabilirsiniz :

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

Elbette, desen eşleştirme bir koşullu yürütme biçimidir, ancak daha sonra yine nesne yönelimli ileti gönderimidir.


2
Nasıl hakkında False ||| False = Falseve _ ||| _ = Trueonun yerine? :)
fredoverflow

3
@ FredOverflow: Her zaman doğru işlemcinin değerlendirilmesini gerektirir. Genellikle Boolean operatörlerinin doğru argümanlarında, yani "kısa devre yaptırma" gibi katı olmaları beklenir.
Jörg W Mittag

Ah, elbette. Daha derin bir sebep olması gerektiğini biliyordum :)
fredoverflow

İlk bölüm bana hemen Eric Lippert'in devam eden geçiş tarzıyla ilgili harika serisini hatırlattı . Tamamen rastlantısal ama yine de eğlenceli :)
Voo

1
@ JörgWMittag FredOverflow'un tanımı uygun şekilde kısa devre yapıyor. True ||| undefinedGörmek için ghci'de kendinizi deneyin !
Daniel Wagner

3

Burada VEYA'yı ya da gerçekten herhangi bir mantıksal işleci tanımlamanın en geleneksel yolunu kullanarak tanımlamanın başka bir yolu: bir doğruluk tablosu kullanın.

Bu elbette Javascript veya Perl gibi daha yüksek seviyeli dillerde yapmak için oldukça önemsizdir ancak bu örneği C'nin içinde, tekniğin yüksek seviye dil özelliklerine bağlı olmadığını göstermek için yazıyorum:

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

Aynısını AND, NOR, NAND, NOT ve XOR ile yapabilirsiniz. Kod şöyle bir şey yapabilecek şekilde sözdizimine benzeyecek kadar temiz:

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

Bunun matematiksel anlamda “en saf” yaklaşım olduğunu düşünüyorum. OR-operatörü sonuçta bir fonksiyondur ve doğruluk tablosu gerçekten de bu fonksiyonun bir ilişki ve küme olarak özüdür. Tabii bu da eğlenceli bir OO şekilde yazılmış olabilir Of:BinaryOperator or = new TruthTableBasedBinaryOperator(new TruthTable(false, true, true, true));
GELMEKTEDİR

3

Mantıksal operatörleri bir tamsayı aritmetik ifadeleri olarak ifade etmenin bir başka yolu (mümkün olduğunda). Bu yol, birçok yüklemin daha büyük bir ifadesi için çok dallanmayı önleyebilir.

1 olsun yanlış olsun 0 olsun

Her ikisinin toplamı 1'den büyükse, o zaman geri dönmek doğru veya yanlış olur.

boolean isOR(boolean arg1, boolean arg2){

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

   return (L+R) > 0;

}

6
booleanExpression ? true : falseönemsizden eşittir booleanExpression.
Keen

Metodolojinizden hoşlanıyorum ama basit bir hata, her iki argümanın toplamının, SIFIR'dan daha büyük olması, BİR'den daha büyük olmaması gerektiğidir.
15'te

1
return (arga+argb)>0
Tamamen

1
Sadece metnini düzeltirdim. Kodunuz mükemmel değildir, ama bir çizgide olabilir: return (((arg1 ? 1 : 0)+(arg2 ? 1 : 0)) > 0); :)
Grantly

1
@SenthuSivasambu kullanımına itirazım yok arg1 ? 1 : 0;. Bunlar bir Booleanı bir sayıya dönüştürmek için güvenilir ifadelerdir. Sadece önemsiz şekilde yeniden etkilenebilecek iade ifadesidir.
Keen

1

İki form:

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

VEYA

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

Diğer önerilere göre biraz daha küçük olmanın yanında golf gibi bir avantaj daha var. Şube sayısını azaltmak için bu kadar aptalca bir mikro-optik bile değil, bu yüzden çok yoğun bir şekilde kullanılacak bir ilkel yaratmayı düşünüyoruz.

JavaScript tanımı ||ifade onun gevşek yazma aracı ile birlikte bu, hangi benzer olan false || "abc"bir değere sahiptir "abc"ve 42 || "abc"değere sahiptir 42.

Zaten başka mantıksal operatörlere sahip olsanız da, benzerleri nand(not(arg1), not(arg2))hiç dallanma olmaması avantajına sahip olabilir.


Önceki cevabı tekrarlamanın amacı nedir ( kabul ettiğiniz gibi )?
gnat

@gnat, bu cevabı görmeme rağmen canımı sıkmayacak kadar yakındı, ama yine de hiçbirinde bulamayacağınız bir şey var, bu yüzden bırakıyorum.
Jon Hanna

@gnat, aslında "Bir açıklama ve bağlam sağlayan uzun cevaplar arıyoruz" düşüncesinde. Şimdi bu cevapla daha mutluyum.
Jon Hanna

1

İf yapısını kullanan tüm programlanmış çözümlere ek olarak, üç NAND kapısını birleştirerek bir OR geçidi oluşturmak mümkündür. Wikipedia'da nasıl yapıldığını görmek istiyorsanız, buraya tıklayın .

Bundan, ifade,

DEĞİL [DEĞİL (A VE A) VE DEĞİL (B VE B)]

ve NOT kullanan VE VEYA ile aynı cevabı verir. Hem NOT hem de AND kullanımının NAND'ı ifade etmenin sadece belirsiz bir yolu olduğuna dikkat edin.


DEĞİL (A VE A) == DEĞİL (A)?
Charlie

Evet kesinlikle. Aynı wikipedia makalesinde, NOT kapısını NAND geçitlerine nasıl düşürdüklerini görebilirsiniz. VE kapısı için aynı. OR geçidi için sundukları formülü düzenlememeyi seçtim.
Walter Mitty

1

Tüm iyi cevaplar çoktan verildi. Ama bunun beni durdurmasına izin vermeyeceğim.

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

Alternatif:

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

Umarım hiç kimse böyle yaklaşımları kullanmaz. Sadece alternatiflerin farkındalığını arttırmak için buradalar.

Güncelleme:

Negatif sayılar yukarıdaki yaklaşımların her ikisini de kırabildiğinden, diğer bir kötü öneri:

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

Bu sadece DeMorgan Kanunlarını kullanır ve sırasıyla ne zaman ve neye* benzer ve &&ne şekilde muamele gördüğü gerçeğini kötüye kullanır . (Bekle, bunun kod golf olmadığını mı söylüyorsun ?)truefalse10

İşte iyi bir cevap:

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

Ancak bu, daha önce verilmiş olan diğer cevaplarla özdeştir.


3
Bu yaklaşımlar temelde hatalı. -1 + 1 arg1+arg2, -1 ve 0 max(arg1,arg2), vb.
kabarık

@fluffy Bu yaklaşım, Boolean argümanlarını üstlenir ve ardından çoğu çöp girdisi ile doğru şekilde çalışır. Sorun çıkaran bir miktar çöp olduğunu belirtmeniz iyi. Bu tür bir şey, gerçek problem alanını mümkün olduğu kadar doğrudan modellemeye çalışmamız (ve kendi zekamız tarafından ele geçirilmekten kaçınılması) pratikte bu şekilde yapılmalı.
Keen

Eğer saf 1-bit Mantıksal değerleri yapıyoruz, o zaman ekleme hala beri 1 + 1 = 0. :), iş yapmaz
kabarık

@ fluffy Açık dönüşümlerin geldiği yer burasıdır. İhtiyaç duyup duyulmadıkları, uygulamanın detaylarına bağlıdır (bu tam da bu yüzden aptalca bir fikirdir).
Keen

0

Tanımlamanın bir yolu orbir arama tablosu aracılığıyla. Bu açık yapabiliriz:

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

dönüş değerinin ne aolduğuna bağlı olarak sahip olması gereken değerleri içeren bir dizi yaratırız . Sonra bir arama yaparız. C ++ benzeri dillerde, varlık ve varlık boolile dizi dizini olarak kullanılabilecek bir değere yükseltir .true1false0

Bunu daha sonra diğer mantıksal işlemlere genişletebiliriz:

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

Şimdi bunların hepsinin bir dezavantajı, ön ek notasyonu gerektirmesidir.

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

ve şimdi yazabilirsiniz true *OR* falseve çalışır.

Yukarıdaki teknik, bağımsız değişken bağımlı aramayı destekleyen bir dili ve şablonları gerektirir. Muhtemelen bunu jenerik ve ADL ile bir dilde yapabilirsiniz.

Bir kenara, *OR*kümelerle çalışmak için yukarıdakileri uzatabilirsiniz . Basitçe invokeaynı ad alanında ücretsiz bir fonksiyon oluşturun 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;
}

ve şimdi set *OR* setikisinin birliğini döndürür.


0

Bu bana karakteristik işlevleri hatırlıyor:

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

Bu sadece, booleanları (1, 0) olarak kabul edebilen diller için geçerlidir. Boolean bir sınıf olduğundan Smalltalk veya Python için geçerli değildir. Smalltalk'ta daha da ileri gidiyorlar (bu bir yalancı kodla yazılacak):

False::or(a)
    return a

True::or(a)
    return self

Ve ikili yöntemler için var ve:

False::and(a)
    return self

True::and(a)
    return a

Bu yüzden "mantık" OP deyiminde tamamen geçerli, ancak ayrıntılı olduğunu belirtti. Dikkat et, fena değil. Örneğin bir matrise dayanan matematiksel bir operatör gibi davranan bir işleve ihtiyacınız varsa mükemmeldir. Diğerleri gerçek bir küp uygular (Quine-McCluskey ifadesi gibi):

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

Ve değerlendireceksin ya da [a] [b]

Bu yüzden evet, buradaki her mantık geçerlidir (dilin VEYA operatörünü xDDDDDDDD kullanarak yazdığı hariç).

Ama en sevdiğim şey DeMorgan yasası: !(!a && !b)


0

Swift standart kütüphanesi bak ve kısayol YA ve kısayol VE operasyonların bunların uygulanmasını kontrol yok gerekli değilse ikinci işleci de / izin verdi.


-2

Mantık tamamen doğru, ancak basitleştirilebilir:

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

Muhtemelen dilinizin bir OR operatörü de vardır - sorunun ruhuna aykırı değilse - neden olmasın

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 }Daha da iyisi return arg1 = True or arg2 = True. if condition then true else falsegereksizdir.
Doval

4
Asker, taleplerinin "operatörün kendisini kullanmadan" olduğuna dikkat çekti
gnat

2
Ben böyle bir şey demedim. Kastettiğim şey buydu, ama soru düzelene kadar bunu söylemedi ve o şekilde cevap verdi.
logicNoob
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.