führende Nullen ermitteln.



  • Hi,
    mir fehlt im Moment der ansatz wie ich die Anzahl der führenden Nullen bei einer Gleitkommazahl ermitteln kann.

    Ich wollte es jetzt so versuchen, aber es ist recht umständlich.
    - wandle die Zahl in einen String um
    - suche das Komma
    - zähle ab dem Komma alle Elemente die 0 sind, bis das erste != 0 ist

    Der erste Ansatz in C++ sieht so aus

    char s_Zahl[200];
    double zahl=0.00004103
    bool start_cnt=0; //flag, ob ma schon hinter dem Komma ist
    int count;
    sprintf(s_Zahl,"%d",zahl);
    for(int i=0; i<200; i++)
    {
      if(s_Zahl[i]=='.')
      {
        start_cnt=1;
        i++; //gleich mit nächstem Element weitermachen
      }
      if(start_cnt)
        if(is_digit(s_Zahl[i]) && s_Zahl[i]=='0') //Probe ob Element eine Zahl und 0
          count++;
        else
          return;
    }
    


  • Wie wärs mit nem std::string und dann find_first_not_of("0")? Macht das Leben deutlich einfacher...



  • Ne, ist mir zu einfach 🙄

    DANKE



  • Hallo,
    wie wäre es einfach mal ohne Strings?

    int leadingZeros(double d)
    {
    	int res = 0;
    	int fak = 10;
    	for (int t; (t = d * fak) == 0 ; fak *= 10)
    		++res;
    	return res;
    }
    

    Achtung: Nicht getestet!



  • Danke, die Idee ist einfach genial einfach. 😮



  • Na also, wenn das nicht dem Logarithmus zu knacken ist...

    Irgendwie mal den 10er Logarithmus andwenden. Da ein Minus davor dürfte schonmal ziemlich in die richtige Richtung gehen, oder täusche ich mich da?

    MfG Jester



  • @Jester
    Wäre Möglich, ist aber vom Rechenaufwand sehr aufwendig.

    Ich hab jetzt ne tolle Lösung auf der Idee von HumeSikkins.
    Damit werden alle Nullen nach dem Komma ausgegeben, bis einen andere Ziffer kommt.

    int leading_zero(double d)
    {
      int cnt=0;
      d=d-(long)d; //Abtrennen der Ziffern vor dem Komma
      while(true)
      {
        d=d*10;
        if(d<1)
          cnt++;
        else
          return cnt;
      }
      return cnt;
    }
    

    Wie ich finde einfach, genial einfach.



  • Bist Du sicher, daß der log langsamer ist als die Schleife?
    Das würde mich wundern.

    MfG Jester



  • @Jester

    Ich hab es mal probiert, log10 ist langsamer als *

    double klein=0.004;
    start = clock();
    for(i=0; i<10000000;i++)
    	log10(klein);
    finish=clock();
    duration = (double)(finish - start) / CLOCKS_PER_SEC;
    cout<<duration<<" Sekunden"<<endl;
    
    printf("\n");
    
    start = clock();
    for(i=0; i<10000000;i++)
    	klein=klein*10;
    finish=clock();
    duration = (double)(finish - start) / CLOCKS_PER_SEC;
    cout<<duration<<" Sekunden"<<endl;
    

    Als Ergebnis kommt bei mir:
    2.553 Sekunden für log10
    2.364 Sekunden für *

    Ist aber in dem Fall egal, da wohl nie versuchen werde mehr als 10E7 Nullen zu erfragen. 😃

    Oder siehst Du das anders?

    cu



  • @daishi
    Dein Test ist ein Milchmädchen-Test. Wenn dann müsstest du schon das klein = klein * 10 in eine Funktion packen. Sinnvoller wäre aber gleich ein Vergleich der beiden fertigen Lösungen.

    Wie auch immer: die Geschwindigkeit ist imo ersteinmal zweitrangig. Wichtig ist die Lesbarkeit (bzw. Verständlichkeit) der Lösung.

    @Jester
    Wie sähe die Funktion unter Anwendung des Logs aus? Ich habe eben ein klein bischen rumgespielt, bin aber leider zu keiner schönen Lösung gekommen.



  • @HumeSikkins
    Du hattest recht, es war ein schlechtes Beispiel.
    Wenn ich eine Funktion verwende ist log noch langsamer

    double funktion(double x)
    {
    	return x*10;
    }
    

    2.553 Sekunden
    gegen
    1.252 Sekunden



  • Ich glaube hier misst jemand die Geschwindigkeit im Debug.


Anmelden zum Antworten