Porównanie wielu warunków do jednego

0

Witam. Mam w kodzie coś takiego:

if zmienna1 and stala1 = stala1 then

Czy dobrze rozumiem, że równie dobrze można to zapisać:

if zmienna1 = stala1 then

bo pierwsze wyrażenie można rozumieć jako:

if zmienna1 = stala1 and stala1 = stala1

?

0

Sprawdzasz czy jeden równa się jeden?
To trochę niepotrzebne bo jeden zawsze będzie jeden nie trzeba tego sprawdzać, a dwa zawsze będzie dwa.

0

Nie nie można. to nie jest porównywanie jeden do wielu. Chyba nie ma takiej konstrukcji co szukasz.
Co do kodu to wyobraź sobie iż tam są nawiasy

if (zmienna1) and (stala1 = stala1) then

Więc najpier liczysz co masz w nawiasach i masz

if (zmienna1) and (true) then
5
paranoise napisał(a):

Witam. Mam w kodzie coś takiego:

if zmienna1 and stala1 = stala1 then

To co widać powyżej to typowy test czy zmienna liczbowa zmienna1 posiada zapalone wszystkie te bity, które określa maska stala1.

Czy dobrze rozumiem, że równie dobrze można to zapisać:

if zmienna1 = stala1 then

Nie, to nie będzie tożsame — zmienna1 może posiadać więcej zapalonych bitów niż stała stala1, żeby warunek został spełniony. Po to używa się koniunkcji bitowej, aby zgasić bity, które nas nie interesują, po czym te nas interesujące porównać z maską. Jeśli użyjesz drugiej konstrukcji, to ograniczysz spełnienie warunku wyłącznie do sytuacji, w której wartości zmienna1 i stala1 są identyczne.

Zobacz na ten przykład:

       v  v v
    %00100101; // stala1
and %00100101; // zmienna1
    ---------
    %00100101; // wynik koniunkcji (to samo co stala1)
       ^  ^ ^  // ok

Zmienna ma taką samą wartość jak stała, więc wynikiem koniunkcji jest taka sama liczba. Natomiast jeśli zmienna będzie posiadać więcej zapalonych bitów, np.:

       v  v v
    %00100101; // stala1
and %11111101; // zmienna1
    ---------
    %00100101; // wynik koniunkcji (to samo co stala1)
       ^  ^ ^  // ok

to koniunkcja spowoduje, że te zgaszone w masce będą również zgaszone w rezultacie — warunek nadal zostanie spełniony, dlatego że wynikiem jest taka sama liczba jak ta w masce. Żeby warunek nie został spełniony, w zmiennej musi brakować zapalonych bitów na pozycjach, w których są one zapalone w masce, np.:

       v  v v
    %00100101; // stala1
and %11001001; // zmienna1
    ---------
    %00000001; // wynik koniunkcji (różny od stala1)
            ^  // dupa
0

Szkoda że nie podałeś deklaracji zmiennych.
Z tego że kod się kompiluje można się domyślać że nie są to zmienne zmiennoprzecinkowe ani stringi

0

źle postawiłeś nawiasy - najpierw jest AND a dopiero potem =

Kurde, zapomniałem że w Pascalu był tam mały WTF z kolejnością i zawsze należało używac nawiasów. Czyli to jest

if ((zmienna1 and stala1) = stala1) then

XD
Ale nie wiem co ktoś chciałby tym osiągnąć XD

1
KamilAdam napisał(a):

Kurde, zapomniałem że w Pascalu był tam mały WTF z kolejnością i zawsze należało używac nawiasów.

Kolejność wykonywania instrukcji w trakcie ewaluacji wyrażenia jest taka sama jak np. w C — główną rolę odgrywają priorytety operatorów oraz nawiasy. Natomiast to co Pascala od C odróżnia, to wykorzystywanie tego samego zestawu operatorów do operacji logicznych i binarnych. Czyli operatory takie jak not, and, or i xor mogą być bitowe lub logiczne i to zależy od kontekstu (typu danych operandów i wyników poszczególnych ewaluacji). Nie jest to jakoś szczególnie trudne do zrozumienia. ;)

0

Istnienie tych ”podwójnych” operatorów jest uzasadnione składniowo — Pascale mają operatory w formie słów, nie znaków jak w językach C-pochodnych. Jeśli by chcieć rozdzielić and na bitowy i logiczny, to trzeba by stworzyć np. andl (logiczny and) i andb (binarny and), a te już nie wyglądają dobrze. Tak więc twórca tutaj postawił na czytelność i prostotę składni. — furious programming 36 minut temu

Twórca postawił (w tym przypadku) na nieczytelność i prostotę składni.

generalnie klasyczny proceduralny Pascal ma składnię bardzo elegancką, o względnie niskim koszcie tworzenia kompilatora (w onym czasie mutacje Algola przyprowadzały twórców kompilatora o siwiznę, Wirth tego uniknął)
Jest szkodą dla branży, że nie zwyciężył jako język ogólnego programowania systemowego, wystarczało niewiele mu dodać, a nic burzącego filozofię (zresztą dialekty dzielnie to nadrabiały, z kilkoma tylko brakami)

Ale to z bitowymi i logicznymi operatorami to (wczuwam się) był dla C-owoców duży gwóźdź

Tylko że kompilator jak wie, że to logiczne operacje to jeśli miałbyś a and ( bardzo skompilkowane równanie) to jeśli a będzie false to drugie się nie wykona, a jeśli by było bitowe i logiczne jednocześnie to niepotrzebnie się wykonuje druga część. Kompilator mając metadane na temat operacji to może wprowadzić dodatkowe optymalizacje. — tumor 42 minuty temu

Nie dałbym sobie ręki uciąć, że dotyczy to pascala.

0
AnyKtokolwiek napisał(a):

Tylko że kompilator jak wie, że to logiczne operacje to jeśli miałbyś a and ( bardzo skompilkowane równanie) to jeśli a będzie false to drugie się nie wykona, a jeśli by było bitowe i logiczne jednocześnie to niepotrzebnie się wykonuje druga część. Kompilator mając metadane na temat operacji to może wprowadzić dodatkowe optymalizacje. — tumor 42 minuty temu

Nie dałbym sobie ręki uciąć, że dotyczy to pascala.

Ręki nie dam sobie za to uciąć ale wydaje mi się iż już turbo Pascal miał przełącznik żeby generować skoki dla and/or

0

Ale ten pascal jest okropny, nie mogłem z hello worldem sobie poradzić, trzeba ręcznie na boolean typ rzutować, oczy mi wypaliło od patrzenia na ten kod.
https://godbolt.org/z/hfvE63GKq
Jakoś mega dziwnie i nieintuicyjnie się programuje w tym pascalu trochę jak basic albo jakiś brainfuck.
Nigdy więcej, chyba jestem za młody na pascala, włosy jeszcze kolorowe.

https://godbolt.org/z/esvGdcxGT

1

No trzeba zrobić x > 0 żeby na boolean zrzutować.

Ale wiesz iż tak jest w większości statycznie typowanych języków? To raczej C/C++ są tu wyjątkami. W Javie czy Haskellu miałbyś tak samo porównanie do 0, bo int i boolean to różne typy w tych językach programowania

1

Po to są oddzielne operatory, żeby nie mieszać logicznych z bitowymi operacjami, nie no w javie można zrobić if (x) nie trzeba robić if (x == 0)

jak x jest intem to nie można, kod:

class HelloWorld {
    public static void main(String[] args) {
        int x = 7;
        if (x) {
            System.out.println("Hello, World!");
        }
    }
}

Się nawet nie skompiluje

ERROR!
javac /tmp/frywOMTf9d/HelloWorld.java
/tmp/frywOMTf9d/HelloWorld.java:4: error: incompatible types: int cannot be converted to boolean
        if (x) {
^
1 error
1
AnyKtokolwiek napisał(a):

Twórca postawił (w tym przypadku) na nieczytelność i prostotę składni.

Zależy dla kogo — dla mnie jeden zestaw operatorów jest znacznie lepszym rozwiązaniem, niż podział na dedykowane operacjom logicznym i binarnym (jak np. w C). W Pascalach nie da się źle użyć operatora i np. zamiast koniunkcji logicznej użyć koniunkcji bitwej. Nie da się pomylić, bo kompilator dostosowuje typ operacji kontekstowo, na podstawie typu danych obu operandów. W C możesz się pomylić i się o tym nie dowiedzieć — kompilator wykona nakazaną mu operację.

Nie dałbym sobie ręki uciąć, że dotyczy to pascala.

No to dobrze, bo już byś ręki nie miał.

We Free Pascalu ewaluacja wyrażeń domyślnie jest uproszczona (tzw. lazy evaluation), dzięki czemu kompilator może skutecznie optymalizować ich kod. Jeśli w trakcie wykonania kodu wyrażenia, wstępny wynik nie pozwoli np. na spełnienie instrukcji warunkowej, to dalsza część wyrażenia jest pomijana. Aby nakazać kompilatorowi wykonanie wyrażeń w całości, należy skorzystać z dyrektywy {$BOOLEVAL} — można dla całego modułu lub kontekstowo. Jest to istotne w przypadku złożonych wyrażeń, szczególnie tych, które posiadają wywołania funkcji — dzięki leniwej ewaluacji, te funkcje w ogóle nie zostaną wykonane.


tumor napisał(a):

Ale ten pascal jest okropny, nie mogłem z hello worldem sobie poradzić, trzeba ręcznie na boolean typ rzutować, oczy mi wypaliło od patrzenia na ten kod.
https://godbolt.org/z/hfvE63GKq

Za dużo tych nawiasów dałeś — o wiele za dużo. Pamiętaj, że instrukcje warunkowe w Pascalach nie wymagają grupowania wyrażenia w nadrzędne, główne nawiasy (tak jak C-pochodne języki). Kod tego warunku można uprościć do tej postaci, zachowując takie samo działanie:

if Square(3) or Square(2) <> 0 then

I wracając do pozornego problemu operatorów — kompilator nie rzuci błędem kompilacji tylko w przypadku, gdy obie te funkcje jako rezultat zwracają liczby całkowite. Jeśli którakolwiek zwraca wartość logiczną lub jakikolwiek typ danych nie będący jawnym intem, dostaniesz błąd. I tak samo będzie, jeśli obie zwracają wartość logiczną. Również dostaniesz błąd kompilacji, jeśli źle pogrupujesz instrukcje nawiasami, np. w takiej sytuacji:

if Square(3) or (Square(2) <> 0) then

Gdybyś coś takiego zrobił w C, nie dowiedziałbyś się od kompilatora tego, że napisałeś błędny kod. Pascal jest zdecydowanie bezpieczniejszy od C, właśnie ze względu na silne typowanie i konieczność doprowadzenia wyrażenia do jawnej wartości logicznej na potrzeby instrukcji warunkowej.

Oczywiście można to zmienić i przeładować sobie operator przypisania int→bool i mieć możliwość tworzenia warunków jak w C, czyli bez doprowadzania wyniku operacji składowych do jawnej wartości logicznej, np. w ten sposób:

{$mode objfpc}

  operator := (const AParam: Integer): Boolean; inline;
  begin
    Result := AParam <> 0;
  end;

var
  Int1: Integer = 2;
  Int2: Integer = 4;
begin
  if Int1 or Int2 then // cicha konwersja wyniku liczbowego na wartość logiczną
    WriteLn('dupa');
end.

ale niech cię ręka boska broni przed takimi głupotami. ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1