Unerwartetes Ergebnis bei Modulo

Unerwartetes Ergebnis bei Modulo

am 02.10.2007 14:27:30 von Hendrik Schnepel

Hallo Newsgroup,

ich habe gerade in einem Forum eine Frage gelesen, die ich mir selbst
nicht ganz beantworten kann.

Warum werden hier zwei verschiedene Ergebnisse ausgegeben:

hsch@tango perl -le 'print 7382 % 100'
82 (wie erwartet)

hsch@tango perl -le 'print +(73.82 * 100) % 100'
81 (eher ueberraschend?)

Das ganze passiert nur bei bestimmten Kombinationen von Vor- und
Nachkommaziffern. Eine int(...) Anweisung hilft auch nicht weiter.

Was wieder erwartungsgemaess arbeitet, ist:

hsch@tango perl -le 'print +((73.82 * 100)."") % 100'

Aber das ist doch wirklich unschoen...

Kann mir jemand sagen, wie dieser Effekt zustande kommt (ich vermute mal
irgendetwas, das durch interne (floating point?) Darstellung verursacht
wird), und wie man obige Rechnung evtl. besser programmieren koennte?

Gruss,
Hendrik

Re: Unerwartetes Ergebnis bei Modulo

am 02.10.2007 14:48:50 von Roman Racine

Hendrik Schnepel wrote:

> Kann mir jemand sagen, wie dieser Effekt zustande kommt (ich vermute mal
> irgendetwas, das durch interne (floating point?) Darstellung verursacht
> wird), und wie man obige Rechnung evtl. besser programmieren koennte?

Das kommt durch Floating-Point Arithmetik zustande, d.h. in der
Floatingpoint-Arithmetik ist die Zahl eben nicht ganz 7382, sondern ein
klein wenig weniger.
perl -le 'print int(73.82 * 100)'
gibt nämlich 7381.

Mit solchen unerwarteten Ergebnissen musst du grundsätzlich mit jeder
gängigen Programmiersprache rechnen, wenn du Ganzzahlarithmetik und
Gleitkommaarithmetik mischst. Solange du endliche Präzision verwendest,
wird man immer ein Beispiel wie das obige konstruieren können, wo die
interne Darstellung gerade ein kleines bisschen weniger als die ganze Zahl
ist.

Mit Math::BigFloat kriegst du das gewünschte Ergebnis. Allerdings ändert es
nichts daran, dass eine Operation wie die von dir vorgeschlagene ziemlich
"unschön" ist, weil sehr unerwartete Ergebnisse rauskommen können.
Möglicherweise gibt es andere Wege, wie du zum gewünschten Ziel kommen
könntest. Das könnte man beurteilen, wenn du uns erklären würdest, was du
eigentlich genau erreichen willst.

Gruss

Roman°
--
IRC-Freenode: #usenet-friends
http://www.usenet-friends.ch.vu/

Re: Unerwartetes Ergebnis bei Modulo

am 02.10.2007 20:07:47 von Florian Weimer

* Hendrik Schnepel:

> Warum werden hier zwei verschiedene Ergebnisse ausgegeben:
>
> hsch@tango perl -le 'print 7382 % 100'
> 82 (wie erwartet)
>
> hsch@tango perl -le 'print +(73.82 * 100) % 100'
> 81 (eher ueberraschend?)

73.82 sind 3691 Fünftel, und Fünftel lassen sich in einer
Binärdarstellung nicht exakt wiedergeben, im Gegensatz zur Basis 10.

Re: Unerwartetes Ergebnis bei Modulo

am 03.10.2007 12:18:44 von Hendrik Schnepel

This message is in MIME format. The first part should be readable text,
while the remaining parts are likely unreadable without MIME-aware tools.

---559023410-851401618-1191406724=:15055
Content-Type: TEXT/PLAIN; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 8BIT

Hallo Roman,

danke fuer die Details, alles klar. Ich hatte soetwas erwartet, aber mich
trotzdem gewundert, ... naja ;)

> Möglicherweise gibt es andere Wege, wie du zum gewünschten Ziel kommen
> könntest. Das könnte man beurteilen, wenn du uns erklären würdest, was du
> eigentlich genau erreichen willst.

Es ging darum, den Cent-Anteil eines Geldbetrags zu ermitteln. Das
letztendlich funktionierend zu implementieren ist aber kein Problem :)

Gruss,
Hendrik
---559023410-851401618-1191406724=:15055--

Re: Unerwartetes Ergebnis bei Modulo

am 08.10.2007 12:31:35 von Ingo Menger

On 3 Okt., 12:18, Hendrik Schnepel
wrote:
> Hallo Roman,
>
> danke fuer die Details, alles klar. Ich hatte soetwas erwartet, aber mich
> trotzdem gewundert, ... naja ;)
>
> > Möglicherweise gibt es andere Wege, wie du zum gewünschten Ziel kom=
men
> > könntest. Das könnte man beurteilen, wenn du uns erklären würde=
st, was du
> > eigentlich genau erreichen willst.
>
> Es ging darum, den Cent-Anteil eines Geldbetrags zu ermitteln. Das
> letztendlich funktionierend zu implementieren ist aber kein Problem :)

Aber mit Geldbeträgen in binärer Gleitkommarithmetik zu rechnen ist
ein Problem. Wie Florian schon richtig begründet hat, geht das bei den
meisten Centbeträgen in die Hose, denn 1/100 =3D 1/(5*5*2*2) und 5 ist
teilerfremd zu 2. Das heißt, Du kannst überhaupt nur 4 Centbeträge
genau darstellen: 0, 25, 50 und 75