Miksi 0 on väärä?

Tämä kysymys saattaa kuulostaa tyhmältä, mutta miksi 0 arvioidaan false ja mikä tahansa muu [kokonaisluku] -arvo arvoon true on suurin osa ohjelmointikielistä?

Merkkijonojen vertailu

Koska kysymys näyttää olevan vähän liian yksinkertainen, selitän itselleni hieman enemmän: ensinnäkin se saattaa tuntua ilmeiseltä jokaiselle ohjelmoijalle, mutta miksi ei olisi ohjelmointikieliä – niitä voi olla, mutta ei yhtään, mitä käytin – missä 0 arvioi true ja kaikki muut [kokonaisluku] -arvot false? Se yksi huomautus saattaa tuntua satunnaiselta, mutta minulla on muutama esimerkki siitä, että se on voinut olla hyvä idea. Ensinnäkin, ottakaamme esimerkkinä merkkijonot kolmisuuntaisesta vertailusta, otan C ”s strcmp esimerkkinä: jokaisella ohjelmoijalla, joka yrittää C: tä äidinkielenä, voi olla houkutus kirjoittaa seuraava koodi:

Koska strcmp palauttaa 0 joka arvioi false -arvoksi, kun merkkijonot ovat tasa-arvoiset, aloitusohjelmoija yritti epäonnistua surkeasti ja yleensä ei aluksi ymmärrä miksi. Jos sen sijaan 0 olisi arvioitu arvoon true, tätä toimintoa olisi voitu käyttää sen yksinkertaisimmassa lausekkeessa – yllä olevassa – kun verrataan tasa-arvoa, ja -1 – ja 1 -tarkastukset olisi tehty vain tarvittaessa. Olisimme pitäneet palautustyyppiä bool (mielessämme tarkoitan) suurimman osan ajasta.

Otetaan lisäksi käyttöön uusi tyyppi, sign, joka vain ottaa arvot -1, 0 ja 1. Se voi olla aika kätevä. Kuvittele, että C ++: ssa on avaruusalusoperaattori ja haluamme sen kohteelle std::string (no, jo compare -toiminto on jo olemassa, mutta avaruusalusoperaattori on hauskempaa). Ilmoitus olisi tällä hetkellä seuraava:

 sign operator<=>(const std::string& lhs, const std::string& rhs);  

Olisiko 0 arvioitu arvoon true, avaruusaluksen operaattoria ei edes olisi olemassa, ja olisimme voineet julistaa operator== näin:

 sign operator==(const std::string& lhs, const std::string& rhs);  

Tämä operator== ovat käsitelleet kolmisuuntaista vertailua kerralla, ja niitä voidaan silti käyttää seuraavan tarkistuksen suorittamiseen samalla, kun he pystyvät kuitenkin tarkistamaan, mikä merkkijono on leksikografisesti parempi kuin toinen:

 if (str1 == str2) { // Do something... }  

vanhojen virheiden käsittely

Meillä on nyt poikkeuksia, joten tämä osa koskee vain vanhoja kieliä, joissa sellaista ei ole olemassa (esimerkiksi C). Jos katsomme C: n vakiokirjastoa (ja myös POSIX-kirjastoa), voimme varmasti nähdä, että maaaaany-funktiot palauttavat onnistuneesti 0 ja muuten kokonaisluvut. Olen valitettavasti nähnyt joitain ihmisiä tee tällaisia asioita:

 #define TRUE 0 // ... if (some_function() == TRUE) { // Here, TRUE would mean success... // Do something }  

Jos ajattelemme, miten ajattelemme Ohjelmoinnissa meillä on usein seuraava päättelymalli:

 Do something Did it work? Yes -> That"s ok, one case to handle No -> Why? Many cases to handle  

Jos ajattelemme jälleen kerran, olisi ollut järkevää laittaa ainoa neutraali arvo 0 arvoon yes (ja ”miten C” s funktiot toimivat), kun taas kaikki muut arvot voivat olla käytettävissä ratkaisemaan no -tapaukset. Kuitenkin kaikilla tuntemillani ohjelmointikielillä (paitsi joitain kokeellisia esoteerisia kieliä), että yes arvioi false -tilan if -tilassa, wh kaikki no -tapaukset arvioidaan true -arvoksi. On monia tilanteita, joissa ”se toimii” edustaa yhtä tapausta, kun taas ”se ei toimi” edustaa monia todennäköisiä syitä. Jos ajattelemme sitä tällä tavalla, 0 -arviointi true -arvoksi ja loput false olisi ollut paljon järkevämpää.

Päätelmä

Johtopäätökseni on lähinnä alkuperäinen kysymykseni: miksi suunnittelimme kieliä, joissa false ja muut arvot ovat true, ottaen huomioon muutamat yllä olevat esimerkkini ja ehkä joitain muita, joita en ajatellut?

Seuranta: On mukavaa nähdä, että on monia vastauksia, joissa on monia ideoita ja niin monta mahdollista syytä Rakastan kuinka intohimoisesti näytät olevan siitä.Esitin alun perin tämän kysymyksen kyllästyneisyydestä, mutta koska näytät niin intohimoiselta, päätin mennä hieman pidemmälle ja kysyä Boolen valinnan syistä 0 ja 1 Math.SE: ssä 🙂

Kommentit

  • strcmp() ei ole hyvä esimerkki tosi tai väärä, koska se palauttaa 3 erilaista arvoa. Ja olet yllättynyt, kun aloitat kuoren käytön, jossa 0 tarkoittaa totta ja mikä tahansa muu tarkoittaa väärää.
  • @ ott–: Unix-kuoreissa 0 tarkoittaa menestystä ja muuta -zero tarkoittaa epäonnistumista – ei aivan samaa kuin ” true ” ja ” false ”.
  • @KeithThompson: In Bash (ja muut kuoret), ” menestys ” ja ” epäonnistuminen ” ovat todella samat kuin ” true ” ja ” false ”. Tarkastellaan esimerkiksi lausetta if true ; then ... ; fi, jossa true on komento, joka palauttaa nollan ja tämä kertoo if suoritettavaksi ....
  • Laitteistossa ei ole yhtään booleaania, vain binääriluvut, ja useimmissa historiallisissa ISA-luvuissa pidetään lukua, joka ei ole nolla. nimellä ” true ” kaikissa ehdollisissa haaroitusohjeissa (elleivät ne ’ käytä lippuja sen sijaan). Joten matalan tason kielet ovat kaikin keinoin velvollisia noudattamaan taustalla olevia laitteisto-ominaisuuksia.
  • @MasonWheeler Boolen-tyypin saaminen ei tarkoita mitään ’. Esimerkiksi pythonilla on bool -tyyppi, mutta vertailut / jos olosuhteilla jne. Voi olla palautusarvo.

Vastaus

0 on false, koska molemmat nolla elementtiä yhteisissä seminaareissa . Vaikka ne ovat erillisiä tietotyyppejä, on järkevää muuntaa niiden välillä, koska ne kuuluvat isomorfisiin algebrallisiin rakenteisiin.

  • 0 on identiteetti lisäykselle ja nolla kertolaskulle. Tämä pätee kokonaislukuihin ja rationaaliarvoihin, mutta ei IEEE-754 liukuluku: 0.0 * NaN = NaN ja 0.0 * Infinity = NaN .

  • false on Boolen xor (⊻) identiteetti ja nolla Boolen ja (∧). Jos Boolean edustaja on {0, 1} – kokonaislukujoukko modulo 2 -, voit ajatella, että addition on lisäys ilman kantoa ja ∧ kuin kertolasku.

  • "" ja [] ovat identiteetti ketjutuksessa, mutta on olemassa useita toimintoja, joille ne ovat järkeviä kuin nollat. Toisto on yksi, mutta toistaminen ja ketjutus eivät levitä, joten nämä toiminnot eivät muodosta semiringia.

Tällaiset implisiittiset muunnokset ovat hyödyllisiä pienissä ohjelmissa, mutta suurissa voi tehdä ohjelmista vaikeampia päättää. Vain yksi monista kielisuunnittelun kompromisseista.

Kommentit

  • Hienoa, että mainitsit luettelot. (BTW, nil on sekä tyhjä luettelo [] että false -arvo Common Lisp -ohjelmassa ; onko taipumusta yhdistää identiteettejä eri tietotyypeistä?) Sinun on silti selitettävä, miksi on luonnollista pitää väärää additiivisena identiteettinä ja totta multiplikatiivisena identiteettinä eikä päinvastoin. Eikö ’ ole mahdollista pitää true -tunnistetta AND ja nollana OR?
  • +1 vastaaviin identiteetteihin viittaamiseksi. Lopuksi vastaus, joka ei ’ t vain kiehua ” -käytäntöön, käsittele sitä ”.
  • +1 antaa tietoja konkreettisesta ja hyvin vanhasta matematiikasta, jossa tätä on noudatettu ja jolla on ollut järkevää merkitystä
  • Tätä vastausta ei ’ t on järkevää. true on myös seminaarien (Boolen ja / tai) identiteetti ja nolla. Ei ole mitään syytä katsoa, että false on lähempänä 0 kuin true.
  • @TonioElGringo: Tosi ja väärä ero on ero XOR: n ja XNOR: n välillä. Isomorfisia renkaita voidaan muodostaa AND / XOR: lla, missä tosi on moninkertaistuva identiteetti ja väärä lisäaine, tai OR: lla ja XNOR: lla, jossa väärä on multiplikatiivinen identiteetti ja tosi on lisäaine, mutta XNOR: a ei yleensä pidetä yleisenä perustoiminta XOR: n tapaan.

Vastaa

Koska matematiikka toimii.

FALSE OR TRUE is TRUE, because 0 | 1 is 1. ... insert many other examples here. 

C-ohjelmilla on perinteisesti ehtoja, kuten

 if (someFunctionReturningANumber())  

pikemminkin kuin

 if (someFunctionReturningANumber() != 0)  

koska nollan käsite, joka vastaa väärää, ymmärretään hyvin.

Kommentit

  • Kielet on suunniteltu siten, koska matematiikalla on järkeä. Se tuli ensin.
  • @Morwenn, se juontaa juurensa 1800-luvulle ja George Boole. Ihmiset ovat edustaneet Vääriä arvona 0 ja Tosi kuin! 0 pidempään kuin tietokoneita on ollut.
  • En ymmärrä, miksi matematiikka ei ole ’ ei toimi toisin, jos vain muutat kaikkia määritelmiä niin, että AND on + ja OR on *.
  • Aivan: matematiikka toimii molemmilla tavoilla ja vastaus tämä kysymys näyttää olevan puhtaasti tavanomainen.
  • @Robert Se on ’ d hyvä, jos voisit sanoa ” matemaattinen tausta ” viestissäsi.

Vastaa

Kuten muut ovat sanoneet, matematiikka oli etusijalla. Siksi 0 on false ja 1 on true.

Mistä matematiikasta puhumme? Boolen algebrat , jotka ovat peräisin 1800-luvun puolivälistä, kauan ennen digitaalisten tietokoneiden tuloa.

Voit myös sanoa, että käytäntö tuli -loogiselta , joka on jopa vanhempi kuin loogiset algebrat. Tämä muodostaa suuren määrän loogisia tuloksia, jotka ohjelmoijat tuntevat ja rakastavat (false || x on yhtä suuri kuin x, true && x on yhtä suuri kuin x ja niin edelleen).

Pohjimmiltaan puhumme aritmeettisesta joukosta, jossa on kaksi elementtiä. Ajattele laskemista binäärisenä. Boolen algebrat ovat tämän käsitteen ja sen teoreettisen perustan lähtökohta. C-tyyppisten kielten yleissopimukset ovat vain yksinkertainen sovellus.

Kommentit

  • Voisit , varmasti. Mutta sen pitäminen ” vakio ” -tyylillä sopii hyvin yleiseen aritmeettiin (0 + 1 = 1, ei 0 + 1 = 0).
  • Kyllä, mutta oletettavasti kirjoittaisit AND +: lla ja OR: lla *: llä, jos käännät määritelmät myös päinvastoin.
  • Matematiikka ei ’ ei tule ensin. Math tunnisti, että 0 ja 1 muodostavat kentän, jossa AND on kuin kertolasku ja OR on kuin summaus.
  • @ Kaz: Mutta {0, 1} OR: lla ja AND: llä ei muodosta kenttää.
  • Minua häiritsee vähän, että useammissa vastauksissa ja kommenteissa sanotaan, että true = 1. Se ’ ei ole aivan tarkka, koska true != 0, joka ei ole aivan sama. Yksi syy (ei ainoa), miksi tulisi välttää vertailuja, kuten if(something == true) { ... }.

Vastaa

Luulin, että tämä liittyi elektroniikan ”perintöön” ja myös loogiseen algebraan, jossa

  • 0 = off, negative, no, false
  • 1 = on, positive, yes, true

strcmp palauttaa arvon 0, kun merkkijonot ovat tasa-arvoisia, on tekemistä sen kanssa, koska se tosiasiallisesti laskee kahden merkkijonon välisen etäisyyden. Se, että myös 0 pidetään vääränä, on vain sattumaa.

0 palauttaminen menestykseen on järkevää koska 0 tarkoittaa tässä tapauksessa ei virhettä ja mikä tahansa muu numero olisi virhekoodi. Minkä tahansa muun numeron käyttäminen menestykseen ei olisi järkevää, koska sinulla on vain yksi onnistumiskoodi, kun taas sinulla voi olla useita virhekoodeja. Käytit ”toimiiko se?” ikään kuin jos lauseke-lauseke ja sano 0 = kyllä, olisi järkevämpää, mutta lauseke on oikeampi ”Menikö pieleen?” ja sitten näet, että 0 = ei on paljon järkeä. Ajatuksella false/true ei ole tässä mitään järkeä, koska se on no error code/error code.

Kommentit

  • Haha, olet ensimmäinen, joka ilmoitti palautusvirhekysymyksen yksiselitteisesti. Tiesin jo, että tulkitsin sen omalla tavallani ja voisin kysyä toisin, mutta sinä ’ ilmaisit ensimmäisenä sen nimenomaisesti (monista vastauksista ja kommenteista).Itse asiassa en sanoisi, että ’ ei sanoisi, että yhdellä tai toisella tavalla ei ole mitään järkeä, mutta enemmän molemmilla on merkitystä eri tavoin 🙂
  • Itse asiassa ’ d sano 0 kohteelle success/no error on ainoa järkevä asia, kun muut kokonaisluvut edustavat virhekoodeja . Se, että 0 myös satunnaisesti edustaa false muissa tapauksissa, ei ole merkitystä, koska emme ’ puhu totta tai väärää täällä lainkaan;)
  • Minulla oli sama idea, joten korostin
  • mielipiteesi strcmp() etäisyyden laskeminen on melko hyvä. Jos sitä olisi kutsuttu nimellä strdiff(), if (!strdiff()) olisi hyvin loogista.
  • ” elektroniikka […] jossa 0 = […] väärä, 1 = […] tosi ” – jopa elektroniikassa tämä on vain yleissopimus , ja se ei ole ’ t ainoa. Kutsumme tätä positiiviseksi logiikaksi, mutta voit käyttää myös negatiivista logiikkaa, jossa positiivinen jännite osoittaa väärän ja negatiivinen tosi. Sitten piiristä, jota ’ käytät AND: lle, tulee OR, OR muuttuu AND ja niin edelleen. De Morganin ’ lain vuoksi se kaikki päätyy vastaavuuteen. Joskus ’ löydät osan elektronisesta piiristä, joka on toteutettu negatiivisessa logiikassa helppokäyttöisyyden vuoksi, jolloin kyseisen osan signaalien nimet merkitään niiden yläpuolella olevalla palkkilla.

vastaus

Kuten tässä artikkelissa selitetään , arvoja false ja true ei pidä sekoittaa kokonaislukuihin 0 ja 1, mutta ne voidaan tunnistaa Galois-kentän elementeillä (äärellinen kenttä) kahdesta elementistä (katso täällä ).

Kenttä on joukko, jossa on kaksi operaatiota, jotka täyttävät tietyt aksioomat.

Symboleita 0 ja 1 käytetään tavallisesti kentän additiivisten ja kerrottavien identiteettien osoittamiseen, koska reaaliluvut ovat myös kenttä (mutta ei äärellinen), jonka identiteetit ovat numeroita 0 ja 1.

Lisäaineen identiteetti on kentän elementti 0, joka on kaikille x: lle:

x + 0 = 0 + x = x 

ja multiplikatiivinen identiteetti on kentän elementti 1 siten, että kaikille x:

x * 1 = 1 * x = x 

Kahden elementin äärellisessä kentässä on vain nämä kaksi elementtiä, nimittäin additiivinen identiteetti 0 (tai false) ja kerrannaisidentiteetti 1 (tai true). Tämän kentän kaksi operaatiota ovat looginen XOR (+) ja looginen AND (*).

Huom. Jos käännät operaatioita (XOR on kertolasku ja AND on summaus), kertolasku ei ole jakautuva summauksen yli eikä sinulla ole enää kenttää. Tällöin sinulla ei ole syytä kutsua kahta elementtiä 0 ja 1 (missä tahansa järjestyksessä). Huomaa myös, että et voi valita operaatiota TAI XOR: n sijasta: riippumatta siitä, miten tulkitset TAI / JA lisäykseksi / kertolaiseksi, tuloksena oleva rakenne ei ole kenttä (kaikkia käänteisiä elementtejä ei ole kenttäaksioomien vaatimalla tavalla).

Mitä tulee C-funktioihin:

  • Monet toiminnot palauttavat kokonaisluvun, joka on virhekoodi. 0 tarkoittaa EI VIRHEÄ.
  • Intuitiivisesti funktio strcmp laskee kahden merkkijonon eron. 0 tarkoittaa, että kahden merkkijonon välillä ei ole eroa, eli että kaksi merkkijonoa ovat samat.

Yllä olevat intuitiiviset selitykset voivat auttaa muistamaan palautusarvojen tulkinnan, mutta sitä on vielä helpompaa tarkista vain kirjaston dokumentaatio.

Kommentit

  • +1 osoittaaksesi, että jos vaihdat mielivaltaisesti, matematiikka ei enää toimi.
  • Käännetty: Kun annetaan kenttä, jossa on kaksi elementtiä ja operaatiot * ja +, tunnistamme True arvoksi 0 ja False luvulle 1. Tunnistamme TAI *: lla ja XOR +: lla.
  • Tulet huomaamaan, että molemmat näistä tunnistuksista tehdään samalla kentällä ja molemmat ovat Boolen logiikan sääntöjen mukaisia. Muistiinpanosi on valitettavasti virheellinen 🙂
  • Jos oletat, että True = 0 ja XOR on +, True-arvon on oltava XOR: n identiteetti. Mutta se ei johdu siitä, että True XOR True = False. Ellet määritä uudelleen operaatiota XOR True-arvossa niin, että True XOR True = True. Sitten tietysti rakennustyösi toimii, koska olet juuri nimittänyt asioita uudelleen (missä tahansa matemaattisessa rakenteessa voit aina onnistuneesti tehdä nimipermutaation ja saada isomorfisen rakenteen). Toisaalta, jos annat True, False ja XOR: lla olevan tavanomainen merkityksensä, True XOR True = False and True ei voi olla additiivinen identiteetti, eli True ei voi olla 0.
  • @Giorgio: Korjasin rakenteen kommenttisi mukaan viimeisessä kommentissani…

Vastaa

Ota huomioon, että vaihtoehtoiset järjestelmät voivat olla myös hyväksyttäviä suunnittelupäätöksiä.

Kuoret: 0-poistumistila on tosi, ei-nolla on väärä

Esimerkki kuorista, jotka käsittelevät 0 exit status as true on jo mainittu.

 $ ( exit 0 ) && echo "0 is true" || echo "0 is false" 0 is true $ ( exit 1 ) && echo "1 is true" || echo "1 is false" 1 is false  

Syynä tähän on On yksi tapa menestyä, mutta monia tapoja epäonnistua, joten 0: n käyttö erityisarvona, joka tarkoittaa ”ei virheitä”, on käytännöllistä.

Ruby: 0 on aivan kuten mikä tahansa muu numero

Normaalien ohjelmointikielien joukossa on joitain poikkeavuuksia, kuten Ruby, jotka käsittelevät 0 todellisena arvona.

$ irb irb(main):001:0> 0 ? "0 is true" : "0 is false" => "0 is true" 

perustelu on, että vain false ja nil pitäisi olla vääriä. Monille Ruby-aloittelijoille se on todella hyvä. Joissakin tapauksissa on kuitenkin hienoa, että 0: ta kohdellaan aivan kuten kaikkia muita numeroita.

irb(main):002:0> (pos = "axe" =~ /x/) ? "Found x at position #{pos}" : "x not found" => "Found x at position 1" irb(main):003:0> (pos = "xyz" =~ /x/) ? "Found x at position #{pos}" : "x not found" => "Found x at position 0" irb(main):004:0> (pos = "abc" =~ /x/) ? "Found x at position #{pos}" : "x not found" => "x not found" 

, tällainen järjestelmä toimii vain kielellä, joka pystyy erottamaan booleanit erillisenä tyypinä numeroista. Aikaisempina laskentapäivinä ohjelmointikielillä tai konekielellä työskentelevillä ohjelmoijilla ei ollut tällaista ylellisyyttä. On luultavasti aivan luonnollista kohdella 0 ”tyhjänä” tilana ja asettaa vähän arvoksi 1 lipuksi, kun koodi havaitsi jotain tapahtuneen. Laajennettuna käytäntö kehitti, että nollaa pidettiin vääränä, ja nollan ulkopuolisia arvoja pidettiin tosi. Sen ei kuitenkaan tarvitse olla tuolla tavalla.

Java: Numeroita ei voida ollenkaan käsitellä booleina

Java-käyttöjärjestelmässä true ja false ovat ainoat loogiset arvot. Numerot eivät ole loogisia ehtoja, eikä niitä voida edes heittää loogisiin ( Java-kielimääritys, Sec 4.2.2 ):

Integraalityyppien ja tyypin boolean välillä ei ole suoratoistoa .

Tämä sääntö vain välttää kysymyksen kokonaan – kaikki loogiset lausekkeet on kirjoitettava nimenomaisesti koodiin.

Kommentit

  • Rebol ja Red käsittelevät molemmat 0-arvoisia INTEGER! -arvoja tosi, ja niillä on erillinen NONE! -tyyppi (vain yhdellä arvolla, EI MITÄÄN) käsitellään ehdollisena vääränä LOGIC! false -arvon lisäksi. Olen ’ löytänyt huomattavaa turhautumista yrittäessäni kirjoittaa JavaScript-koodi, joka käsittelee 0 väärin; se on lisäys syötävä kömpelö päätös dynaamisesti kirjoitetulle kielelle. Jos haluat testata jotain, joka voi olla nolla tai nolla, sinun on kirjoitettava if (thing === 0), se ei ole hienoa.
  • @HostileFork En halua ’ ei tiedä. Minusta on järkevää, että 0 on true (kuten kaikki muutkin kokonaisluvut) dynaamisessa kielessä. Sain joskus sattua 0, kun yritin saada kiinni None Pythonissa, ja sitä voi joskus olla melko vaikea havaita.
  • Rubiini ei ole poikkeava. Ruby ottaa tämän Lispiltä (Ruby on jopa salaa nimeltään ” MatzLisp ”). Lisp on tietotekniikan valtakieli. Nolla on myös vain oikea arvo POSIX-kuoressa, koska se ’ s on teksti: if [ 0 ] ; then echo this executes ; fi. Väärien tietojen arvo on tyhjä merkkijono, ja testattava vääryys on epäonnistunut komennon lopetustila, jota edustaa non -nolla.

Vastaa

Ennen kuin käsittelemme yleistä tapausta, voimme keskustella vastaesimerkkeistäsi.

Merkkijonovertailut

Sama pätee itse asiassa monenlaisiin vertailuihin. Tällaiset vertailut laskevat kahden kohteen välisen etäisyyden . Kun kohteet ovat samat, etäisyys on minimaalinen. Joten kun ”vertailu onnistuu”, arvo on 0. Mutta oikeastaan strcmp: n palautusarvo ei ole looginen, se on etäisyys ja että mikä ansaitsee tietämättömät ohjelmoijat tekemässä if (strcmp(...)) do_when_equal() else do_when_not_equal().

C ++: ssa voimme suunnitella uudelleen strcmp palauttamaan Distance -objekti, joka ohittaa operator bool() -arvon ja palauttaa arvon tosi, kun 0 (mutta muut ongelmat purevat sinua). Tai tavallisessa C: ssä on vain streq -funktio, joka palauttaa 1, kun merkkijonot ovat samat, ja 0 muuten.

API-puhelut / ohjelman poistumiskoodi

Täällä välität syystä, miksi jokin meni pieleen, koska se ajaa päätökset virheellisesti. Kun asiat onnistuvat, et halua tietää mitään erityistä – aikomuksesi toteutuu. Siksi palautusarvon on välitettävä tämä tieto.Se ei ole looginen, se on virhekoodi. Erityinen virhearvo 0 tarkoittaa ”ei virhettä”. Loppuosa edustaa paikallisesti merkityksellisiä virheitä, joita sinun on käsiteltävä (mukaan lukien 1, mikä tarkoittaa usein ”määrittelemätöntä virhettä”).

Yleinen tapaus

Tästä jää kysymys: miksi loogiset arvot ovat True ja False edustettuina yleisesti 1: llä ja 0: lla?

No, subjektiivisen ”tuntuu paremmalta tällä tavalla” -argumentin lisäksi tässä on muutama syy (myös subjektiivinen), joita voin ajatella:

  • sähköpiirien analogia. Virta on päällä 1 sekunnin ajan ja POIS 0 sekunnin ajan. Haluan, että (1, Kyllä, Tosi, Päällä) on yhdessä ja (0, Ei, Epätosi, Pois), eikä toinen sekoitus

  • muistin alustus. Kun memset(0) joukko muuttujia (olkoon ne intoja, kellukkeita, booleja), haluan niiden arvon vastaavan konservatiivisimpia oletuksia. Esimerkiksi. summani on lähtökohtaisesti 0, predikaatti on väärä jne.

Ehkä kaikki nämä syyt ovat sidoksissa koulutukseeni – jos minua olisi opetettu liittämään 0 todellisen alussa, menisin päinvastoin.

Kommentit

  • Itse asiassa on ainakin yksi ohjelmointikieli, joka pitää 0: ta tosi. Unix-kuori.
  • +1 todellisen ongelman ratkaisemiseksi: Suurin osa Morwenn ’ -kysymyksistä ei ole ’ t noin bool.
  • @ dan04 Se on. Koko viesti kertoo syistä valinnan valitsemiseen ryhmästä int bool monilla ohjelmointikielillä. Vertailu ja virheviestit ovat vain esimerkkejä paikoista, joissa sen lähettämisellä muulla kuin tällä hetkellä ’ tekemällä tavalla olisi järkevää.

vastaus

Korkean tason näkökulmasta puhut kolmesta melko erilaisesta tietotyypistä:

  1. Totuusarvo. Boolen algebran matemaattinen käytäntö on käyttää arvoa 0 merkinnällä false ja arvoa true, joten on järkevää noudattaa tätä käytäntöä. Luulen, että tällä tavalla on järkevämpää myös intuitiivisesti.

  2. Vertailun tulos. Tämä on kolme arvoa: <, = ja > (huomaa, ettei yksikään niistä ole true). Heille on järkevää käyttää arvoja -1, 0 ja 1 (tai yleisemmin negatiivinen arvo, nolla ja positiivinen arvo).

    Jos haluat tarkistaa tasa-arvon a Ja sinulla on vain toiminto, joka suorittaa yleisen vertailun, mielestäni sinun pitäisi tehdä se nimenomaiseksi käyttämällä jotain strcmp(str1, str2) == 0. Mielestäni ! -sovelluksen käyttäminen tässä tilanteessa on hämmentävää, koska se käsittelee muuta kuin loogista arvoa kuin se olisi looginen.

    Muista myös, että vertailu ja tasa-arvon ei tarvitse olla sama asia. Jos esimerkiksi tilaat ihmisiä heidän syntymäpäivänsä mukaan, Compare(me, myTwin) pitäisi palauttaa 0 , mutta Equals(me, myTwin) pitäisi palauttaa false.

  3. Funktion onnistuminen tai epäonnistuminen , mahdollisesti myös yksityiskohtia tuosta onnistumisesta tai epäonnistumisesta. Jos puhut Windowsista, tätä tyyppiä kutsutaan nimellä HRESULT ja nollasta poikkeava arvo ei välttämättä tarkoita epäonnistumista. Itse asiassa negatiivinen arvo tarkoittaa epäonnistumista ja ei-negatiivista menestystä. Menestysarvo on hyvin usein S_OK = 0, mutta se voi olla myös esimerkiksi S_FALSE = 1 tai muita arvoja.

Sekaannus johtuu tosiasiasta että kolme loogisesti melko erilaiset tietotyypit esitetään itse asiassa yhtenä tietotyyppinä (kokonaisluku) C: llä ja joillakin muilla kielillä ja että voit käyttää kokonaislukua ehdossa. Mutta en usko, että olisi järkevää määritellä looginen logiikka uudelleen, jotta joidenkin ei-boolean tyyppien käyttö olosuhteissa olisi yksinkertaisempaa.

Harkitse myös toista tyyppiä, jota käytetään usein C-tilassa: osoitin . Siellä on luonnollista kohdella NULL -osoitinta (jota edustaa nimellä 0) false. Joten ehdotuksenne noudattaminen vaikeuttaisi myös osoittimien käsittelyä. (Vaikka henkilökohtaisesti haluan mieluummin verrata osoittimia nimenomaisesti NULL: een sen sijaan, että niitä kohdellaan booleanina.)

Vastaus

Nolla voi olla väärä, koska useimmilla suorittimilla on ZERO-lippu, jota voidaan käyttää haarautumiseen. Se tallentaa vertailutoiminnon.

Katsotaan miksi.

Jotkut psuedokoodit, koska yleisö luultavasti ei lue kokoonpanoa

c- lähdekoodin yksinkertaiset silmukakutsuja heiluttaa 10 kertaa

 for (int foo =10; foo>0; foo-- ) /* down count loop is shorter */ { wibble(); }  

joku teeskentelee kokoonpanoa tälle

0x1000 ld a 0x0a "foo=10 0x1002 call 0x1234 "call wibble() 0x1005 dec a "foo-- 0x1006 jrnz -0x06 "jump back to 0x1000 if not zero 0x1008 

c- lähde toinen yksinkertainen silmukka kutsuu wibble 10 kertaa

 for (int foo =0; foo<10; foo-- ) /* up count loop is longer */ { wibble(); }  

jotkut teeskentelevät kokoonpanoa tälle tapaukselle

0x1000 ld a 0x00 "foo=0 0x1002 call 0x1234 "call wibble() 0x1005 dec a "foo-- 0x1006 cmp 0x0a "compare foo to 10 ( like a subtract but we throw the result away) 0x1008 jrns -0x08 "jump back to 0x1000 if compare was negative 0x100a 

lisää c-lähdettä

 int foo=10; if ( foo ) wibble()  

ja kokoonpano

0x1000 ld a 0x10 0x1002 jz 0x3 0x1004 call 0x1234 0x1007 

näet kuinka lyhyt se on?

lisää c-lähdettä

 int foo=10; if ( foo==0 ) wibble()  

ja kokoonpano (oletetaan marginaalisesti älykäs kääntäjä, joka voi korvata == 0 ilman vertailua )

0x1000 ld a 0x10 0x1002 jz 0x3 0x1004 call 0x1234 0x1007 

Kokeillaan nyt true = 1 -käytäntöä.

Lisää c-lähdettä #define TRUE 1 int foo = TRUE; jos (foo == TOSI) wibble ()

ja kokoonpano

0x1000 ld a 0x1 0x1002 cmp a 0x01 0x1004 jz 0x3 0x1006 call 0x1234 0x1009 

näet, kuinka lyhyt tapaus, jossa nolla ei ole tosi?

Todella varhaisessa suorittimessa oli pieniä lippusarjoja kiinnitettynä akkuun.

Jos haluat tarkistaa, onko a> b tai a = b yleensä vertailukäsky.

  • Ellei B ole joko ZERO – tällöin ZERO-lippu asetetaan Toteutetaan yksinkertaiseksi loogiseksi NOR: ksi tai akun kaikille biteille.
  • Tai NEGATIIVINEN, jossa käytetään vain ”merkkibittiä” eli akun merkittävintä bittiä jos käytät kahden komplementtiaritmeettistä arvoa. (Enimmäkseen me teemme)

Toistetaan tämä. Joissakin vanhemmissa suorittimissa sinun ei tarvinnut käyttää vertailukäskyä akulle, joka on nolla, tai akulle, joka on pienempi kuin nolla.

Näetkö nyt, miksi nolla voi olla väärä?

Huomaa, että tämä on psuedo-koodi, eikä mikään oikea käskyjoukko näytä tältä. Jos tiedät kokoonpanon, tiedän, että yksinkertaistan asioita paljon täällä. Jos tiedät jotain kääntäjän suunnittelusta, sinun ei tarvitse lukea tätä vastausta. Jokainen, joka tietää jotain silmukan purkamisesta tai haaroitusennusteesta, edistynyt luokka on käytävällä huoneessa 203.

Kommentit

  • Sinun mielipiteesi ei ole oikein esitetty tässä, koska yksi asia if (foo) ja if (foo != 0): n tulisi luoda sama koodi, ja toiseksi ’ osoitat uudelleen, että käyttämäsi kokoonpanokieli ’ on itse asiassa nimenomainen loogiset operandit ja testit niille. Esimerkiksi jz tarkoittaa jump if zero. Toisin sanoen if (a == 0) goto target; Ja määrää ei edes testata suoraan; ehto muunnetaan sen loogiseksi lipuksi, joka on tallennettu erityiseen konesanaan. Se ’ on oikeastaan enemmän kuin cpu.flags.zero = (a == 0); if (cpu.flags.zero) goto target;
  • Ei Kaz, vanhempi suoritin ’ ei toiminut näin. T jz / jnz voidaan suorittaa ilman vertailukäskyjä. Mikä oli oikeastaan koko viestini asia.
  • En ’ kirjoittanut mitään vertailuohjeesta.
  • Voitko mainitse prosessori, jolla on jz -käsky, mutta ei jnz? (tai mikä tahansa muu epäsymmetrinen ehdollisten ohjeiden joukko)

vastaus

On paljon vastauksia, jotka viittaavat siihen Joidenkin matemaattisten ominaisuuksien vuoksi vaaditaan vastaavuus 1: n ja todellisen välillä. En löydä sellaista ominaisuutta ja ehdotan, että se on puhtaasti historiallinen käytäntö.

Kun otetaan huomioon kenttä, jossa on kaksi elementtiä, meillä on kaksi operaatiota: summaus ja kertolasku. Voimme kartoittaa Boolen operaatiot tällä kentällä kahdella tavalla :

Perinteisesti tunnistamme True-arvon 1: llä ja False-arvon 0. Tunnistamme AND-merkin *: llä ja XOR +: lla. Täten OR on kyllästävä lisäys.

Voisimme kuitenkin yhtä helposti identifioi True 0: lla ja False 1: llä. Sitten tunnistamme OR: n *: llä ja XNOR +: lla. AND on siis kyllästävä lisäys.

Kommentit

  • Jos olit seurannut wikipedian linkkiä, voisit huomata, että boolen algebran käsite on suljettu kahden elementin Galois-kentän ( fi.wikipedia.org/wiki) käsitteen kanssa. / GF% 282% 29 ). Symboleita 0 ja 1 käytetään tavanomaisesti vastaavien additiivisten ja multiplikatiivisten identiteettien osoittamiseen, koska reaaliluvut ovat myös kenttä, jonka identiteetit ovat numeroita 0 ja 1.
  • @NeilG Luulen, että Giorgio yrittää sanoa sen ’ enemmän kuin vain yleissopimus. Boolen algebran 0 ja 1 ovat pohjimmiltaan samat kuin 0 ja 1 GF: ssä (2), jotka käyttäytyvät melkein samalla tavalla kuin 0 ja 1 reaalilukuina summauksen ja kertomisen suhteen.
  • @svick: Ei , koska voit yksinkertaisesti nimetä kertolasku ja kyllästyslisäys OR: ksi ja AND: ksi ja kääntää sitten tarrat siten, että 0 on tosi ja 1 väärä.Giorgio sanoo, että se oli Boolen logiikan käytäntö, joka hyväksyttiin tietojenkäsittelyn yleissopimukseksi.
  • @Neil G: Ei, et voi kääntää + ja * ja 0 ja 1, koska kenttä vaatii jakamista kertomalla lisäys (katso fi.wikipedia.org/wiki/Field_%28mathematics%29 ), mutta jos asetat +: = AND ja *: = XOR , saat T XOR (T JA F) = T XOR F = T, kun taas (T XOR T) JA (T XOR F) = F JA T = F. Siksi kääntämällä operaatioita ja identiteettejä sinulla ei ole kenttää enää. Joten IMO, joka määrittelee 0 ja 1 sopivan kentän identiteeteiksi, näyttää sieppaavan väärän ja totta melko uskollisesti.
  • @giorgio: Olen muokannut vastausta tekemään selväksi, mitä tapahtuu.

vastaus

Kummallista kyllä, nolla ei ole aina väärä.

Erityisesti Unix- ja Posix-käytäntö on määritellä EXIT_SUCCESS arvoksi 0 (ja EXIT_FAILURE arvoksi 1). Itse asiassa se on jopa tavallinen C-yleissopimus !

Joten Posix-kuorille ja -poistumiselle (2) syscalls, 0 tarkoittaa ”onnistunutta”, joka on intuitiivisesti enemmän totta kuin epätosi.

Erityisesti kuori ”s if haluaa prosessin palautus EXIT_SUCCESS (eli 0) sen ”sitten” -haaran seuraamiseksi!

Kaaviossa (mutta ei Common Lisp: ssä tai MELT ) 0 ja nolla (ts. () kaaviossa) ovat totta, koska ainoa väärä arvo on #f

Olen samaa mieltä, olen nokkela!

Vastaa

C: tä käytetään matalan tason ohjelmointiin lähellä laitteistoa, alueella, jolla sinun on joskus vaihdettava bitti- ja loogisten operaatioiden välillä samoilla tiedoilla.Se, että vaaditaan muuntaa numeerinen lauseke loogiseksi vain testin suorittamiseksi, sekaisin koodi.

Voit kirjoittaa esimerkiksi:

 if (modemctrl & MCTRL_CD) { /* carrier detect is on */ }  

pikemminkin kuin

 if ((modemctrl & MCTRL_CD) != 0) { /* carrier detect is on */ }  

Yhdessä yksittäisessä esimerkissä se ei ole niin paha, mutta sen tekeminen saa ikävän.

Samoin keskustele toimintojen kanssa. Boolen operaation, kuten vertailun, tuloksen kannalta on hyödyllistä tuottaa vain 0 tai 1: Oletetaan, että haluamme asettaa jonkin sanan kolmannen bitin sen perusteella, onko modemctrl sisältää kantoaallon havaitsemisbitin:

 flags |= ((modemctrl & MCTRL_CD) != 0) << 2;  

Täällä meillä on oltava != 0, vähentämään kaksisuuntaisen & lausekkeen tulos 0 tai 1, mutta koska tulos on vain kokonaisluku, meillä ei ole tarvetta lisätä ärsyttäviä osia, jotta looginen arvo voidaan muuntaa kokonaisluvuksi.

Vaikka modernilla C: llä on nyt bool -tyyppi, se silti säilyttää tällaisen koodin pätevyyden sekä siksi, että se on hyvä asia, että takia yhteensopivan massiivisen rikkoutumisen vuoksi, joka muuten aiheutuisi.

Toinen esimerkki, jossa C on liukas: kahden loogisen tilan testaaminen nelisuuntaisena kytkimenä:

Tätä ei voitu ottaa pois C-ohjelmoijalta ilman taistelua!

Lopuksi C palvelee joskus eräänlaisena korkean tason kokoonpanokielenä. Kokoonpanokielillä meillä ei myöskään ole loogisia tyyppejä. Totuusarvo on vain bitti tai nolla-arvo nolla-arvo muistipaikassa tai rekisterissä. Kokonaisluku nolla, looginen nolla ja osoite nolla testataan kaikki samalla tavalla kokoonpanokielen käskyjoukoissa (ja ehkä jopa liukuluku nolla). C: n ja kokoonpanokielen välinen samankaltaisuus on hyödyllinen, esimerkiksi kun C: tä käytetään kohdekielenä toisen kielen (jopa sellaisen, jolla on voimakkaasti kirjoitetut booleanit!) Kääntämisessä.

Vastaa

Totuusarvo- tai totuusarvolla on vain 2 arvoa. Tosi ja väärä.

Näiden ei tulisi olla kokonaislukuja, mutta bitteinä (0 ja 1 ).

Muiden kokonaislukujen sanominen 0: n tai 1: n lisäksi ei ole väärä, on hämmentävä lausunto. Totuustaulukot käsittelevät totuusarvoja, ei kokonaislukuja.

Totuusarvon mahdollisesta arvosta -1 tai 2 hajottaisi kaikki totuustaulukot ja kaikki niihin liittyvät boolen logiikat.

  • 0 JA -1 ==?!
  • 0 TAI 2 ==?!

Useimmilla kielillä on yleensä boolean tyyppi, joka valettuun numerotyyppiin, kuten kokonaisluku, paljastaa väärän arvon, syötetään kokonaislukuarvoksi 0.

Kommentit

  • 0 JA -1 == mitä looginen arvo heität heille. Se ’ s, mistä kysymykseni kuuluu, miksi heittää heidät ryhmään TRUE tai FALSE.En koskaan sanonut – ehkä sanoin, mutta sitä ei ollut tarkoitettu – kokonaisluvut olivat totta tai väärää, kysyin, miksi he arvioivat sitä, mihin heidät heitetään loogiseksi.

Vastaus

Viime kädessä puhut ydinkielen rikkomisesta, koska jotkut sovellusliittymät ovat hämmentäviä. Crappy-sovellusliittymät eivät ole uusia, eikä niitä voi korjata rikkomalla kieltä. On matemaattinen tosiasia, että 0 on väärä ja 1 on totta, ja kaikki kielet, jotka eivät kunnioita sitä, ovat periaatteessa rikkoutuneita. Kolmisuuntainen vertailu on kapealla eikä sillä ole yritystä, jonka tulos muunnetaan implisiittisesti bool -iksi, koska se palauttaa kolme mahdollista tulosta. Vanhoilla C-sovellusliittymillä on yksinkertaisesti virheellinen virheenkäsittely ja ne ovat myös vaikeutettuja, koska C: llä ei ole tarvittavia kieliominaisuuksia, jotta sillä ei olisi kauheita käyttöliittymiä.

Huomaa, että en sano sitä kielille, joilla ei ole implisiittisiä kokonaisluku-> looginen muunnos.

Kommentit

  • ” On matemaattinen tosiasia, että 0 on väärä ja 1 on tosi ” Erm.
  • Voitteko mainita viitteen ” matemaattiseen tosiseikkaan, että 0 on väärä ja 1 on tosi ”? Vastauksesi kuulostaa vaaralliselta kuin pilkka.
  • Se ’ ei ole matemaattinen tosiasia, mutta se ’ on ollut matemaattinen käytäntö 1800-luvulta lähtien.
  • Boolen algebraa edustaa rajallinen kenttä, jossa 0 ja 1 ovat identiteettielementtejä operaatioille, jotka muistuttavat additonia ja kertolaskua. Nämä toiminnot ovat vastaavasti OR ja AND. Itse asiassa looginen algebra kirjoitetaan aivan kuten tavallinen algebra, jossa rinnakkaisuus merkitsee AND: ta, ja symboli + tarkoittaa OR. Joten esimerkiksi abc + a'b'c tarkoittaa (a and b and c) or (a and (not b) and (not c)).

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *