Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> W jaki logiczny sposób można skrócić tę funkcję?
Saki
post 24.03.2013, 15:56:36
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. }


--------------------
Moje serwisy: services.itunix.eu | spytajsie.com

Server: Debian; Desktop: Mac Mini 10.8.1, ArchLinux XFCE
Go to the top of the page
+Quote Post
Michael2318
post 24.03.2013, 16:00:30
Post #2





Grupa: Zarejestrowani
Postów: 651
Pomógł: 116
Dołączył: 3.06.2012
Skąd: Lędziny

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


Do czego Ci to ma służyć?
I nie używaj AND tylko &&, tak samo nie OR tylko || smile.gif

Ten post edytował Michael2318 24.03.2013, 16:02:39
Go to the top of the page
+Quote Post
Saki
post 24.03.2013, 16:06:19
Post #3





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

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


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?

Ten post edytował Saki 24.03.2013, 16:04:19


--------------------
Moje serwisy: services.itunix.eu | spytajsie.com

Server: Debian; Desktop: Mac Mini 10.8.1, ArchLinux XFCE
Go to the top of the page
+Quote Post
Pilsener
post 25.03.2013, 20:12:21
Post #4





Grupa: Zarejestrowani
Postów: 1 590
Pomógł: 185
Dołączył: 19.04.2006
Skąd: Gdańsk

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


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.
Go to the top of the page
+Quote Post
thek
post 25.03.2013, 22:45:08
Post #5





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 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
Powód edycji: [thek]: Kilka uwag...


--------------------
Najpierw był manual... Jeśli tam nie zawarto słów mądrości to zapytaj wszechwiedzącego Google zadając mu własciwe pytania. A jeśli i on milczy to Twój problem nie istnieje :D
Go to the top of the page
+Quote Post
LSM
post 26.03.2013, 10:09:35
Post #6





Grupa: Zarejestrowani
Postów: 64
Pomógł: 6
Dołączył: 20.03.2011
Skąd: Świdnica

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


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. }


Ten post edytował LSM 26.03.2013, 10:16:12


--------------------
"I see" - said the blind man.
Go to the top of the page
+Quote Post

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

 



RSS Wersja Lo-Fi Aktualny czas: 27.04.2024 - 20:32