Announcement

Collapse
No announcement yet.

Funktion "Round" fehlerhaft ?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Funktion "Round" fehlerhaft ?

    Hallo an alle Mathematiker und Delphi-Experten !

    Nachdem ich zum ersten Mal die Delphi-Funktion "round" benutzt hatte, stellte ich fest, daß sie falsch arbeitet.

    Beispiel: round(1.5) liefert 2, round(2.5) liefert auch 2

    Immer wenn der Nachkommaanteil 0.5 und der Vorkommaanteil eine gerade Zahl ist, wird das Ergebnis falsch. Ich schrieb mir daraufhin eine eigene Funktion und mußte jetzt zu meiner großen Überraschung feststellen, daß auch meine eigene Rundungsfunktion nicht richtig arbeitet, möglicherweise aus demselben Grund, aus dem auch Delphi falsch rundet. Wer kann dieses Phänomen erklären ? Ich verwende Delphi 4.

    Johann

    procedure test;
    var x,y :real;
    begin
    x := 0.285;
    y := Rounded(x,2); // Ergebnis: y = 0.28 Falsch !!
    x := 0.325;
    y := Rounded(x,2); // Ergebnis: y = 0.33 Richtig !!
    end;

    function Rounded(pReal : real; pNKStellen : integer):real;
    var zw1,zw2 : real;
    begin
    zw1 := power(10,pNKStellen); // Potenz ermitteln !
    zw2 := pReal * zw1;
    if (frac(zw2) < 0.5) then
    result := int(zw2) / zw1
    else
    result := (int(zw2) + 1) / zw1;
    end;

  • #2
    Round arbeitet genau so wie du es beschreibst. Die Hilfe sagt das gleiche dazu. Es ist einfach eine falsche Annahme deinerseits ueber das was Round macht.<br>
    Was du wohl haben willst ist Int(f+0.5)

    Comment


    • #3
      (1) Das Verhalten von Round ist "a feature, not a bug" :-).
      <br>Schau einfach mal in die Online-Hilfe.
      <br>(2) Das "Fehlverhalten" deiner Funktion liegt daran, dass Gleitkommazahlen auf Rechnern (wg. Binärsystem) nicht (immer) exakt dargestellt werden können. Z.B. kannst du im Debugger sehen, dass frac(zw2) nicht *genau* 0,5 ist. Lass dir dazu mal frac(zw2) - 0.5 im Überwachungsfenster anzeigen -- es ist ein (sehr, sehr kleiner) negativer Wert. Deswegen läuft deine Funktion nicht wie erwartet durch den then-Zweig, sondern durch den else-Zweig.
      <br>Uli

      Comment


      • #4
        Hallo,

        vielen Dank für deine Antwort. So was habe ich mir schon gedacht. Mein Problem ist aber, das ich kaufmännisch runden muß, d.h. steht hinter der zu rundenden Nachkommastelle eine 5 oder mehr wird aufgerundet, sonst abgerundet. 0,285 ergibt also gerundet 0,29 und 0,325 0,33. Wie kann ich das in Delphi erreichen ?

        Johan

        Comment


        • #5
          trunc(x) ?<p>
          Gruß,<br>
          Marku

          Comment


          • #6
            Das kaufmaennische runden habe ich doch angegeben. Nur fuer negative Zahlen musst du noch pruefen ob meine Formel richtig ist

            Comment


            • #7
              Value := Round(Input * 100) / 100 oder <br>
              Value := Int(Input * 100 + 0.5) / 10

              Comment


              • #8
                Hi, eine etwas andere lustigere Variante:
                <BR>
                Verwende FormatFloat, die runded nach Deinen Vorstellungen.
                Du musst dann nur den String wieder zurückwandeln, wenn Du weiterrechnen willst.

                <PRE>
                label.caption:=formatFloat('0.#',22.25); // Ergibt 22.3
                label.caption:=formatFloat('0.#',22.24); // Ergibt 22.2
                label.caption:=formatFloat('0.#',22.35); // Ergibt 22.4
                </PRE>

                Andrea

                Comment


                • #9
                  Vielleicht geht es elegangter aber die Funktion runden genau :-)

                  Function SRound(X : Double): Integer ;
                  const
                  D = 0.500001 ;
                  begin
                  if X > 0 then Result := Trunc( X + D )
                  else if X < 0 then Result := Trunc( X - D )
                  else Result := 0 ;
                  end;
                  Function XRound( X : Double ; Digits : Word): Double ;
                  var
                  I : Integer ;
                  begin
                  I := Round( IntPower( 10 , Digits ) ) ;
                  Result := SRound( X * I ) / I ;
                  end

                  Comment

                  Working...
                  X