Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> W jaki logiczny sposób można skrócić tę funkcję?
Saki
post
Post #1





Grupa: Zarejestrowani
Postów: 240
Pomógł: 2
Dołączył: 5.12.2010
Skąd: Fulda

Ostrzeżenie: (0%)
-----


Witam, piszę dla szkoły pewną stronę, skupiłem się narazie na działaniu, działa wszystko ładnie pięknie, ale mam mały problem z logiką kodu, wszystkie funkcje składają się z ifów, moje kolejne funkcje posiadają już przeszło 40 ifów i wszytsko działa, ale czy ktoś wie jak to można skrócić w logiczny sposób?
I aby tak samo działało.

  1. function leitwert($u, $r, $i, $g) {
  2. if ( $u AND $i ) {
  3. $r = $u/$i;
  4. $g = 1/$r;
  5. }
  6. if ( $i AND $r ) {
  7. $u = $r*$i;
  8. $g = 1/$r;
  9. }
  10. if ( $u AND $r ) {
  11. $i = $u/$r;
  12. $g = 1/$r;
  13. }
  14. if ( $g AND $i ) {
  15. $r = 1/$g;
  16. $u = $r*$i;
  17. }
  18. if ( $u AND $r ) {
  19. $g = 1/$r;
  20. $i = $u/$r;
  21. }
  22. if ( $u AND $g ) {
  23. $i = $u*$g;
  24. $r = $u/$i;
  25. }
  26. if ( $i AND $r ) {
  27. $u = $i*$r;
  28. $g = 1/$r;
  29. }
  30. if ( $g ) {
  31. $r = 1/$g;
  32. }
  33. if ( $r ) {
  34. $g = 1/$r;
  35. }
  36.  
  37. return array('r' => $r, 'u' => $u, 'i' => $i, 'g' => $g );
  38. }
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi
thek
post
Post #2





Grupa: Moderatorzy
Postów: 4 362
Pomógł: 714
Dołączył: 12.02.2009
Skąd: Jak się położę tak leżę :D




Pytanie... Po kiego grzyba Ci tyle IFów, które w zależności od danych mogą prowadzić do nieoczekiwanych wyników? Zwróć uwagę na zależności! Mając określone dane możesz wyliczyć tylko określone inne. Sprowadź więc całość do pewnych zależności, sprawdzając co występuje a co nie i zagnieżdżając owe IFy zamiast wypuszczać obok siebie. Zauważ, że Twój kod wielokrotnie liczy to samo, a na dodatek nie sprawdzasz co się dzieje gdy ktoś wprowadzi dane w celu wywalenia całości (IMG:style_emoticons/default/wink.gif) Jak? Załóżmy, że ktoś poda $u, $i, $g, to $r będzie kilka razy obliczane (linie 3, 15, 24, 31). A co gdy poda wszystkie 4? (IMG:style_emoticons/default/biggrin.gif) Zacznij od najmniej zależnych, czyli $g oraz $r.
  1. function leitwert($u, $i, $r, $g) {
  2. if ($r) {
  3. $g1 = 1 / $r;
  4. if ($g && $g != $g1) {
  5. throw Exception('G is malformed!');
  6. } else {
  7. $g = $g1;
  8. }
  9. } elseif ($g) {
  10. $r1 = 1 / $g;
  11. if ($r && $r != $r1) {
  12. throw Exception('R is malformed!');
  13. } else {
  14. $r = $r1;
  15. }
  16. }
  17. if ($i) {
  18. if ($u) {
  19. $r1 = $i / $u;
  20. if ($r && $r != $r1) {
  21. throw Exception('R is malformed!');
  22. } else {
  23. $r = $r1;
  24. }
  25. } elseif ($r) {
  26. $u1 = $i / $r;
  27. if ($u && $u != $u1) {
  28. throw Exception('U is malformed!');
  29. } else {
  30. $u = $u1;
  31. }
  32. }
  33. } elseif ($u) {
  34. if ($i) {
  35. $r1 = $i / $u;
  36. if ($r && $r != $r1) {
  37. throw Exception('R is malformed!');
  38. } else {
  39. $r = $r1;
  40. }
  41. } elseif ($r) {
  42. $i1 = $u * $r;
  43. if ($i && $i != $i1) {
  44. throw Exception('I is malformed!');
  45. } else {
  46. $i = $i1;
  47. }
  48. }
  49. } elseif ($r) {
  50. if ($i) {
  51. $u1 = $i / $r;
  52. if ($u && $u != $u1) {
  53. throw Exception('U is malformed!');
  54. } else {
  55. $u = $u1;
  56. }
  57. } elseif ($u) {
  58. $i1 = $u * $r;
  59. if ($i && $i != $i1) {
  60. throw Exception('I is malformed!');
  61. } else {
  62. $i = $i1;
  63. }
  64. }
  65. }
  66. if (!$g) {
  67. $g = 1 / $r;
  68. }
  69. if ($i && $u && $r && $g) {
  70. return array('i' => $i, 'u' => $u, 'r' => $r, 'g' => $g);
  71. } else {
  72. throw Exception('Not enough data!');
  73. }
  74. }

Czemu tak? Zaczniemy od sprawdzenia czy $g albo $r były podane. Liczenie ma sens w przypadku gdy tylko jedna z nich istnieje. Jeśli są obie lub brak obu - jest to bezcelowe (IMG:style_emoticons/default/smile.gif) A co gdy ktoś poda obie z powietrza? Przykładowo $r = 10, $g = 50... Skrypt powinien od razu zaprotestować. Na tym etapie może się też okazać, że wciąż nie mamy potrzebnego nam do dalszych obliczeń $r. Może tak być w sytuacji, gdy nie ma ani $r, ani $g potrzebnego do prostego jego wyliczenia.

Teraz "trójkącik" (IMG:style_emoticons/default/wink.gif) Klasyczny $i = $u * $r, gdzie jedna jest zależna od dwóch pozostałych. Tu można prościutko polecieć zagnieżdżeniem. Sprawdzamy która z trzech wartości występuje i jeśli któraś jest, sprawdzamy czy są pozostałe. Jeśli jakiejś brak - obliczamy brakującą.

Na końcu może się okazać, że skończyliśmy tylko z $u, $i, $r dla wariantu gdy podano do funkcji $u oraz $i, więc w tym wypadku trzeba obliczyć brakujące $g;

I to by było prawie tyle... Ale gdyby ktoś podał tylko jeden parametr do funkcji? Zadanie byłoby niepoliczalne, gdyż za mało danych do policzenia wszystkich. Stąd ostatnie sprawdzenie czy wszystkie dane są niezerowe, które może rzucić wyjątek.

Wydaje się o wiele dłuższe? Pozornie. Ty masz zachodzące po kolei 9 ifów, które zawsze się wykonają, niezależnie co byś nie robił. Jak zwróciłem uwagę, niektóre wielokrotnie mogą liczyć to samo. Ja sprawdzam, które obliczenia są faktycznie niezbędne i tylko je wykonuję. Ograniczam się jedynie do niezbędnych, czyli brakujących obliczeń. Co istotne... Nie poprawiam błędów użytkownika. Jeśli wpisze głupoty w stylu: $i = 5, $u = 10, $r = 300, to Twój kod poleci i wypluje dane pozornie prawidłowe... Wiesz dlaczego? Właśnie dlatego, że się nadpisują. Ty tego nie rozumiesz, ale kod skopiowałeś skądś, gdzie taka kolejność została celowo zastosowana. Dane błędne są bowiem nadpisywane prawidłowymi. Problem z tym, że jest to bez Twojej wiedzy i nie masz kontroli nad tym, co ciąg obliczeń uzna za dane prawidłowe. Zależy to bowiem od tego, który IF wykona się pierwszy i nadpisze jaką wartość. Ja w takiej sytuacji sprawdzam, czy ewentualna wyliczona jest zgodna z podaną w parametrze. Jeśli coś jest nie tak - rzucam wyjątek zamiast liczyć głupoty.

I pamiętaj, że PHP zaokrągla! Do tego więc co mam najlepiej podejść z uwzględnieniem tego. Poczytaj o błędach zaokrągleń i jak ich uniknąć (IMG:style_emoticons/default/wink.gif) Kod myślę, że kumaci zrozumieją i nieco poprawią by działał mimo owych problemów (IMG:style_emoticons/default/smile.gif)
Powód edycji: [thek]: Kilka uwag...
Go to the top of the page
+Quote Post

Posty w temacie


Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 14.10.2025 - 07:52