Forum: PC-Programmierung Runden einer Dezimalzahl in C


von Radon (Gast)


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

von flyingwolf (Gast)


Lesenswert?

deklarier doch mal "Summe" als float

von Tobi H. (tobi-) Benutzerseite


Lesenswert?

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

von Blackbird (Gast)


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.

von Rolf Magnus (Gast)


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.

von Radon (Gast)


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!

von Blackbird (Gast)


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

von Rolf (Gast)


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, ...

von Kate (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


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
1
int round( double Value )
2
{
3
  if( Value > 0.0 )
4
    return (int)( Value + 0.5 );
5
6
  if( Value < 0.0 )
7
    return (int)( Value - 0.5 );
8
9
  return 0;
10
}

von imon (Gast)


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.

von Karl H. (kbuchegg)


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 :-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.