Funktionenproblem



  • Mein Code sieth jetzt so aus:

    #include<iostream>
    using namespace std;
    
    //Funktionendeklaration
    
    int potenz(unsigned int x)
    {
        unsigned int a, exp;
    
    	a = 1;
    
        while(exp > 0)
        {
         a = a * x;
         exp = exp - 1;
        }
    
        return a;
    }
    
    int main()
    {
        unsigned int n, exp, x, y, z, a;
    
        cin >> n;                           //Eingabe Zahl
        a = n;
    
        exp = 0;                            //Berechnung der Potenz anhand der Zahl
        while(n > 0)
        {
         n = n / 10;
         exp = exp + 1;
        }
    
        cout << exp << endl;
    
        while(exp > 0)                         //Berechnung der Zahl mit Funktion
        {
         y = (n / potenz(10)) % 10;
         exp = exp - 1;
        }
    
        cout << y << endl;
    
    system("pause");
    return 0;
    }
    

    Das Problem besteht jetzt an der letzten while-Schleife in der main. Ich will hier jetzt quasi jede einzelne Stelle zerlegt mit der gleichen Potenz (bei einer 4-stelligen Zahl ist die potenz jeder Ziffer auch 4) miteinander addieren. Versteht ihr was ich meine?


  • Mod

    knivil schrieb:

    SeppJ schrieb:

    Bis 2^53 rechnet man bei double und Ganzzahlen exakt.

    Da normalerweise die Potenzen ueber die e-Funktions implementiert sind, koennen Ungenauigkeiten schon frueher auftreten. Genau weiss ich es aber nicht.

    Guter Einwand. Probieren wir es aus:

    #include<cmath> 
    #include<iostream>
    #include <stdint.h>
    using namespace std;
    
    uint64_t pow(uint64_t base, unsigned exponent)
    {
      uint64_t result=1;
      for (unsigned i=0; i<exponent; ++i) result*=base;
      return result;
    }
    
    int main()
    {
      for(uint64_t base=1; base<pow(2,52); ++base)
        {
          unsigned max_exp=log(pow(2,53))/log(base);
          for (unsigned exponent=1; exponent< max_exp; ++exponent)
            {
              double floatingpow = pow(static_cast<double>(base), static_cast<double>(exponent));
              if (floatingpow > pow(2., 53.)) break; // Überlauf
              uint64_t integerpow = pow(base, exponent);
              if (floatingpow!=integerpow)
                {
                  cout<<"Ungenaues Ergebnis: "<<base<<" hoch "<<exponent << " = " << integerpow << " != " << floatingpow <<'\n';
                }
          }
        }
    }
    

    Wird ein bisschen brauchen, alle Kombinationen durchzuprobieren, aber bei mir läuft das Programm nun schon sehr sehr lange ohne eine Fehlstelle zu finden.



  • Ich glaub ich hab mein Problem etwas umständlich formuliert. Für die Zahl 325 soll die letzt while-Schleife folgendes machen: 33+23+5^3. Nur eben jetzt nicht nur für diese Zahl bzw. nicht nur für Zahlen mit 3 Stellen sondern von 1 bis unendlich viele Stellen! Ich glaub so ist es verständlicher



  • Einfaches Schema:

    Zahl = 123
    letzte zahl = 0

    1. letze Zahl = Zahl Modulo 10

    letzte Zahl = 3

    2. Zahl = Zahl - letzte Zahl
    3. Zahl = Zahl / 10

    Zahl = 12


  • Mod

    bandchef schrieb:

    Ich glaub ich hab mein Problem etwas umständlich formuliert. Für die Zahl 325 soll die letzt while-Schleife folgendes machen: 33+23+5^3. Nur eben jetzt nicht nur für diese Zahl bzw. nicht nur für Zahlen mit 3 Stellen sondern von 1 bis unendlich viele Stellen! Ich glaub so ist es verständlicher

    Und wo ist dein Problem? Wie du die Stellen einer Zahl bestimmen kannst, wurde dir schon erklärt und (wenn du Vicious Falcons Komplettlösung nicht einfach mit "Bäh, mag nicht nachdenken" abgelehnt hättest) sogar explizit vorgemacht.



  • int potenz(unsigned int x)
    

    Du moechtest also x^exp rechnen? Diese Funktion muss 2 Parameter haben, x und der entsprechende Exponent. Auch ist in der Funktion a und exp nicht initialisiert. Wenn du das hast, dann implementiere die Funktion potenz .

    Als zweites wuerde ich eine Funktion fuer die Anzahl der Ziffern schreiben. Nach http://de.wikipedia.org/wiki/Narzisstische_Zahl muss jeder Ziffer hoch ihrer Laenge in der Summe wieder die gleiche Zahl ergeben.

    Wird ein bisschen brauchen, alle Kombinationen durchzuprobieren

    Ich haette binaere Suche verwendet ... Alle Zahlen bis 2^53 durchzuprobieren bei 1GHz dauert wohl 9007199s bzw. 2501 Stunden.



  • Sorry, aber ich kapiers einfach nicht. Es geht ja jetzt nur noch darum die eingegebene Zahl in ihre einzelnen Stellen zu zerlegen und mit dem jeweiligen Exponenten zu potenzieren und danach sämtlich stellen zu addieren. Könnt ihr mir nicht nochmal speziell dazu helfen?



  • knivil schrieb:

    ..fehlerhaft, da 4150 und 4151 auch ausgegeben werden.

    4[h]5[/h] + 1[h]5[/h] + 5[h]5[/h] + 0[h]5[/h]
    1024 + 1 + 3125 + 0 = 4150 , 4051 eben 4150+1[h]5[/h]
    

    War ein Zufall, dass ich deinen Edit gerade noch gesehen habe.



  • Wenn er eine eigene Lösung entwickeln möchte ist das nur nachvollziehbar. Trotzdem würde ich gerne an V.Falcons appellieren seine schöne Lösung wieder in den Post aufzunehmen, da dies für eventuell zukünftige Leser hilfreich sein wird.

    Momentan möchte der Autor aber nur wissen wie man auf eine für ihn verständliche Weise eine Zahl in seine Bestandteile zerlegen kann.



  • Fuer 4150 ist n = 4 bei mir. Und sie taucht beispielsweise nicht in der Tabelle bei Wikipedia auf.

    appellieren seine schöne Lösung wieder in den Post aufzunehmen

    Gern, wenn sie er nicht mehr hat, ich habe sie noch. 🙂



  • ch hab sie nicht.



  • knivil schrieb:

    Fuer 4150 ist n = 4 bei mir.

    4[h]4[/h]+1[h]4[/h]+5[h]4[/h] != 4150
    

    knivil schrieb:

    Und sie taucht beispielsweise nicht in der Tabelle bei Wikipedia auf.

    Oh, dann kann die Rechnung meines letzten Posts ja gar nicht richtig sein 🙄


  • Mod

    knivil schrieb:

    Wird ein bisschen brauchen, alle Kombinationen durchzuprobieren

    Ich haette binaere Suche verwendet ... Alle Zahlen bis 2^53 durchzuprobieren bei 1GHz dauert wohl 9007199s bzw. 2501 Stunden.

    Doh! Das hätte ich vorher mal abschätzen sollen. Aber binäre Suche würde glaube ich nichts bringen, weil ich ja nicht weiß, ob alle Werte oberhalb einer bestimmten Basis fehlerhaft wären, wenn diese fehlerhaft ist. Mittlerweile ist mein Programm aber auch weit jenseits der dritten Wurzel von 2^53 angelangt, das heißt es wird bloß die ganze Zeit nur noch (basis hoch 2) getestet. Wenn wir mal annehmen, dass pow da keinen Fehler mehr macht (eventuell eine spezielle Implementierung für diesen Fall), dann wird da auch nichts mehr kommen.



  • Ich habe es einmal auf templates umgestellt, da ich die größte Zahl im Dezimalsystem ebenfalls berechnen lassen wollte:

    template<typename T>
    T mypow(const T& val,size_t exp)
    {
    	if(!exp)
    		return 1;
    	T ret=val;
    	for(size_t i=1;i<exp;++i)
    		ret*=val;
    	return ret;
    }
    
    template<typename T>
    int IsArmstrong(const T& val)
    {
    	const int MaxExp = 10; // bis wohin soll getestet werden?
    	T i; // wird immer auf den Wert von val gebracht, val dürfen wir nicht verändern
    	T res; // der berechnete Wert
    	for(int exp=1;exp<=MaxExp;++exp)
    	{
    		res = 0;
    		i = val;
    		do
    		{
    			res+=mypow(i%10,exp);
    		}while ((i/=10)>0);
    		if(res==val)
    			return exp;
    	}
    	return 0;
    }
    

    Der Returnwert gibt jetzt auch (sinnigerweise) den Exponenten zurück.
    Für den 32 Bit Bereich:

    1       0
    1       1
    1       2
    1       3
    1       4
    1       5
    1       6
    1       7
    1       8
    1       9
    3       153
    3       370
    3       371
    3       407
    4       1634
    5       4150
    5       4151
    4       8208
    4       9474
    5       54748
    5       92727
    5       93084
    5       194979
    6       548834
    7       1741725
    7       4210818
    7       9800817
    7       9926315
    7       14459929
    8       24678050
    8       24678051
    8       88593477
    9       146511208
    9       472335975
    9       534494836
    9       912985153
    

    @ SeppJ 👍 Ncht alles annehmen, testen!



  • 4       1634
    5       4150
    5       4151
    4       8208
    

    Hmm ... warum ist der Exponent 5? Zwar gilt fuer 5 das alle Ziffern hoch 5 zusammen addiert wieder die gleiche Zahl ergeben, aber es ist dennoch keine Armstrongzahl. Dazu muss der Exponent mit der der Anzahl der Ziffern uebereinstimmen. Ich habe es so gemacht: (highly advanced solution, nicht abschreiben, das faellt auf)

    unsigned int power(unsigned int n, unsigned int expo)
    {
        return expo ? n * power(n, expo-1) : 1;
    }
    
    unsigned int length(unsigned int n)
    {
        return (n < 10) ? 1 : 1 + length(n/10);
    }
    
    unsigned int armstrongHelper(unsigned int n, unsigned int len)
    {
        return n ? power(n%10,len) + armstrongHelper(n/10,len) : 0;
    }
    
    bool armstrong(unsigned int n)
    {
        return n == armstrongHelper(n,length(n));
    }
    

    Die Rekursion sollte vom Compiler wegoptimiert werden, habe mir aber den Assemblercode nicht angesehen.



  • Alles klar, jetzt erst weiß ich was du meinst:
    Es ist vom Wert der ersten Ziffer abhängig, desto einfacher sollte die Auswertung sein.
    Wie geschrieben, Armstrong-Zahlen waren mir unbekannt.


Anmelden zum Antworten