Zakres zmiennych w pętli

0

Cześć, potrzebuję sprawdzić czy zmienna x i y zawiera się w przedziale od n do m.
Robię to w ifach i zakresy zrobiłem tak, ale nie działa to poprawnie.

 
//1
    if (x in [0..(szerokosc div 2)]) and (y in [0..(wysokosc div 2)]) then
    begin
      ekran1 := ekran1+1;

    end;
    //2
    if (x in [(szerokosc div 2)..szerokosc]) and (y in [0..(wysokosc div 2)]) then
    begin
      ekran2 := ekran2+2;

    end;
    //3
    if (x in [0..(szerokosc div 2)]) and (y in [(wysokosc div 2)..wysokosc]) then
    begin
      ekran3 := ekran3+3;

    end;
    //4
    if (x in [(szerokosc div 2)..szerokosc]) and (y in [(wysokosc div 2)..wysokosc]) then
    begin
      ekran4 := ekran4+4;

    end;

Sprawdzałem to debuggerem to te zakresy zamiast zawierać się od np 0 do 600, pokazywało mi, że
0..(szerokosc div 2)] = 0.

0

Sprawdź więc pod debugerem ile wynosi wartość zmiennej szerokosc; I jeśli dzielisz przez 2 to nie używaj do tego Div, tylko Shr - jest o wiele szybsze:

szerokosc shr 1

daje to samo, co:

szerokosc div 2

Więcej o optymalizacji kodu możesz poczytać w tym artykule;

Poza tym cztery razy wykonujesz dzielenie całkowite, zamiast zadeklarować sobie jedną dodatkową zmienną i do niej zapisać wynik tego dzielenia; Czyli coś w tym stylu:

var
  intWidth, intHeight: Integer;
  intHalfWidth, intHalfHeight: Integer;
  X, Y: Integer;
begin
  intWidth := 800;
  intHeight := 600;
  X := 300;
  Y := 300;

  intHalfWidth := intWidth shr 1;
  intHalfHeight := intHeight shr 1;

  { 1 }
  if (X in [0 .. intHalfWidth]) and (Y in [0 .. intHalfHeight]) then
  begin
    // instrukcje
  end;

  { 2 }
  if (X in [intHalfWidth .. intWidth]) and (Y in [0 .. intHalfHeight]) then
  begin
    // instrukcje
  end;

  { 3 }
  if (X in [0 .. intHalfWidth]) and (Y in [intHalfHeight .. intHeight]) then
  begin
    // instrukcje
  end;

  { 4 }
  if (X in [intHalfWidth .. intWidth]) and (Y in [intHalfHeight .. intHeight]) then
  begin
    // instrukcje
  end;
end;

EDIT: Zbyt duże zakresy - nie przejdzie (patrz kilka postów niżej).

0

dzięki, poczytam.
zrobiłem 2 zmienne, wstawiłem je do kodu ale wynik jest ten sam.

szerokosc  :=  Screen.Width;
wysokosc :=  Screen.Height;

wys2 :=  Screen.Height shr 1;
szer2  :=  Screen.Width shr 1;
 
if (x in [0..szer2]) and (y in [0..wys2]) then
    begin
      ekran1 := ekran1+1;

    end;
    //2
    if (x in [szer2..szerokosc]) and (y in [0..wys2]) then
    begin
      ekran2 := ekran2+1;

    end;
    //3
    if (x in [0..szer2]) and (y in [wys2..wysokosc]) then
    begin
      ekran3 := ekran3+1;

    end;
    //4
    if (x in [szer2..szerokosc]) and (y in [wys2..wysokosc]) then
    begin
      ekran4 := ekran4+1;

    end;

wiem, że mogę to zrobić if (x <= n and x>m) and (y <=k and y>l) ale to takie za bezpośrednie.

0
Furious Programming napisał(a)

I jeśli dzielisz przez 2 to nie używaj do tego div, tylko shr - jest o wiele szybsze:

W Dragona się obracasz? (no offence ;P)
KAŻDY kompilator znany ludzkości takie optymalizacje wykonuje przy -O1, jak nie nawet -O0, a korzystając z przesunięć bitowych do mnożenia/dzielenia czytelność kodu znacznie się zmniejsza.
Poza tym:
1.To dział "newbie".
2.A on nie pisze funkcji wywoływanej miliardy razy na sekundę.

@autor tematu: afair set w Pascalu może zawierać wyłącznie 256 elementów, stąd już np.taki kod:
Writeln(1024 in [0..2048]); zwróci "false": http://ideone.com/ANQhjH
(chociaż afair we Free Pascalu starają się przerzucić na 32-bitowe sety, lecz nie wyprzedzajmy faktów).

Użyj funkcji Math.InRange.

0

A jeśli nie chcesz dodawać dodatkowego modułu do programu to napisz funkcję InRange samemu:

function NumberInRange(ANumber, ALow, AHigh: Integer): Boolean;
begin
  Result := (ANumber >= ALow) and (ANumber <= AHigh);
end;

i potem wykonaj sprawdzanie:

intHalfWidth := intWidth div 2;   // div użyte specjalnie
intHalfHeight := intHeight div 2; // dla @Patryk27 :P

if NumberInRange(X, 0, intHalfWidth) then
begin
  if NumberInRange(Y, 0, intHalfHeight) then
    { 1 }
  else
    { 3 };
end
else
  if NumberInRange(Y, 0, intHalfHeight) then
    { 2 }
  else
    { 4 };
end;

Dzięki temu zawsze dokonasz jedynie dwóch sprawdzeń zakresu, zamiast w najgorszym przypadku ośmiu.

0

Sprawdź więc pod debugerem ile wynosi wartość zmiennej szerokosc; I jeśli dzielisz przez 2 to nie używaj do tego div, tylko shr - jest o wiele szybsze:

Ale wiesz że w ten sposób co najwyżej utrudniasz zadanie kompilatorowi? Każdy współczesny kompilator to wie, natomiast niektóre mogą się dziwić zastosowaniu shr/shl. Więc sam sobie zaciemniasz kod i dodatkowo sprawę utrudniasz kompilatorowi. Nie polecam.

KAŻDY kompilator znany ludzkości takie optymalizacje wykonuje przy -O1, jak nie nawet -O0, a korzystając z przesunięć bitowych do mnożenia/dzielenia czytelność kodu znacznie się zmniejsza.
Poza tym:
1.To dział "newbie".
2.A on nie pisze funkcji wywoływanej miliardy razy na sekundę.

Całkowicie się zgadzam.

Niech pozna sztuczki optymalizacyjne - przydadzą się w przyszłości ;)

Jasne, jak pisałem swój exe protector to często używałem shl/shr tylko problem jest taki, że wtedy nie masz optymalizatora i musisz samemu znać triki (a akurat ten jest bardzo podstawowy i wręcz często wolniejszy niż inne triki).
Jak chcecie się bawić w sztuczki to lepiej powiedzcie jak w asmie x86 szybko pomnożyć liczbę przez 3 lub 9 ;) .

No ok, lecz "sztuczką optymalizacyjną" może być np.wyłączenie range-checking, zabawa ze zmianą FPU/SSE, przełącznik inline i ogólna restrukturyzacja programu, a nie ręczna obfuskacja kodu ;)

Sztuczką optymalizacyjną jest coś co zmusza kompilator do generowania ładniejszego kodu np. użycie pointerów zamiast tablic etc.

Generalnie to sety w Pascalu przydają się głównie do własnych zbiorów i zbiorów znaków.

0

jak w asmie x86 szybko pomnożyć liczbę przez 3 lub 9 (Num << 1)+Num dla liczb całkowitych, lecz nie wiem jak z szybkością tego ;P

To nie jest kod assemblera.

a9 = a8+a, to jest 1 klasa podstawówki... :-|

Pała! Siadaj, to nie kod assemblera. Czekam na kod assemblera :) .

Jeżeli chcecie napisać coś w stylu:

;input -eax, output ebx
mov ebx,eax
shr eax,3
add ebx,eax

To nie, to nie jest dobrze. To jest wolna metoda.

0

Niech zgadnę - opcode lea?
Zapewne coś w rodzaju:

lea eax, [ebx*3]

Szybciej się nie da :P

0

wolna? pokaż szybszą, mastah..

Niech zgadnę - opcode lea?

Tak jest:
lea eax,[eax*8+eax]
nie można zrobić lea eax,[eax*3] ale można lea eax,[eax*2+eax] :P

Szybciej się nie da

Zawsze się da szybciej, kwestia tego jak dobry jesteś w assemblerze. Po prostu ktoś by to zrobił bez mnożenia, albo by przeniósł mnożenie etc.

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