2016-05-04 10 views
0

Ich machte this FizzBuzz exercise on CodingBat;Der leistungsfähigste Ansatz zum Lösen von FizzBuzz

Bei einer Zeichenfolge str, wenn die Zeichenfolge mit "f" beginnt, geben Sie "Fizz" zurück. Wenn die Zeichenfolge mit "b" endet, geben Sie "Buzz" zurück. Wenn die Bedingungen "f" und "b" erfüllt sind, geben Sie "FizzBuzz" zurück. In allen anderen Fällen geben Sie die Zeichenfolge unverändert zurück.

und kam mit dieser Antwort;

public String fizzString(String str) 
{ 
    String sum = ""; 

    if (str.startsWith("f")) sum += "Fizz"; 
    if (str.endsWith("b")) sum += "Buzz"; 

    return (sum == "") ? str : sum; 
} 

jedoch ging der Autor des Problems für;

public String fizzString(String str) 
{ 
    if (str.startsWith("f") && str.endsWith("b")) return "FizzBuzz"; 
    if (str.startsWith("f")) return "Fizz"; 
    if (str.endsWith("b")) return "Buzz"; 

    return str; 
} 

die Art und Weise zu überflüssig schien ...

Ich habe mich gefragt, würde es einen Unterschied in der realen Welt, Performance-weise, macht für das erste Programm gehen eher dann dem zweiten?

+4

Die zweite ist schneller. Ich glaube nicht, dass die FizzBuzz-Performance in der realen Welt jemals eine Rolle spielt. – erickson

+0

In der realen Welt? Wahrscheinlich nicht. In einer pingeligen Welt gibt es Kompromisse zu beiden Ansätzen. Der erste Ansatz verwendet die 'String'-Verkettung, die [notorisch langsam] sein kann (http://stackoverflow.com/q/1532461/758280). Der zweite Ansatz verwendet mehr Konditionals als der erste. – Jeffrey

+0

String Verkettung ist nicht die zusätzliche Bedingung, die im schlimmsten Fall für Lösung Nr. 2 Überprüfung wert. Sie müssen möglicherweise mehr Speicher für eine Zeichenfolge Verkettung zuweisen, die viel langsamer als die Überprüfung einer booleschen Bedingung –

Antwort

0

Meine Berechnungen sagen, sonst ... (Der Abschnitt Kommentar bekam zu voll.)

ich ein Java-Programm, das einen Code-Block so schnell wie möglich für eine bestimmte Zeit laufen (1000 Millisekunden) . Es wird dies 10 Mal tun, um einen Durchschnittswert zu erhalten, am wenigsten und am meisten.

Ich muss sagen, die erste Methode kommt schneller, um durchschnittlich etwa 4.000.000 Schleifen pro Sekunde.

Hier meine Ergebnisse sind:

First Method: 
Least loops: 26,312,768 
Most loops: 26,918,157 
Average loops: 26,582,653.7 

    Second Method: 
Least loops: 22,039,592 
Most loops: 22,596,476 
Average loops: 22,424,598.5 

Hier ist der Quellcode ich habe, sagen Sie mir bitte die Daten Ich habe einen Weg bekam verzerrt würde. Ich behielt die Last, die mein Computer unter konstant war, und ich hielt den Code konstant. Das einzige, was sich geändert hat, war, was ich innerhalb der while Schleife angerufen habe.

package personal; 
 

 
import java.util.ArrayList; 
 
import java.util.Arrays; 
 
import java.util.Collections; 
 
import java.util.List; 
 

 
public class SpeedTest { 
 

 
    public static void main(String[] args) { 
 
    int loops = 10; 
 
    double DELAY = 1000; 
 
    int i; 
 
    double[] loopCount = new double[loops + 1]; 
 
    double sum = 0; 
 
    for (i = 0; i < loops + 1; i++) { 
 

 
     long startTime = System.currentTimeMillis(); 
 
     long endTime = (long)(startTime + DELAY); 
 
     long index = 0; 
 

 
     while (true) { 
 
     fizzString("TEST"); 
 
     //fizzString2("TEST"); 
 
     long now = System.currentTimeMillis(); 
 
     if (now >= endTime) { 
 
      break; 
 
     } 
 
     index++; 
 
     } 
 

 
     if (i != 0) { 
 
     if (DELAY != 1000) { 
 
      if (DELAY/1000 % 1 == 0) { 
 
      System.out.printf("Test %.0f. %,.0f loops in %.0f seconds.\n", (float) i, (float) index, (float) DELAY/1000); 
 
      } else if ((DELAY/100) % 1 == 0) { 
 
      System.out.printf("Test %.0f. %,.0f loops in %.1f seconds.\n", (float) i, (float) index, (float) DELAY/1000); 
 
      } else if ((DELAY/10) % 1 == 0) { 
 
      System.out.printf("Test %.0f. %,.0f loops in %.2f seconds.\n", (float) i, (float) index, (float) DELAY/1000); 
 
      } else if (DELAY % 1 == 0) { 
 
      System.out.printf("Test %.0f. %,.0f loops in %.3f seconds.\n", (float) i, (float) index, (float) DELAY/1000); 
 
      } 
 
     } else { 
 
      System.out.printf("Test %.0f. %,.0f loops in %.0f second.\n", (float) i, (float) index, (float) DELAY/1000); 
 
     } 
 
     loopCount[i] = index; 
 
     } 
 
    } 
 
    Arrays.sort(loopCount); 
 
    System.out.printf("Least loops: %,.0f\n", (loopCount[1])); 
 
    System.out.printf("Most loops: %,.0f\n", loopCount[loops]); 
 

 
    for (int d = 1; d < loopCount.length; d++) { 
 
     sum += loopCount[d]; 
 
    } 
 
    double averageLoopCount = 1.0f * sum/(loopCount.length - 1); 
 
    System.out.printf("Average loops: %,.1f", averageLoopCount); 
 
    } 
 

 
    public static String fizzString(String str) { 
 
    if (str.startsWith("f") && str.endsWith("b")) return "FizzBuzz"; 
 
    if (str.startsWith("f")) return "Fizz"; 
 
    if (str.endsWith("b")) return "Buzz"; 
 

 
    return str; 
 
    } 
 

 
    public static String fizzString2(String str) { 
 
    String sum = ""; 
 

 
    if (str.startsWith("f")) sum += "Fizz"; 
 
    if (str.endsWith("b")) sum += "Buzz"; 
 

 
    return (sum == "") ? str : sum; 
 
    } 
 
}

Try für euch :)

+0

Ich habe es einfach immer und immer wieder gemacht, und du hast recht, es ist schneller ... Ich verstehe nicht, warum hat der andere gesagt, dass die Lösung # 2 die schnellste war? – CaffeinatedSynapse

+0

@CoffeeAddict Der wahre Grund: Ich weiß es nicht; Was ich sagen kann, ist: * Fügen Sie "Theorie vs Praxis" Zitat hier ein * – Kaelinator

+4

Zunächst verwendet dieser Benchmark TEST als String, was die String-Konstruktion des ersten Ansatzes eliminiert, da er nicht mit f beginnt und mit b endet . Zweitens ignoriert es das Ergebnis, wodurch Hotspot den Aufruf von fizzbuzz vollständig vermeiden kann. Drittens verwendet es System.currentTimeMillis() und ruft es bei jeder Iteration auf, wo wahrscheinlich die meiste Zeit verbracht wird. Einen Mikro-Benchmark in Java zu schreiben ist schwer. Lesen Sie http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java –

0

Das ist wirklich der tatsächlichen CPU-Anweisungen ab, die ausgeführt werden sollen,

aber die allgemeine Idee ist

    haben
  • die geringste Anzahl von ausgeführten Verzweigungen (if-else)
  • die geringste Anzahl von Speicherzugriffen
  • keine dynamische Zuweisung.

So etwas sollte schneller als die beiden vorgeschlagenen Lösungen sein.

public String fizzString(String str) 
{ 
    if (str.length() == 0) return str; 

    if (str.charAt(0) == 'f') { 
     if (str.charAt(str.length() - 1) == 'b') { 
      return "FizzBuzz"; 
     } 
     return "Fizz"; 
    } 
    if (str.charAt(str.length() - 1) == 'b') { 
     return "Buzz"; 
    } 
    return str; 
} 
Verwandte Themen