Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: W jaki logiczny sposób można skrócić tę funkcję?
Forum PHP.pl > Forum > PHP
Saki
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. }
Michael2318
Do czego Ci to ma służyć?
I nie używaj AND tylko &&, tak samo nie OR tylko || smile.gif
Saki
Cytat(Michael2318 @ 24.03.2013, 16:00:30 ) *
Do czego Ci to ma służyć?


  1. <?PHP include('function.php');
  2. $leitwert = leitwert($_POST['u'], $_POST['r'], $_POST['i'], $_POST['g']);
  3. ?>
  4. <p>Leitwert</p>
  5. <form method="post" action="">
  6. <p> U [V] <input type="text" name="u" value="<?=$leitwert['u']?>" placeholder="U [V]" /></p>
  7. <p> G [S] <input type="text" name="r" value="<?=$leitwert['g']?>" placeholder="G [S]" /></p>
  8. <p> I [A] <input type="text" name="i" value="<?=$leitwert['i']?>" placeholder="I [A]" /></p>
  9. <p> R [Ohm] <input type="text" name="r" value="<?=$leitwert['r']?>" placeholder="R [Ohm]" /></p>
  10. <input type="submit" value="Berechnen" />
  11. </form>
  12. <p>
  13. U: Spannung in Volt<br />
  14. I: Stromstaerke in Ampere<br />
  15. G: Leitwert in Siemens<br />
  16. R: Widerstand in Ohm<br />
  17. </p>
  18.  
  19.  


Cytat(Michael2318 @ 24.03.2013, 16:00:30 ) *
Do czego Ci to ma służyć?
I nie używaj AND tylko &&, tak samo nie OR tylko || smile.gif


A masz może jakiś pomysł jak zmienić logikę funkcji, aby nie było tysiące ifów?
Pilsener
Cytat
A masz może jakiś pomysł jak zmienić logikę funkcji, aby nie było tysiące ifów?

Logika dla każdej kombinacji unikalna? Użyć konstrukcji switch, wykona się blok zależny od wysłanych zmiennych a jeśli nie to default.
thek
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 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? 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 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" 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ąć wink.gif Kod myślę, że kumaci zrozumieją i nieco poprawią by działał mimo owych problemów smile.gif
LSM
Odpal sobie to i testuj. Może ułatwi Ci to pracę z kodem. Ilość IF'ów minimalnie zmniejszyłem ;-). Sprawa jest o tyle ciężka, że tutaj mamy przekazane parametry, które mogą, ale nie muszą być zmieniane w trakcie wykonania funkcji dlatego do funkcji getI, getU itd. trzeba przekazać wszystkie parametry. Jest na to sposób - zastosować klasę i zmienne klasy. Powodzenia.


  1. testLeitwerg();
  2.  
  3. function testSingle( $u, $r, $i, $g ) {
  4. $old = old_leitwert( $u, $r, $i, $g);
  5. $new = leitwert( $u, $r, $i, $g);
  6. $res = array_diff($old, $new);
  7. if( !empty( $res ) ){
  8. echo "ERR;";
  9.  
  10. } else {
  11. echo "OK;";
  12. }
  13. echo " params: $u, $r, $i, $g <br />";
  14. var_dump( $old );
  15. var_dump( $new );
  16.  
  17. }
  18.  
  19. function testLeitwerg(){
  20. /* testSingle( 0, 2, 2, 2 );
  21. testSingle( 2, 0, 2, 2 );
  22. testSingle( 2, 2, 0, 2 );
  23. testSingle( 2, 2, 2, 0 ); */
  24.  
  25. testSingle( 15, 6, 2, 2 );
  26. testSingle( 666, 8, 2, 2 );
  27. testSingle( 54, 2, 3, 6 );
  28. testSingle( 54544, 1, 2, 23 );
  29. }
  30.  
  31. function old_leitwert($u, $r, $i, $g) {
  32. # 1
  33. if ( $u AND $i ) {
  34. $r = $u/$i;
  35. $g = 1/$r;
  36. }
  37.  
  38. # 2
  39. if ( $i AND $r ) {
  40. $u = $r*$i;
  41. $g = 1/$r;
  42. }
  43.  
  44. # 3
  45. if ( $u AND $r ) {
  46. $i = $u/$r;
  47. $g = 1/$r;
  48. }
  49.  
  50. # 4
  51. if ( $g AND $i ) {
  52. $r = 1/$g;
  53. $u = $r*$i;
  54. }
  55.  
  56. #5
  57. if ( $u AND $r ) {
  58. $g = 1/$r;
  59. $i = $u/$r;
  60. }
  61.  
  62. # 6
  63. if ( $u AND $g ) {
  64. $i = $u*$g;
  65. $r = $u/$i;
  66. }
  67.  
  68. # 7
  69. if ( $i AND $r ) {
  70. $u = $i*$r;
  71. $g = 1/$r;
  72. }
  73.  
  74. # 8
  75. if ( $g ) {
  76. $r = 1/$g;
  77. }
  78.  
  79. # 9
  80. if ( $r ) {
  81. $g = 1/$r;
  82. }
  83.  
  84. return array('r' => $r, 'u' => $u, 'i' => $i, 'g' => $g );
  85. }
  86.  
  87. function leitwert($u, $r, $i, $g) {
  88. echo 'NEW: <br />';
  89. # 1
  90. $r = getR( $u, $r, $i, $g );
  91. $g = getG( $u, $r, $i, $g );
  92.  
  93. # 2
  94. $u = getU( $u, $r, $i, $g );
  95. $g = getG( $u, $r, $i, $g );
  96.  
  97. # 3
  98. $i = getI( $u, $r, $i, $g) ;
  99. $g = getG( $u, $r, $i, $g );
  100.  
  101. # 4
  102. $r = getR( $u, $r, $i, $g );
  103. $u = getU( $u, $r, $i, $g );
  104.  
  105. # 5
  106. $g = getG( $u, $r, $i, $g );
  107. $i = getI( $u, $r, $i, $g );
  108.  
  109. # 6
  110. $i = getI( $u, $r, $i, $g );
  111. $r = getR( $u, $r, $i, $g );
  112.  
  113. # 7
  114. $u = getU( $u, $r, $i, $g );
  115. $g = getG( $u, $r, $i, $g );
  116.  
  117. # 8
  118. $r = getR( $u, $r, $i, $g );
  119.  
  120. # 9
  121. $g = getG( $u, $r, $i, $g );
  122.  
  123. return array('r' => $r, 'u' => $u, 'i' => $i, 'g' => $g );
  124. }
  125.  
  126. function getR( &$u, &$r, &$i, &$g ){
  127. if ( $g OR ($g AND $i) ) {
  128. $r = 1/$g;
  129. }
  130. if ( ($u AND $g) OR ($u AND $i) ) {
  131. $r = $u/$i;
  132. }
  133. return $r;
  134. }
  135. function getG( &$u, &$r, &$i, &$g ){
  136. if ( $r OR ($r AND $u) OR ($r AND $i) OR ($g AND $i) OR ($u AND $i) ) {
  137. $g = 1/$r;
  138. }
  139. return $g;
  140. }
  141. function getU( &$u, &$r, &$i, &$g ){
  142. if ( $i AND ($g OR $r) ) {
  143. $u = $i*$r;
  144. }
  145. return $u;
  146. }
  147. function getI( &$u, &$r, &$i, &$g ){
  148. if ( $u AND $g ) {
  149. $i = $u*$g;
  150. }
  151. if ( $u AND $r ) {
  152. $i = $u/$r;
  153. }
  154. return $i;
  155. }
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.