Größtes Element aus Werteliste ermitteln



  • Hallo zusammen,

    gibt es in C eine Funktion oder ein Makro, das mir aus einer Liste von double-Werten den größten zurück gibt?
    Sowas wie "max_element" in C++ oder __max(a,b) für zwei Werte, dann eben für drei also: __max(a,b,c)

    Gruss,
    Torben



  • ^^gibts bestimmt irgendwo, sind nur keine standard-funktionen. aber sowas kannste dir doch leicht selber proggen. ausserdem ist max(a,b,c) doch max(max(a,b),c). oder nicht?
    🙂



  • Hallo,

    meinst du soetwas?

    #include <stdlib.h>
    #include <stdarg.h>
    #include <float.h>
    
    #include <stdio.h>
    
    double dmax(int n, ...)
    {
    	double max = DBL_MIN;
    	va_list a;
    
    	va_start(a, n);
    	while (--n > 0) {
    		double e = va_arg(a, double);
    		max = e > max ? e : max;
    	}
    
    	va_end(a);
    	return max;
    }
    
    int main()
    {
    	double a = 2.2, b = 3.3, c = 5.5, d = 4.4;
    	printf("%f\n", dmax(4, a, b, c, d));
    	return EXIT_SUCCESS;
    }
    

    Oder möchtest du das Maximum aus einem Array bestimmen?

    #include <stdlib.h>
    #include <math.h>
    #include <float.h>
    
    #include <stdio.h>
    
    void* max(void *base, size_t nmemb, size_t size,
    	  int (*compar) (const void *, const void *))
    {
    	register unsigned char *i, *r, *max;
    
    	i = r = max = base;
    	r += nmemb * size;
    
    	while (i < r) {
    		if (compar(i, max) > 0)
    			max = i;
    		i += size;
    	}
    
    	return max;
    }
    
    static int cmp(const void *p1, const void *p2)
    {
    	double v1, v2;
    
    	v1 = *(const double *)p1;
    	v2 = *(const double *)p2;
    
    	if (fabsl(v1 - v2) < DBL_EPSILON)
    		return 0;
    	return v1 < v2 ? -1 : 1;
    }
    
    int main()
    {
    	double v[] = { }, *m;
    	size_t n = sizeof(v) / sizeof(double);
    
    	m = max(v, n, sizeof(double), cmp);
    	printf("%f\n", *m);
    
    	free(m);
    	return EXIT_SUCCESS;
    }
    

    Grüße
    Martin



  • Hola!
    Wie wäre es mit einer simplen, intuitiven Lösung für ein Array:

    #include <stdio.h>
    
    double maximum ( double w[], unsigned n )
    {
        double max = w[0];
        unsigned i = 1;
        while ( i < n )
        {
            if ( w[i] > max )
                    max = w[i++];
        }
        return max;
    }
    
    int main(int argc, char *argv[])
    {
        double werteliste[] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 };
        printf( "Maximum: %f", maximum( werteliste, sizeof ( werteliste )
        / sizeof(double)));
    
        system("PAUSE");	    
        return 0;
    }
    

    Gruß
    h.



  • @hobbyprogger:

    Für

    double werteliste[] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 5.0 };
    /* 5.0 doppelt */
    

    läuft dein Programm in eine Endlosschleife.

    Grüße



  • Außerdem:

    Dangerous comparison involving double types:
    Two real (float, double, or long double) values are compared directly using a
    C primitive. This may produce unexpected results since floating point
    representations are inexact. Instead, compare the difference to FLT_EPSILON
    or DBL_EPSILON.

    Es macht also durchaus Sinn die Vergleichsfunktion auszulagern. So wird die Funktion zur Bestimmung des Maximums nicht zu lang und Benutzer können den Vergleich nach den Erfordernissen programmieren.

    @hobbyprogger: Dennoch eine schöne Lösung. 🙂

    Grüße



  • jo, da haddu recht, die endlosschleife kann man ja so verhindern:

    while ( i < n ) 
    { 
        if ( w[i] > max ) 
        {
            max = w[i]; 
        }
        i++;
    }
    

    mit dem
    DBL_EPSILON zeugs peil ich jetzt nicht. gruß,
    h.



  • oder man nimmt ganz intuitiv eine for-Schleife.

    double max(double const *array, size_t n) {
      assert(array);
      double max = DBL_MIN;
      for(size_t i = 0; i < n; ++i) {
        if(array[i] > max) {
          max = array[i];
        }
      }
      return max;
    }
    

    @lucky_tux
    das bezieht sich eher auf den Vergleich mit ==. Weil wegen der endlichen Präzision mathematisch äquivalente Rechnungen nicht zum gleichen Ergebnis kommen können und es immer einen gewissen Fehler geben kann.



  • lucky_tux schrieb:

    Dangerous comparison involving double types:
    Two real (float, double, or long double) values are compared directly using a
    C primitive. This may produce unexpected results since floating point
    representations are inexact. Instead, compare the difference to FLT_EPSILON
    or DBL_EPSILON.

    Bei einem reinen > Vergleich sollte das kein Problem sein.

    lucky_tux schrieb:

    Es macht also durchaus Sinn die Vergleichsfunktion auszulagern. So wird die Funktion zur Bestimmung des Maximums nicht zu lang und Benutzer können den Vergleich nach den Erfordernissen programmieren.

    Dann sieht der Aufruf so aus?:

    T max = maximum (array, sizeof(array)/sizeof(*array), sizeof(*array), callback);
    

    Na ich weiss nicht :p



  • die nehm ich 🙂



  • hobbyprogger schrieb:

    Hola!
    Wie wäre es mit einer simplen, intuitiven Lösung für ein Array:

    #include <stdio.h>
    
    double maximum ( double w[], unsigned n )
    {
        double max = w[0];
        unsigned i = 1;
        while ( i < n )
        {
            if ( w[i] > max )
                    max = w[i++];
        }
        return max;
    }
    
    ...
    

    Gruß
    h.

    Was ist, wenn nach dem größten Element noch ein kleineres kommt ?

    Dann wird i nicht mehr inkrementiert und du hast auch eine Endlosschleife, oder ?



  • Korhil schrieb:

    hobbyprogger schrieb:

    Hola!
    Wie wäre es mit einer simplen, intuitiven Lösung für ein Array:

    #include <stdio.h>
    
    double maximum ( double w[], unsigned n )
    {
        double max = w[0];
        unsigned i = 1;
        while ( i < n )
        {
            if ( w[i] > max )
                    max = w[i++];
        }
        return max;
    }
    
    ...
    

    Gruß
    h.

    Was ist, wenn nach dem größten Element noch ein kleineres kommt ?

    Dann wird i nicht mehr inkrementiert und du hast auch eine Endlosschleife, oder ?

    ist doch schon längst verbessert worden:

    while ( i < n )
    {
        if ( w[i] > max )
        {
            max = w[i];
        }
        i++;
    }
    

    comprende?



  • h schrieb:

    Korhil schrieb:

    hobbyprogger schrieb:

    Hola!
    Wie wäre es mit einer simplen, intuitiven Lösung für ein Array:

    #include <stdio.h>
    
    double maximum ( double w[], unsigned n )
    {
        double max = w[0];
        unsigned i = 1;
        while ( i < n )
        {
            if ( w[i] > max )
                    max = w[i++];
        }
        return max;
    }
    
    ...
    

    Gruß
    h.

    Was ist, wenn nach dem größten Element noch ein kleineres kommt ?

    Dann wird i nicht mehr inkrementiert und du hast auch eine Endlosschleife, oder ?

    ist doch schon längst verbessert worden:

    while ( i < n )
    {
        if ( w[i] > max )
        {
            max = w[i];
        }
        i++;
    }
    

    comprende?

    por supuesto



  • ja, geanu sowas habe ich gemeint, wobei die Schleife wohl einen Wert vergisst.

    lucky_tux schrieb:

    Hallo,

    meinst du soetwas?

    #include <stdlib.h>
    #include <stdarg.h>
    #include <float.h>
    
    #include <stdio.h>
    
    double dmax(int n, ...)
    {
    	double max = DBL_MIN;
    	va_list a;
    
    	va_start(a, n);
    	while (--n > 0) {
    		double e = va_arg(a, double);
    		max = e > max ? e : max;
    	}
    
    	va_end(a);
    	return max;
    }
    
    int main()
    {
    	double a = 2.2, b = 3.3, c = 5.5, d = 4.4;
    	printf("%f\n", dmax(4, a, b, c, d));
    	return EXIT_SUCCESS;
    }
    

    Oder möchtest du das Maximum aus einem Array bestimmen?

    #include <stdlib.h>
    #include <math.h>
    #include <float.h>
    
    #include <stdio.h>
    
    void* max(void *base, size_t nmemb, size_t size,
    	  int (*compar) (const void *, const void *))
    {
    	register unsigned char *i, *r, *max;
    
    	i = r = max = base;
    	r += nmemb * size;
    
    	while (i < r) {
    		if (compar(i, max) > 0)
    			max = i;
    		i += size;
    	}
    
    	return max;
    }
    
    static int cmp(const void *p1, const void *p2)
    {
    	double v1, v2;
    
    	v1 = *(const double *)p1;
    	v2 = *(const double *)p2;
    
    	if (fabsl(v1 - v2) < DBL_EPSILON)
    		return 0;
    	return v1 < v2 ? -1 : 1;
    }
    
    int main()
    {
    	double v[] = { }, *m;
    	size_t n = sizeof(v) / sizeof(double);
    
    	m = max(v, n, sizeof(double), cmp);
    	printf("%f\n", *m);
    
    	free(m);
    	return EXIT_SUCCESS;
    }
    

    Grüße
    Martin


Anmelden zum Antworten