mehrdeutiger Aufruf einer überladener Funktion



  • Hallo Leute,
    ich habe mich bis jetzt lediglich alleine mit c++ rumgeschlagen, komme jetzt aber nicht wirklich weiter. Ich habe ein längeres Programm geschrieben welches mir noch 4 Fehler ausgibt, die alle sehr ähnlich sind. Wenn ich einen davon beheben kann, dann auch den Rest. Erstmal ein wenig Quellcode:

    Der Anfang:

    #include "stdafx.h"
    #include <iostream>
    using namespace std;
    #include <math.h>
    

    Und die Stelle des Problems:

    const double cMin = 2 * floor(sqrt(r)) * log(n);
    

    Als Fehler bekomme ich hier:
    Error C2668:'log' mehrdeutiger Aufruf einer überladener Funktion
    kann 'long double log(long double)' sein
    oder "float log(float)"

    Ich habe schon ein wenig probiert den Fehler zu beheben, durch eine Änderung habe ich es geschafft den Fehler zu ändern, sodass ich als Fehlerausgabe bekommen habe "unerwarteter Typ double".
    Ich hoffe ihr habt einen Tipp für mich.

    Schonmal Danke im Voraus.
    oder "double log(double)"



  • Welche Funktion soll denn genommen werden, wenn du log mit einem int aufrufst?



  • Meinst du welchen Logarithmus ich verwenden möchte? Oder wie soll ich das verstehen.

    Das gleiche Problem habe ich an einer anderen Stelle mit der CodeZeile

    const unsigned int iMax = sqrt(n) + 1;
    

    Gibt haargenau den gleichen Fehler nur mit sqrt anstatt mit log.

    Aber mit sqrt kann er doch nichts falsch verstehen.

    Anscheinend hängt es ja mit dem Typ zusammen, ob double,float etc...

    Aber ich denke ich habe deine Frage nicht gut genug verstanden.
    Solange bin ich noch nicht bei c++ dabei.


  • Mod

    Mit der Frage war gemeint: Es gibt drei Funktionen namens log . Eine nimmt einen float entgegen und gibt float zurück, eine macht das gleiche für double und eine für long double. Ein int ist weder ein float noch ein double noch ein long double. Aber ein int kann implizit in jeden dieser drei Typen umgewandelt werden. Wenn du der log-Funktion nun einen int gibst, dann ist unklar, welche der srei Funktionen gemeint ist und du musst daher eine explizite Umwandlung (static_cast) vornehmen, um die Mehrdeutigkeit aufzulösen.

    In C++11 gibt es übrigens noch eine Überladung für integrale Datentypen, da wäre der Fall für int eindeutig. Guck doch mal, ob dein Compiler C++11 kann.



  • #include <complex>
    
    ...
    
    std::sqrt<float>(r);
    std::log<float>(r);
    
    ...
    

  • Mod

    Sone schrieb:

    #include <complex>
    
    ...
    
    std::sqrt<float>(r);
    std::log<float>(r);
    
    ...
    

    Ich hoffe, das soll Klugscheißerei sein, dass es mehr als die drei von mir genannten Überladungen gibt, nicht als ernsthafte Alternative. Bei dir weiß man ja nie. Da du keinen Kommentar dazu abgibst, lege ich es mal zu deinem Vorteil als Klugscheißerei aus.



  • So, schonmal danke für die Hilfe, jetzt weiß ich wenigstens warum das Programm nicht funktioniert. Ich glaube aber, dass ich es noch nicht richtig verstehe mit static_cast umzugehen. Ich poste mal die kleine Teilfunktion des Programs hier vollständig:

    static bool IsPrime(unsigned int n)
    {
    	//unsigned long m;
    	if (n < 2) return false;
    	if (n < 4) return true;
    	if (n % 2 == 0) return false;
    	//m=static_cast<unsigned long>(n);
    
    	const unsigned int iMax = sqrt(n/*m*/) + 1;
    	unsigned int i;
    	for (i = 3; i <= iMax; i += 2)
    		if (n/*m*/ % i == 0)
    			return false;
    
    	return true;
    }
    

    Die Kommentar wären meine Änderung gewesen, leider ohne Erfolg 😕
    Long ist natürlich noch viel zu klein, aber darum geht es ja erstmal nicht.



  • "Ohne Erfolg" ist keine gute Fehlerbeschreibung. Davon abgesehen castest du nach long double. Wieso denn? SeppJ hat doch schon gesagt was für Typen gehen:

    Eine nimmt einen float entgegen und gibt float zurück, eine macht das gleiche für double und eine für long double. Ein int ist weder ein float noch ein double noch ein long double.

    Auch ein unsigned long ist keines der 3 Typen.

    So sollte es (z.B.) funktionieren:

    static bool IsPrime(unsigned int n)
    {
        if (n < 2) return false;
        if (n < 4) return true;
        if (n % 2 == 0) return false;
    
        const unsigned int iMax = sqrt(static_cast<double>(n)) + 1;
        unsigned int i;
        for (i = 3; i <= iMax; i += 2)
            if (n % i == 0)
                return false;
    
        return true;
    }
    


  • Kleiner Fehler: Das erste oben soll natürlich

    Davon abgesehen castest du nach unsigned long.

    heißen.



  • So, wie du es geschrieben hast sagt er:

    'Initialisierung': Konvertierung von 'double' in 'const unsigned int', möglicher Datenverlust

    Ansonsten kein Fehler mehr. Ich möchte ja große Primzahlen einsetzen(ca 1000 Binärstellen)



  • SeppJ schrieb:

    Sone schrieb:

    #include <complex>
    
    ...
    
    std::sqrt<float>(r);
    std::log<float>(r);
    
    ...
    

    Ich hoffe, das soll Klugscheißerei sein, dass es mehr als die drei von mir genannten Überladungen gibt, nicht als ernsthafte Alternative. Bei dir weiß man ja nie. Da du keinen Kommentar dazu abgibst, lege ich es mal zu deinem Vorteil als Klugscheißerei aus.

    Es sollte in der Tat Klugscheißerei sein. Aber erklär mir noch schnell, wieso das keine Alternative ist, weil hier implizit in ein complex<> und zurück gecastet wird? Oder weil der Algorithmus langsamer/anders ist?


  • Mod

    Sone schrieb:

    weil hier implizit in ein complex<> und zurück gecastet wird?

    Cast ist lustig. Das ist ein fetter Kontruktor und Konvertierungsoperator.

    Oder weil der Algorithmus langsamer/anders ist?

    Aber Hallo. Gib mal an, wie du den Logarithmus einer komplexen Zahl berechnest und den einer reellen Zahl und staune, wie unterschiedlich der Aufwand ist.



  • ray91 schrieb:

    So, wie du es geschrieben hast sagt er:

    'Initialisierung': Konvertierung von 'double' in 'const unsigned int', möglicher Datenverlust

    Ansonsten kein Fehler mehr. Ich möchte ja große Primzahlen einsetzen(ca 1000 Binärstellen)

    Das liegt daran das

    sqrt(static_cast<double>(n)) + 1;
    

    als double variante einen double zurückgibt. Diesen weißt du dann einem int zu (iMax). Eventuell vorhandene Nachkommastellen werden also einfach abgeschnitten. Das ist dann der Datenverlust. Wenn du 1000 Binärstellen haben willst, reichen aber allgemein solche Datentypen eh nicht, da müsstest du dich wohl schon nach einer extra Bibliothek umschaun, die dann wahrscheinlich auch eine völlig andere sqrt-Funktion anbieten.


  • Mod

    KMT schrieb:

    Das liegt daran das

    sqrt(static_cast<double>(n)) + 1;
    

    als double variante einen double zurückgibt. Diesen weißt du dann einem int zu (iMax). Eventuell vorhandene Nachkommastellen werden also einfach abgeschnitten. Das ist dann der Datenverlust.

    Das ist eigentlich das erwartete Verhalten. Der wirkliche Datenverlust entsteht bei Werten die größer als INT_MAX sind (bzw. kleiner als INT_MIN).



  • Hallo, ich habe noch eine kleine Frage. Anscheinend bin ich doof, denn ich finde den Fehler nicht.
    Folgender Quelltext:

    const unsigned int iMax = sqrt(n) + 1;
        unsigned int i;
    	bool m=true;
        for (i = 3; i <= iMax; i += 2)
    	{
    		 if (n % i == 0)
    		{
    			m=false;
    		}
    	}
    	if (m==true)
    	{
    		cout << "Primzahl";
    	}
    	else
    	{
    		cout << "Keine Primzahl";
    	}
    

    Für Zahlen wie 9 und 15 klappts.
    Aber ab 25 sagt er mir, es sei eine Primzahl. Woran liegt das? Das gleiche gilt für 49,121 etc. Irgendwas muss an meiner for-Schleife falsch sein.
    Ich denke es ist kein großes Problem, leider finde ich es nicht.

    Danke für die Hilfe!



  • Bitte C++-Tags nutzen.
    Ja, deine Schleife ist Blödsinn.
    Nimm lieber

    for (unsigned int i = 2; i < n / 2;++i)
            if (n % i == 0)
            {
                    std::cout << "Keine ";
                    break;
            }
    
    std::cout << "Primzahl!";
    


  • Ich würde das gerne mit dem iMax machen 😕 Das erspart viel Rechenarbeit bei großen Primzahlen.

    const unsigned int iMax = sqrt(n) + 1;
    for (unsigned int i = 3; i <= iMax / i+=2)
            if (n % i == 0)
            {
                    cout << "Keine Primzahl ";
                    break;
            }
    

    cout << "Primzahl";
    Hier sagt er mir trotzdem für Zahlen wie 121, dass es eine Primzahl sei..


  • Mod

    Zeig bitte deinen richtigen Code. Dein Codebeispiel kann unmöglich compilieren. Bitte nur Copy & Paste benutzen. Siehe dazu den dritten Link in meiner Signatur. Sonst verschwendest du nur unsere und deine Zeit mit Fehlern, die gar keine sind, sondern beim Abschreiben entstanden sind.



  • ray91 schrieb:

    Ich würde das gerne mit dem iMax machen 😕 Das erspart viel Rechenarbeit bei großen Primzahlen.

    Nein, tut es nicht. Compiler optimieren, weißt du. (Ich hoffe, n ist bei dir const )
    Und meine Version sagt für 121, Keine Primzahl! 😉


  • Mod

    Sone schrieb:

    ray91 schrieb:

    Ich würde das gerne mit dem iMax machen 😕 Das erspart viel Rechenarbeit bei großen Primzahlen.

    Nein, tut es nicht. Compiler optimieren, weißt du. (Ich hoffe, n ist bei dir const )

    Wieder Unsinn. Kein Compiler der Welt optimiert dir eine Schleife bis n/2 zu sqrt(n), weil er erkennt, dass die Bedingung nie wieder wahr wird. Mit diesem Argument könnte der Compiler anstatt die Schleife zu erzeugen auch erkennen, dass hier Primzahlen gesucht werden und stattdessen einen effizienten Algorithmus generieren. Hör gefälligst auf, zu jedem Thread Müll zu labern! Ich war die letzten 15 Minuten beschäftigt nur deinen Schrott zu korrigieren!



  • SeppJ schrieb:

    Sone schrieb:

    ray91 schrieb:

    Ich würde das gerne mit dem iMax machen 😕 Das erspart viel Rechenarbeit bei großen Primzahlen.

    Nein, tut es nicht. Compiler optimieren, weißt du. (Ich hoffe, n ist bei dir const )

    Wieder Unsinn. Kein Compiler der Welt optimiert dir eine Schleife bis n/2 zu sqrt(n), weil er erkennt, dass die Bedingung nie wieder wahr wird.

    Bist du doof oder so?
    Ich meinte, dass man nicht den Endindex in eine Variable auslagern muss!! Lies doch! 😡


Anmelden zum Antworten