max index berechnen
-
hallo,
ich versuche max Element und dessen Index berechnen. Meine Programmasschnitt:
#ifndef max #define max(a,b) (((a) > (b)) ? (a) : (b)) #endif double max_element( std::vector<double> vector ) { double max_element= 0.0; for(int l = 0; l < (int)vector.size(); l++) { max_dist = max(vector[l], max_dist); } return max_element; }wie kann ich index des max_element finden?
danke und gruß
ns
-
Mit einem Tick besseren Deutsch, würde ich wohl verstehen, was genau du möchtest. Außerdem ist dein Code fehlerhaft und das nicht von der Logik her.
-
Es ist doch immer wieder schön zu sehen, dass die STL ein wenig mitmacht.

Da siehst du btw. auch, wie man das korrekt implementiert.
-
drakon schrieb:
...
Gib zu, du hast geraten was er wollte

-
Ersetz das Makro durch eine inline-Funktion.

-
Unter der Annahme, dass du dies zur Übung selber machst, empfehle ich dir mal nicht den fertigen Algorithmus aus der STL dazu, sondern erweitere deinen Ansatz. Du nimmst am besten noch eine zweite Variable in der du den Index speicherst. Und jedes mal, wenn du ein neues größtes Element gefunden hast, änderst du diese Variable. Dann brauchst du auch nicht dieses doofe Makro (wie kommst du da eigentlich drauf?), abgesehen davon gibt es natürlich auch ein typensicheres max, ebenfalls aus der STL.
std::pair<int,double> max_element( std::vector<double> vector ) // Wir wollen zwei Werte zurückgeben { double max_elem = -1/0.; // (-Unendlich) dürfte die kleinste Zahl sein :-) int max_index = 0; for(unsigned int i = 0; i < vector.size(); i++) // Was spricht gegen unsigned int? int musstest du aus gutem Grund von Hand casten, denn es gibt keine negativen Indizes { if (vector[i] > max_elem) // Momentanes Element ist größer als bisheriges Maximum { max_elem = vector[i]; // Speichere neues Maximum... max_index = i; // ...und passenden Index } } return std::pair<int, double>(max_index,max_elem); }
-
-1/0.; ist eine dubiose Operation, da die interne Darstellung von float/double-Typen implementationsabhängig ist. Besser ist es
numeric_limits<double>::min()zu verwenden, oder noch besser, weil einfacher,
max_elem = vector[0];zu setzen. Die Schleife kann dann ab 1 laufen.
-
make it right schrieb:
-1/0.; ist eine dubiose Operation, da die interne Darstellung von float/double-Typen implementationsabhängig ist. Besser ist es
numeric_limits<double>::min()zu verwenden, oder noch besser, weil einfacher,
max_elem = vector[0];zu setzen. Die Schleife kann dann ab 1 laufen.
Auch das ist schlecht. Denn was ist wenn die Liste leer ist?
Index auf -1 setzen und zur Not dies auch zurückgeben, was dem geneigten Nutzer vermittelt das kein maximales gefunden wurde (weil leer).
EDIT:
Und warum eigentlich eine Kopie von dem vector übergeben statt einer Referenz?
-
@Fellhuhn & make it right: Weil der Fragesteller offensichtlich ein absoluter Beginner ist. Ich wollte ihn jetzt nicht noch mit limits, Referenzen und Sonderfällen verwirren sondern ihm erstmal nur zeigen wie man sowas überhaupt macht. Das Programm lässt er dann dreimal laufen und freut sich dass es funktioniert. Und er versteht hoffentlich die Grundidee. Das dabei vom Expertenstandpunkt gesehen nicht alles optimal gelöst ist, ist dabei doch völlig egal - wahrscheinlich schreibt er schon jetzt das nächste Übungsprogramm und hat dieses längst vergessen.
-
Fellhuhn schrieb:
Auch das ist schlecht. Denn was ist wenn die Liste leer ist?
das musst du sowieso abfangen, sonst gibts du ja den index 0 zurück.
-
So, hier mal die funktionale Variante fuer C++. Der Typparameter double kann auch noch generalisiert werden:
#include <iostream> #include <utility> #include <numeric> struct Triple { int currentIndex_; int maxIndex_; double value_; Triple(int currentIndex, int maxIndex, double value) : currentIndex_(currentIndex), maxIndex_(maxIndex), value_(value) {} }; // define a reduce function for accumulate (fold) Triple maxIndex(Triple acc, double value) { if (acc.value_ < value) { acc.maxIndex_ = acc.currentIndex_; ++acc.currentIndex_; acc.value_ = value; } else { ++acc.currentIndex_; } return acc; } int main() { double i[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6 }; Triple v = std::accumulate(i+1,i+14, Triple(1,0,i[0]), maxIndex); std::cout << "Index: " << v.maxIndex_ << " Value: " << v.value_ << std::endl; return 0; }
-
knivil schrieb:
So, hier mal die funktionale Variante fuer C++. Der Typparameter double kann auch noch generalisiert werden:
wtf?
-
Shade Of Mine schrieb:
wtf?
Naja:
1te Ueberlegung: Wie wuerde ich das funktional machen -> fold ...
2te Ueberlegung: Was ist in C++ aequivalent zu fold -> accumulate ...accumulate ist eine Funktion hoeherer Ordnung (hat als Parameter eine Funktion) ... deswegen funktional ...
Wollte man nur das maximale Element wissen, so reduziert sich die Vergleichsfunktion auf eben std::max.
-
da hat mir das kurze fold aber besser gefallen:
Triple maxIndex(Triple acc, double value) { return Triple( acc.currentIndex, acc.value < value ? acc.maxIndex : acc.currentIndex, acc.value < value ? acc.value : value ); }cooler ist natürlich wenn Triple nur einen int als currentIndex hat und ein Objekt für das index/max pair, dann kannst du
Triple maxIndex(Triple acc, double value) { return Triple( acc.currentIndex+1, acc.value < value ? acc.pair : Pair(value, acc.currentIndex) ); }machen
-
Ja, die Loesung war jetzt auch nur schnell out of the box um das Prinzip zu verdeutlichen. Sicher gibt es noch einige Kniffe, komplett getestet ist es auch nicht ... Deine Variante wuerde ich allein der Laenge wegen vorziehen.
-
Da gefällt mir die Lösung von SeppJ 100x besser.