Vereinfachung einer "C" Funktion

OP #4392535
Lesenswert?

Hallo
Ist nicht so wichtig doch ich dachte mir
fragste mal.

unsigned char GetPlot(char Kurve){
     int dummy;
     dummy = (round( pow(2, Kurve)));
     return ( dummy >> 1 );
}

funktioniert wunderbar nur kann man die Funktion, vereinfachen?

Das dumme dabei 2hoch8 ergibt 256 also 1 byte + 1
deswegen brauche ich den int dummy.
Vielleicht lerne ich mal wieder was

Danke im voraus
Gast #4392541
Lesenswert?

Wenn "Kurve" immer positiv ist, müsste dann nicht

unsigned char Kurve

als Übergabeformat eingetragen sein? Dann würde auch Dummy zu einem 
uint16 und somit könnte der Compiler das wahrscheinlich vereinfachen.
Gast #4392594
Lesenswert?

1
 dummy = (round( pow(2, Kurve)));
2
     return ( dummy >> 1 );

Du rechnest also Zwei hoch Kurve, um dann das Ergebins durch zwei zu 
teilen.

Warum dann nicht gleich Zwei hoch (Kurve-1) ?

EDIT:
Da Kurve immmer eine Ganzzahl ist, kommen auch nur Ganzzahlen als 
Ergebnis von pow raus. Somit sollte doch das round unnötig sein...?
Gast #4392634
Lesenswert?

Matthias L. schrieb:
>
1
>  dummy = (round( pow(2, Kurve)));
2
>      return ( dummy >> 1 );
3
>
>
> Du rechnest also Zwei hoch Kurve, um dann das Ergebins durch zwei zu
> teilen.
>
> Warum dann nicht gleich Zwei hoch (Kurve-1) ?
>
> EDIT:
> Da Kurve immmer eine Ganzzahl ist, kommen auch nur Ganzzahlen als
> Ergebnis von pow raus. Somit sollte doch das round unnötig sein...?

Und das pow ist auch gleich unnötig. Siehe meine Frage oben.

Wozu erst in double rechnen, wenn sowohl die Argumente als auch das 
Resultat integer sind?

Aber wie gesagt: Das wird Karl Heinz alles erklären, und:

"Vielleicht lernst Du mal wieder was".

So ein paar Grundlagen müssen ja auch mal gelernt werden.

Was noch bleibt, sind implzite Umwandlungen und Promotion.
#4392664
Lesenswert?

Klaus schrieb:

> Aber wie gesagt: Das wird Karl Heinz alles erklären, und:

Was soll ich da gross erklären?

Offenbar kann 'Kurve' sowíeso nur Werte zwischen 0 und 8 annehmen. 
Ansonsten würde der Return Datentyp keinen Sinn machen. Also wozu lange 
rumrechnen? Bei 9 verschiedenen Ergebnissen  macht man ein Array, in dem 
man die Werte im voraus ausrechnet und einen davon zurückliefert und gut 
ists.
Getreu dem alten Motto: Space for Time
OP #4392726
Lesenswert?

Danke für die vielen Antworten
ja round ist unnötig kommt noch von der funktion wo ich sinus noch drin 
hatte
sorry

nein kein array ich wollte nur wissen ob
ich den Buffer dummy int 16 bit weglassen könnte.

Als Hintergrund

Ich gebe auf ein LED Display mit 8 x 16 Led's
Das mache ich mit spi und zwei PIC16F887

Muster aus und da dachte fängst Du mal mit einer Sinuskurve an. .-)
#4392732
Lesenswert?

Martin M. schrieb:

> nein kein array ich wollte nur wissen ob
> ich den Buffer dummy int 16 bit weglassen könnte.

Mach dir deswegen keinen Kopf. Compiler sind gut darin, Variablen 
rauszuwerfen, die keiner braucht. Kümmere du dich um die Logik und 
überlass den Rest dem Compiler.

Wenn du die Funktion vereinfachen willst, dann sieh zu, dass du das pow 
los wirst und auch das round. Dort hast du Potential. Aber über 
funktionslokale Variablen brauchst du dir keinen Kopf machen, ausser es 
sind viele und ausser es sind Arrays. Aber aus deiner Funktion intern 
ein
1
unsigned char GetPlot(char Kurve){
2
  return (int)( (round( pow(2, Kurve))) ) >> 1;
3
}
zu machen, ist für eine Compiler eine leichte Übung. Nicht jede 
Variable, die in deiner Funktion vorkommt, führt auch dazu, dass 
irgendwo Speicher dafür reserviert wird. Compiler können das problemlos, 
dass sie über die Verwendung der Register Buch führen und welcher Wert 
wann in welchem Register liegt. Wenn es reicht, diesen Wert von dort 
wieder weiter zu verwenden, gibt es keinen Grund, warum der Wert jemals 
ins SRAM gespeichert werden soll. Wenn es nichts zu speichern gibt, 
braucht man auch keine Speicherreservierung dafür.

Aber all das soll dich nicht kümmern. Du kümmerst dich um die Logik und 
schreibst sie so, wie es für dich am verständlichsten ist. Wenn es mit 
Hilfsvariablen für dich am verständlichsten ist, dann schreibst du das 
eben mit Hilfsvariablen und der Compiler formt das wieder so um und 
stutzt es zurecht, dass die Hilfsvariable rausfliegt. Die dazu 
notwendige Technik beherrschen die Compilerbauer seit Jahrzehnten.
#4392750
Lesenswert?

Karl H. schrieb:
> Kümmere du dich um die Logik und überlass den Rest dem Compiler.

Genau so sieht's aus.

Wenn man nicht gerade einen total ungeeigneten Algorithmus verwendet, 
dann ist nahezu jeder Code gut solange er:

-korrekte Ergebnisse liefert (durch Tests nachgewiesen)
-lesbar und verständlich ist (auch nach Jahren noch)

Alles andere ist Zeit vergeudet an der falschen Stelle.

Übrigens: Für nicht genutzte Rechenzeit oder nicht genutzten Speicher 
gibt es kein Geld zurück ;-)
#4404338
Lesenswert?

Karl H. schrieb:
> Klaus schrieb:
>
>> Aber wie gesagt: Das wird Karl Heinz alles erklären, und:
>
> Was soll ich da gross erklären?
>
> Offenbar kann 'Kurve' sowíeso nur Werte zwischen 0 und 8 annehmen.
> Ansonsten würde der Return Datentyp keinen Sinn machen. Also wozu lange
> rumrechnen? Bei 9 verschiedenen Ergebnissen  macht man ein Array, in dem
> man die Werte im voraus ausrechnet und einen davon zurückliefert und gut
> ists.
> Getreu dem alten Motto: Space for Time

Genau das hab ich mich auch gefragt als ich den Post gelesen habe.
Ich würde es so schreiben:
1
unsigned char GetPlot(unsigned char Kurve) {
2
   int dummy[9] = {1, 2, 4, 8, 16, 32, 64, 128, 256};
3
   if ( ((unsigned int)Kurve-1) > 8 ) return -1; //parameter ausserhalb des zulaessigen Wertebereichs
4
   return (unsigned char)dummy[ (unsigned int)Kurve-1 ];
5
}

In C bin ich nicht sonderlich gut aber muss/sollte der Rückgabewert 
nicht auch unsigned char sein wenn die Funktion unsigned char ist?
@Martin
Und da ich es ungewöhnlich finde, dass du da einen char als 
Funktionsparameter hast: Du willst wirklich den Intergerwert des 
übergebenen Chars benutzen, es ist nicht so dass da als Zeichen eine 
z.B. 6 (hat den Integerwert 54) kommt?
Gast #4404341
Lesenswert?

Michael K. schrieb:
> Ich würde es so schreiben

die ganzen gast sind unnötig.
1
unsigned char GetPlot(unsigned char Kurve) {
2
   unsigned char dummy[] = {1, 2, 4, 8, 16, 32, 64, 128, 256};
3
   //parameter ausserhalb des zulaessigen Wertebereichs
4
   if ( Kurve > 9 || Kurve < 1  ) {
5
      return -1;
6
   } 
7
   return dummy[ Kurve-1 ];
8
}

Cast verwendet man nur wenn man den Compiler zu etwas zwingen will, 
dafür sehe ich hier keine Grund.
Gast #4404350
Lesenswert?

Warum überhaupt ein Array ?

Im oben genannten Fall ist ein Shift-Left viel schneller und braucht 
weniger Code als ein Array.

Also:
1
unsigned char GetPlot(unsigned char Kurve) {
2
   //parameter ausserhalb des zulaessigen Wertebereichs
3
   if ( Kurve > 8 || Kurve == 0  ) {
4
      return -1;
5
   } 
6
   return 1 << (Kurve-1);
7
}
#4404382
Lesenswert?

Peter II schrieb:
> Shift schrieb:
>> Im oben genannten Fall ist ein Shift-Left viel schneller und braucht
>> weniger Code als ein Array.
>
> schnell ist abhängig von der CPU. Bei den Atmels kann das Array durchaus
> schneller sein.

Zumindest bei AVR. Da dieser nicht shiften kann, muss er einen Shift 
über eine variable Anzahl von Bits über wiederhote Additionen in einer 
Schleife nachbilden.

Michael K. schrieb:
> unsigned char GetPlot(unsigned char Kurve) {
>
> if ( ((unsigned int)Kurve-1) > 8 ) return -1; //parameter ausserhalb
> des zulaessigen Wertebereichs

Wenn man negative Werte zurückliefern will, sollte der Return-Typ aber 
auch vorzeichenbehaftet sein.
#4404386
Lesenswert?

Shift schrieb:
> Warum überhaupt ein Array ?
>
> Im oben genannten Fall ist ein Shift-Left viel schneller und braucht
> weniger Code als ein Array.
>
> Also:
>
1
> unsigned char GetPlot(unsigned char Kurve) {
2
>    //parameter ausserhalb des zulaessigen Wertebereichs
3
>    if ( Kurve > 8 || Kurve == 0  ) {
4
>       return -1;
5
>    }
6
>    return 1 << (Kurve-1);
7
> }
8
>

Kommt auf den Prozessor an.
Auf einem AVR muss dein 1<<(Kurve-1) zu dem hier umgeformt werden:
1
....
2
    unsigned char mask = 0x01;
3
    {
4
      unsigned char tmp;
5
      for( tmp = Kurve; tmp > 0; tmp-- )
6
        mask <<= 1;
7
    }
8
    return mask;

immer noch überzeugt, dass das in allen Fällen schneller ist als ein 
simpler Array Zugriff, d.h. eine Dereferenzierung eines Basepointer + 
Offset? Vor allen Dingen dann, wenn man das Array static macht, so dass 
es nicht jedesmal neu initialisiert werden muss.

Auf einem AVR willst du keine Shifts mit variabler Anzahl an Bits haben, 
wenn es auch andere Möglichkeiten gibt.
Gast #4404395
Lesenswert?

sinnvollerweise sollte das Array aber noch const static sein. Und die 
Anmerkung mit dem return -1 sollte man auch berücksichtigen.

also neuer versuch
1
unsigned char GetPlot(unsigned char Kurve) {
2
   static const unsigned char dummy[] = {1, 2, 4, 8, 16, 32, 64, 128, 256};
3
   //parameter ausserhalb des zulaessigen Wertebereichs
4
   Kurve--;
5
   if ( Kurve > sizeof(dummy) ) {
6
      return 0;
7
   } 
8
   return dummy[ Kurve ];
9
}
#4404528
Lesenswert?

Ich sagte ja, so doll bin ich in C nicht. Und ob jetzt Shift oder Array 
schneller ist auf dem AVR weiß/wusste ich auch nicht. Und klar, das 
return -1 ist für unsigned auch wenig schön. In der Regel schreib ich 
ein Programm/Funktion erst mal so runter und kümmere mich dann um die 
Warnings die mir der Compiler nennt. Ich hab ETechnik studiert und unser 
Informatik-Prof hat uns beigebracht: Es gibt keinen Grund Warnings zu 
ignorieren! Ich hab aber obige Funktion nicht dem Compiler zum 
verarbeiten gegeben gehabt, das war mehr frei Schnautze runter 
geschrieben ;)
#4404532
Lesenswert?

Conny G. schrieb:
> Returnwert -1 und unsigned char geht doch nicht zusammen, oder?
> Müsste int sein, damit man das -1 auch rausbekommt.
>
> Ah, ja, Peter hat's schon geschrieben.

Richtig, da käme 255 raus und das ist auch das Problem, dass ich mit dem 
Funktionswert sehe: wie kann die Funktion 256 zurückliefern wenn sie 
unsigned char ist? Das geht nur bis 255 ;)
#4404533
Lesenswert?

Conny G. schrieb:
> Returnwert -1 und unsigned char geht doch nicht zusammen, oder?
> Müsste int sein, damit man das -1 auch rausbekommt.

Die erste Frage sollte allerdings lauten:
Kann es überhaupt passieren, dass hier der Funktion ein ungültiges 
Argument übergeben wird oder ist das durch die Vorgeschichte schon 
ausgeschlossen und es reicht in diesem Fall (wenn überhaupt) zb immer 
das Ergebnis für 0 zu liefern.
#4404536
Lesenswert?

Michael K. schrieb:

> unser
> Informatik-Prof hat uns beigebracht: Es gibt keinen Grund Warnings zu
> ignorieren!

Das ist auch richtig so.
In der professionellen Programmierung wird das so gehandhabt, dass der 
Compiler auf dem höchsten (oder zweithöchsten) Warninglevel einen 
Programmtext ohne jegliche Warnung compilieren muss. Alles andere wird 
als fehlerhaft gewertet und muss behoben werden. Egal ob echter Fehler 
oder Warnung. Nur allzuoft sind Warnungen tatsächliche Probleme, die 
nicht ignoriert werden können.
#4404539
Lesenswert?

Peter II schrieb:
> sinnvollerweise sollte das Array aber noch const static sein. Und die
> Anmerkung mit dem return -1 sollte man auch berücksichtigen.

Warum static? Sorgt das nicht dafür, dass ein Teil des RAMs für das 
Array reserviert bleibt auch wenn die Funktion grade gar nicht benutzt 
wird?
Und return 0 würde ich auf keinen Fall machen, ein retrun 0 lese ich 
immer als "kein Fehler", hier wäre aber ein Fehler aufgetreten. Ob ich 
mich nach 5 Monaten noch dann dabei erinnern würde, wenn ich mir den 
Code noch mal anschaue, dass das return 0 hier dann bedeutet, dass ein 
Fehler auftrat? Ne, da auf jeden Fall was anderes, am liebsten halt ein 
return -1 und da IMO die funktion eh einen anderen Datentyp als unsigned 
char braucht würde ich hier gleich was signed benutzen.
#4404546
Lesenswert?

Michael K. schrieb:
> Peter II schrieb:
>> sinnvollerweise sollte das Array aber noch const static sein. Und die
>> Anmerkung mit dem return -1 sollte man auch berücksichtigen.
>
> Warum static? Sorgt das nicht dafür, dass ein Teil des RAMs für das
> Array reserviert bleibt auch wenn die Funktion grade gar nicht benutzt
> wird?

Tut es.
Aber erstens sind es nur 8 Byte und zweitens fällt dann die ständige 
Initialisierung des Arrays beim AUfruf der Funktion weg.

Wer will, kann das Array ja auch noch ins Flash legen. Das ist dann der 
speichertechnisch günstigste Fall.

> Und return 0 würde ich auf keinen Fall machen, ein retrun 0 lese ich
> immer als "kein Fehler", hier wäre aber ein Fehler aufgetreten.

Kommt drauf an.
Das ist ganz klar eine Berechnungsfunktion, bei der ein Wert ungleich 0 
ein sinnvolles Resultat ist, während 0 nicht vorkommen kann.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren