Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Interessantes vom Runden...

1 view
Skip to first unread message

Thomas Koenig

unread,
May 21, 2023, 4:54:18 PM5/21/23
to
Gerade drauf gestoßen...

#include <stdio.h>
#include <math.h>

int main()
{
double x;
for (int i=0; i<5; i++)
{
x = i + 0.5;
printf ("%.2f %.2f\n", x, nearbyint(x));
}

return 0;
}

gibt welche Ausgabe?

0.50 0.00
1.50 2.00
2.50 2.00
3.50 4.00
4.50 4.00

Helmut Schellong

unread,
May 22, 2023, 3:28:33 AM5/22/23
to

Claus Reibenstein

unread,
May 22, 2023, 12:29:20 PM5/22/23
to
Thomas Koenig schrieb am 21.05.2023 um 22:54:

> Gerade drauf gestoßen...
>
> #include <stdio.h>
> #include <math.h>
>
> int main()
> {
> double x;
> for (int i=0; i<5; i++)
> {
> x = i + 0.5;
> printf ("%.2f %.2f\n", x, nearbyint(x));
> }
>
> return 0;
> }
>
> gibt welche Ausgabe?

Ich würde sagen: Implementationsabhängig, da die "rounding direction"
unterschiedlich implementiert sein kann und, wenn ich den Standard
(2011) richtig interpretiere, nicht mal implementiert sein muss.

Gruß
Claus

Enrik Berkhan

unread,
May 22, 2023, 1:13:06 PM5/22/23
to
Helmut Schellong <r...@schellong.biz> wrote:
> On 05/21/2023 22:54, Thomas Koenig wrote:
>> Gerade drauf gestoßen...
>> [...]
>> 0.50 0.00
>> 1.50 2.00
>> 2.50 2.00
>> 3.50 4.00
>> 4.50 4.00
>
> Das mit 0.5 kenne ich schon ewig.
> Es dient der 4/5-Rundung bei Wandlung in Integer.

Hast du denn auch gemerkt, worum es hier überhaupt ging?


https://en.wikipedia.org/wiki/Rounding#Rounding_half_to_even

Helmut Schellong

unread,
May 22, 2023, 2:23:02 PM5/22/23
to
On 05/22/2023 19:00, Enrik Berkhan wrote:
> Helmut Schellong <r...@schellong.biz> wrote:
>> On 05/21/2023 22:54, Thomas Koenig wrote:
>>> Gerade drauf gestoßen...
>>> [...]
>>> 0.50 0.00
>>> 1.50 2.00
>>> 2.50 2.00
>>> 3.50 4.00
>>> 4.50 4.00
>>
>> Das mit 0.5 kenne ich schon ewig.
>> Es dient der 4/5-Rundung bei Wandlung in Integer.
>
> Hast du denn auch gemerkt, worum es hier überhaupt ging?
>

Meine gesamte Antwort legt nahe, daß ich über 0.5 und um 1.0/2.0 bzw. x/2.0 bei Gleitkomma Bescheid weiß.
Weitere Erwägungen dazu haben in meinem Berufsleben nie eine Rolle gespielt, weil ich
stets mit realen Meßwerten zu tun hatte, die durch bis zu 34-fach summierten ADC-Messungen,
Wegwerfen von Min und Max und Division durch bis zu (34-2) entstanden waren.
Hilfsmittel wie Epsilon waren nahezu bedeutungslos.
Es war also so, daß 0.5 _niemals_ verfälschend addiert wurde.

Stefan Reuther

unread,
May 23, 2023, 12:43:42 PM5/23/23
to
Am 21.05.2023 um 22:54 schrieb Thomas Koenig:
> Gerade drauf gestoßen...
[...]
> printf ("%.2f %.2f\n", x, nearbyint(x));
[...]
> 0.50 0.00
> 1.50 2.00
> 2.50 2.00
> 3.50 4.00
> 4.50 4.00

Das ist einer der Gründe, warum ich trotz quasi universell verfügbarer
FPUs immer noch gerne Rechnungen nach Möglichkeit komplett in ganzen
Zahlen durchführe. Da sind sich die Compiler deutlich einiger als bei
Floating Point, und Rundungs-Operationen aller Art sind explizit
aufgeschrieben.


Stefan

Thomas Koenig

unread,
May 23, 2023, 1:11:21 PM5/23/23
to
Stefan Reuther <stefa...@arcor.de> schrieb:
Wenn's geht...

nerbyint() rundet halt nach dem gegenwärtigen "rounding direction".
Die kann man natürlich mit fesetround() setzen, wenn man es genau
haben will. Ist kein so besonders tolles Design.

Oder man nimmt round(), das rundet immer von Null weg, wenn man
"round ties to even" haben will, kann man roundeven() nehmen
(hm, könnte neu in C23 sein, den habe ich gerade offen).

Und wenn ich ein bisschen lästern darf: Der Abschnitt 4 in Clause
7.6 von n3054 (aka C23) ist ein bisschen arg Prinzip Hoffnung:

Certain programming conventions support the intended model of use
for the dynamic floating-point environment:

- a function call does not alter its caller’s floating-point
control modes, clear its caller’s floating- point status flags,
nor depend on the state of its caller’s floating-point status
flags unless the function is so documented;

— a function call is assumed to require default floating-point
control modes, unless its documen- tation promises otherwise;

— a function call is assumed to have the potential for raising
floating-point exceptions, unless its documentation promises
otherwise.

Fortran macht das in der Sprache klar, da muss der Compiler dafür
sorgen, dass die Rundung am Ausgang der procedure wieder geändert
wird. Hat nur den manchmal überraschenden Nebeneffekt, dass das
Setzen von Rundungsmoden in einem Unterprogramm ein no-op ist :-)

Bonita Montero

unread,
May 25, 2023, 2:53:12 PM5/25/23
to
Dir "rounding direction" rundet nicht an der ersten Nachkommastelle,
zumindest nicht wenn der Exponent nicht sehr groß ist, sondern eben
auf dem temporären Bit vor dem letzten Bit der Mantisse.


Bonita Montero

unread,
May 25, 2023, 2:54:22 PM5/25/23
to
Am 22.05.2023 um 20:23 schrieb Helmut Schellong:
> On 05/22/2023 19:00, Enrik Berkhan wrote:
>> Helmut Schellong <r...@schellong.biz> wrote:
>>> On 05/21/2023 22:54, Thomas Koenig wrote:
>>>> Gerade drauf gestoßen...
>>>> [...]
>>>> 0.50 0.00
>>>> 1.50 2.00
>>>> 2.50 2.00
>>>> 3.50 4.00
>>>> 4.50 4.00
>>>
>>> Das mit 0.5 kenne ich schon ewig.
>>> Es dient der 4/5-Rundung bei Wandlung in Integer.
>>
>> Hast du denn auch gemerkt, worum es hier überhaupt ging?
>>
>
> Meine gesamte Antwort legt nahe, daß ich über 0.5 und um 1.0/2.0 bzw.
> x/2.0 bei Gleitkomma Bescheid weiß.
> Weitere Erwägungen dazu haben in meinem Berufsleben nie eine Rolle
> gespielt, weil ich
> stets mit realen Meßwerten zu tun hatte, die durch bis zu 34-fach
> summierten ADC-Messungen,
> Wegwerfen von Min und Max und Division durch bis zu (34-2) entstanden
> waren.
> Hilfsmittel wie Epsilon waren nahezu bedeutungslos.

Ja, und wie man hier sehen kann ist dir dabei essentielles Wissen
entgangen. ;-)

Bonita Montero

unread,
May 25, 2023, 2:55:25 PM5/25/23
to
Am 23.05.2023 um 18:19 schrieb Stefan Reuther:

> Das ist einer der Gründe, warum ich trotz quasi universell verfügbarer
> FPUs immer noch gerne Rechnungen nach Möglichkeit komplett in ganzen
> Zahlen durchführe. Da sind sich die Compiler deutlich einiger als bei
> Floating Point, und Rundungs-Operationen aller Art sind explizit
> aufgeschrieben.

Die FPUs verhalten sich bei den Grundrechenarten konsistent. Wenn Du
es zuverlässig haben willst setzt Du noch mit fesetround() den Rundungs
-Modus; aber eigentlich ist das von der Runtime immer auf zum nächsten
Wert gerundet gesetzt und ich wüsste nicht wieso man das ändern sollte.

Bonita Montero

unread,
May 25, 2023, 2:58:55 PM5/25/23
to
Achso, außer bei nearbyint(), da gehts dann wirklich um die erste
Nachkommastelle.

Bonita Montero

unread,
May 26, 2023, 7:17:09 AM5/26/23
to
Tja C-Leute sind halt Detail-Frickler ohne Blick für das Große
Ganze. Deswegen sind denen ja Sprachen mit nem höheren Abstrak-
tionsgrad zuwider. Da übersieht man auch mal, dass dezimale FP
-Zahlen in C sehr eingeschränkten Sinn ergeben; meiner Meinung
nach so eingeschränkten Sinn, dass man es dabei belassen könnte,
dass die Leute hierzu externe Libaries nehmen.
0 new messages