2015-10-18 7 views
6

Gewährleistet der Standard, dass Funktionen das gleiche Ergebnis über alle Implementierungen zurückgeben?Was sagt der Standard über CMath aus wie std :: pow, std :: log etc?

Nehmen Sie zum Beispiel pow(float,float) für 32bit IEEE Floats. Ist das Ergebnis für alle Implementierungen identisch, wenn dieselben zwei Floats übergeben werden?

Oder gibt es eine gewisse Flexibilität, die der Standard in Bezug auf winzige Unterschiede ermöglicht, abhängig vom implementierten Algorithmus pow?

+0

Die Std schreibt nicht vor, dass "float" und "double" IEEE-754-Typen sind. Sie könnten maschinenspezifische Typen mit unterschiedlichen Reichweiten und Genauigkeiten sein. – lodo

+1

Wenn Sie zwei Maschinen haben, die die gleiche Darstellung für 'float's und' double's verwenden, und mit den gleichen Einstellungen bezüglich der Rundung, kenne ich die Antwort nicht. In allen anderen Fällen ist die Antwort nein, sie können unterschiedliche Ergebnisse liefern. – lodo

+0

auch zwei verschiedene Compiler auf der gleichen Maschine, die ieee754 gehorcht. Wenn std sagt, ja, die Antwort sollte gleich sein, dann müsste sie definieren, was die richtige Antwort ist. – steviekm3

Antwort

18

Nein, der C++ - Standard erfordert nicht, dass die Ergebnisse der cmath-Funktionen in allen Implementierungen gleich sind. Für Anfänger erhalten Sie möglicherweise nicht IEEE-754/IEC 60559 Fließkommaarithmetik.

Das heißt, wenn eine Implementierung IEC nicht verwendet 60559 und definiert __STDC_IEC_559__, dann muss adhere F des C-Standard Anhang (ja, Ihre Frage ist etwa C++, aber der C++ Standard aufschiebt zum C-Standard für C-Header wie math.h). Anhang F lautet:

  • Der float Typ entspricht der IEC 60559 einzelnes Format.
  • Der Typ double entspricht dem Doppelformat nach IEC 60559.
  • Der Typ long double entspricht einem erweiterten Format nach IEC 60559, ansonsten einem nicht-IEC 60559 erweiterten Format, andernfalls dem IEC 60559 double Format.

Ferner heißt es normale Arithmetik der IEC 60559 Norm folgen müssen:

  • Die +, , * und / Betreiber bieten die IEC 60559 Addieren, Subtrahieren, Multiplizieren und Teile Operationen.

Es bedarf weiterer sqrt IEC folgen 60559:

  • Die sqrt Funktionen in <math.h> die Quadratwurzeloperation 60559 IEC bieten.

Es geht dann auf das Verhalten von mehreren anderen Floating-Point-Funktionen zu beschreiben, von denen die meisten Sie wahrscheinlich nicht daran interessiert sind, für diese Frage.

Schließlich wird es dem math.h Header und gibt an, wie die verschiedenen mathematischen Funktionen (dh sin, cos, atan2, exp usw.) sollten Sonderfälle behandeln (dh asin(±0) kehrt ±0, atanh(x) eine NaN zurück und hebt die "ungültige" Gleitkommaausnahme für | x |> 1, usw.). Aber es bringt nie die genaue Berechnung für normale Eingaben auf den Punkt, was bedeutet, dass Sie sich nicht auf alle Implementierungen verlassen können, die die gleiche Berechnung erzeugen.

Also nein, es erfordert nicht, dass diese Funktionen sich in allen Implementierungen gleich verhalten, auch wenn die Implementierungen alle __STDC_IEC_559__ definieren.


Dies ist alles aus einer theoretischen Perspektive. In der Praxis sind die Dinge noch schlimmer. CPUs implementieren im Allgemeinen IEC 60559-Arithmetik, aber diese kann verschiedene Modi zum Runden haben (so dass die Ergebnisse von Computer zu Computer unterschiedlich sind), und der Compiler (abhängig von Optimierungsflags) könnte einige Annahmen machen, die nicht strikt normkonform sind Gleitkommaarithmetik.

Also in der Praxis ist es noch weniger streng als es in der Theorie ist, und Sie werden sehr wahrscheinlich sehen, dass zwei Computer zu irgendeinem Zeitpunkt etwas andere Ergebnisse produzieren.


Ein Beispiel der realen Welt ist in glibc, die GNU C Bibliothek Implementierung. They have a table of known error limits for their math functions über verschiedene CPUs. Wenn alle mathematischen C-Funktionen bitgenau wären, würden diese Tabellen alle 0 Fehler-ULPs anzeigen. Aber sie nicht. Die Tabellen zeigen, dass tatsächlich in ihren C-Math-Funktionen unterschiedliche Fehler auftreten. Ich denke, dieser Satz ist die interessanteste Zusammenfassung:

Mit Ausnahme bestimmter Funktionen wie sqrt, fma und rint, deren Ergebnisse durch Verweis vollständig spezifiziert sind IEEE entspricht 754 Floating-Point-Operationen und Konvertierungen zwischen Streichern und Gleitkomma zielt das GNU C Library nicht für richtig gerundete Ergebnisse für Funktionen in der Mathematik-Bibliothek [...]

die einzigen Dinge, die bitgenauen in glibc sind, sind die Dinge, die Bit-genaue erforderlich sein durch Anhang F der C-Norm. Und wie Sie in ihrer Tabelle sehen können, sind die meisten Dinge nicht.

+0

Danke für ausführliche Antwort. Um also das gleiche Ergebnis zu garantieren, müsste man seine eigene pow-Funktion schreiben. – steviekm3

+4

Ziemlich viel. Für Situationen, in denen Bit-Genauigkeit wichtig ist (wie bei Audio- und Video-Codecs), ist es nicht ungewöhnlich, dass Sie eine eigene Festkommaarithmetik implementieren. – Cornstalks

+0

Was meinen Sie mit * normalen Eingaben * in Ihrem Satz "Aber die genaue Berechnung für normale Eingaben wird nie niedergeschrieben"? –