www.mikrocontroller.net

Forum: PC-Programmierung Runden einer Dezimalzahl in C


Autor: Radon (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
Ich habe ein kleines Programm zum üben geschrieben:

#include <stdio.h>
#include <conio.h>

int main()
{
  int eins,zwei,drei,vier,fuenf,sechs,summe;
  float schnitt;
  printf("\nNotendurchschnittsrechner\n");
  printf("\t\nNote:\tAnzahl:\n");
  printf("  I\t");   scanf("%i",&eins);
  printf(" II\t");  scanf("%i",&zwei);
  printf("III\t"); scanf("%i",&drei);
  printf(" IV\t");  scanf("%i",&vier);
  printf("  V\t");   scanf("%i",&fuenf);
  printf(" VI\t");  scanf("%i",&sechs);
  summe=eins+zwei+drei+vier+fuenf+sechs;
  schnitt=(eins*1+zwei*2+drei*3+vier*4+fuenf*5+sechs*6)/summe;
  printf("\nAnzahl der Schler: %i\n",summe);
  printf("\nNotendurchschnitt: %.2f\n\n",schnitt);
  printf("\n by Radon");
printf ("\n\t\t\tTaste druecken, um Programm zu beenden...");
getch();
}

Es soll den Notendurchschnitt einer Arbeit berechnen (Ich denke es ist
leicht zu verstehen). Das Problem ist, dass das Ergebnis auf ganze
Zahlen gerundet wird. Wisst ihr welchen Typ von Variable ich benutzen
sollte für Dezimalzahlen mit Kommastellen? Oder liegt es daran, dass in
der Rechnung schon gerundet wird?
Mfg Radon

Autor: flyingwolf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
deklarier doch mal "Summe" als float

Autor: Tobi H. (tobi-) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oder nen bissl casten:
schnitt=(float)(eins*1+zwei*2+drei*3+vier*4+fuenf*5+sechs*6)/(float)summ 
e;

Autor: Blackbird (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gehört nicht unmittelbar zur Fragestellung, könnte aber interessant
sein?

Runden, auf eine Stelle nach dem Komma ohne Verwendung von
Bibliotheken:

double dSum = 3.66;
sum = ((int)(sum * 10 + 0.5)) / 10; // sum = 3.7

2 Stellen nach dem Komma:
double dSum = 3.664;
sum = ((int)(sum * 100 + 0.5)) / 100; // sum = 3.66

Kann auch als Macro oder Inline-Funktion verwendet werden.

Blackbird
Code ist nicht getestet.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> double dSum = 3.66;
> sum = ((int)(sum * 10 + 0.5)) / 10; // sum = 3.7

Das funktioniert so nicht, denn du führst eine Integer-Division durch.
Das Ergebnis wird keine Nachkommastellen mehr haben.
Auch, wenn du das behebst, geht das nur für positive Zahlen gut.

Autor: Radon (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke an alle die mir geantwortet haben!

Ich habe es nacht Tobis Vorschlag gemacht:

schnitt=(float)(eins*1+zwei*2+drei*3+vier*4+fuenf*5+sechs*6)/(float)summ 
e;

Vielen Dank dafür.

Einfach ein super Forum muss ich sagen. Immer nach ein paar Stundenen
massig Antworten!

Autor: Blackbird (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Rolf, danke für den Tip.

/* Source-File: runden.c */
#include <stdio.h>

int main (void)
{
  double dSum = 3.66;
  double dSum2 = 3.664;

  printf ("\nSum=%f\t", dSum);
  dSum = ((int)(dSum * 10.0 + 0.5)) / 10.0; /* dSum = 3.7 */
  printf ("Sum=%f", dSum);

  printf ("\nSum=%f\t", dSum2);
  dSum2 = ((int)(dSum2 * 100.0 + 0.5)) / 100.0; /* dSum2 = 3.66 */
  printf ("Sum=%f\n", dSum2);

  return 0;
}

Nein, für negative Zahlen geht' so nicht.

Blackbird

Autor: Rolf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zum Runden, auch mit negativen Zahlen, gibt's diverse Makros:

// Dividing of (unsigned) integer numbers with good rounding (with
minimized quantisation error).
// Integer division (of positive numbers) ignores everything behind the
point while good rounding
// rounds up >= .5 and rounds down < .5.
#   define mc_POS_DIV(a, b)  ( (a)/(b) +  ( ( (a) % (b) >= (b)/2 ) ? 1
: 0 ) )

// Rounding with minimized quantization error and casting the
(float/double....; NOT complex/imaginary) argument.
//  Necessary for the undefined integer casting rounding behavior at
negative values
// (see C-FAQs or ANSI/ISO standard).
// Before the rounding you should check for nan and do limit the value.
Example:
// float foo; int i; ...; if (isnanf(foo)) foo = 0; mc_LIMIT(INT_MIN,
foo, INT_MAX); i = mc_ROUND_SINT(foo);
#   define mc_ROUND_SLONGLONG(x) ( ( (x) > 0. ) ?  (signed long long
int)((x) + 0.5) : -(signed long long int)(-(x) + 0.5) )
#   define mc_ROUND_SLONG(x) ( ( (x) > 0. ) ?  (signed long int)((x) +
0.5) : -(signed long int)(-(x) + 0.5) )
#   define mc_ROUND_SINT(x) ( ( (x) > 0. ) ?  (signed int)((x) + 0.5) :
-(signed int)(-(x) + 0.5) )
#   define mc_ROUND_SSHINT(x) ( ( (x) > 0. ) ?  (signed short int)((x)
+ 0.5) : -(signed short int)(-(x) + 0.5) )
#   define mc_ROUND_SC(x) ( ( (x) > 0. ) ?  (signed char)((x) + 0.5) :
-(signed char)(-(x) + 0.5) )
#   define mc_ROUND_ULONGLONG(x) ( ( (x) > 0. ) ?  (unsigned long long
int)((x) + 0.5) : (unsigned long long int)0 )
#   define mc_ROUND_ULONG(x) ( ( (x) > 0. ) ?  (unsigned long int)((x)
+ 0.5) : (unsigned long int)0 )
#   define mc_ROUND_UINT(x) ( ( (x) > 0. ) ?  (unsigned int)((x) + 0.5)
: (unsigned int)0 )
#   define mc_ROUND_USHINT(x) ( ( (x) > 0. ) ?  (unsigned short
int)((x) + 0.5) : (unsigned short int)0 )
#   define mc_ROUND_UC(x) ( ( (x) > 0. ) ?  (unsigned char)((x) + 0.5)
: (unsigned char)0 )
#   define mc_ROUND_int64(x) ( ( (x) > 0. ) ?  (int64_t)((x) + 0.5) :
-(int64_t)(-(x) + 0.5) )
#   define mc_ROUND_int32(x) ( ( (x) > 0. ) ?  (int32_t)((x) + 0.5) :
-(int32_t)(-(x) + 0.5) )
#   define mc_ROUND_int16(x) ( ( (x) > 0. ) ?  (int16_t)((x) + 0.5) :
-(int16_t)(-(x) + 0.5) )
#   define mc_ROUND_int8(x) ( ( (x) > 0. ) ?  (int8_t)((x) + 0.5) :
-(int8_t)(-(x) + 0.5) )
#   define mc_ROUND_uint64(x) ( ( (x) > 0. ) ?  (uint64_t)((x) + 0.5) :
(uint64_t)0 )
#   define mc_ROUND_uint32(x) ( ( (x) > 0. ) ?  (uint32_t)((x) + 0.5) :
(uint32_t)0 )
#   define mc_ROUND_uint16(x) ( ( (x) > 0. ) ?  (uint16_t)((x) + 0.5) :
(uint16_t)0 )
#   define mc_ROUND_uint8(x) ( ( (x) > 0. ) ?  (uint8_t)((x) + 0.5) :
(uint8_t)0 )
#   define mc_ROUND_int(x) ( ( (x) > 0. ) ?  (int)((x) + 0.5) :
-(int)(-(x) + 0.5) )
// todo: macros for uint_fast64_t, uint_fast32_t, ...

Autor: Kate (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Können Sie mir bitte helfen diese aufgabe 9,1 muss ich aug ganze runden

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kate wrote:
> Können Sie mir bitte helfen diese aufgabe 9,1 muss ich aug ganze runden

Wo liegt das Problem?

Wenn du eine Fliesskommazahl an einen int zuweist, werden die
Nachkommastellen abgeschnitten.
Aus  3.2  wird so 3
Aber: aus 3.7  wird ebenfalls 3


Wenn man aber vorher zu der Zahl 0.5 dazuaddiert, dann wird
aus 3.2  zunächst 3.7 und davon die Kommastellen abgeschnitten
ergibt 3. So wie es sein soll.

Hat man 3.7, so wird das durch die Addition von 0.5 zu 4.2 und
davon die Kommastellen abgeschnitten macht das 4. Genau so wie
es sein soll. 3.7 auf ganze Zahlen gerundet ergibt 4

Für negative Zahlen läuft es andersrum, man muss 0.5 abziehen
int round( double Value )
{
  if( Value > 0.0 )
    return (int)( Value + 0.5 );

  if( Value < 0.0 )
    return (int)( Value - 0.5 );

  return 0;
}

Autor: imon (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ein if mit ein Floating Wert kann gut gehen muss es aber nicht.

in sofern habe ich immer Bauchschmerzen wenn mir einer eine Lösung wie

 if( Value > 0.0 )

vorschlagt.

außerdem stellt der Standardheader math.h die Funktion round zur 
Verfügung die genau das macht, einen Floating Wert mathematisch korrekt 
zu runden.

Sollte der Compiler die den Header nicht bereitstellen widerspricht das, 
der ISO 9899:1999 und der Compiler sollte auf ein PC ausgemustert 
werden. Hier gibt es wirklich genug Funktionierende ISO konforme 
Compiler so das ich dort echt kein Grund sehe mich mit solchen Kaputen 
fast C Compiler zum zu schlagen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
imon wrote:
> Ein if mit ein Floating Wert kann gut gehen muss es aber nicht.
>
> in sofern habe ich immer Bauchschmerzen wenn mir einer eine Lösung wie
>
>  if( Value > 0.0 )
>
> vorschlagt.

Geb ich dir recht.
In dem Fall ist das aber ok. Entweder die Zahl ist positiv, ist
negativ oder aber sie ist 0. Es gibt herzlich wenig, was du
konkret hier gegen Rundungsfehler tun kannst.
Wenn du dir meine Beiträg hier in den Foren ansiehst, dann bin
ich normalerweise einer der ersten, der auf Rundungsfehler und
die damit zusammenhängenden Probleme hinweist :-)


> außerdem stellt der Standardheader math.h die Funktion round zur
> Verfügung die genau das macht, einen Floating Wert mathematisch korrekt
> zu runden.

Ooops. Jetzt rächt sich, dass ich mit C lange vor 1999 aufgehört
habe und zu C++ gewechselt bin.
Danke für die Info.


Schadet aber auch nichts, wenn der Frager weiss, wie man sowas
machen kann :-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.