Heim  >  Artikel  >  Backend-Entwicklung  >  Warum führt die C-Gleitkomma-Arithmetik zu unerwarteten Ergebnissen und wie können wir diese Präzisionsanomalien abmildern?

Warum führt die C-Gleitkomma-Arithmetik zu unerwarteten Ergebnissen und wie können wir diese Präzisionsanomalien abmildern?

Barbara Streisand
Barbara StreisandOriginal
2024-11-04 21:38:02749Durchsuche

Why does C   floating-point arithmetic produce unexpected results, and how can we mitigate these precision anomalies?

C-Gleitkomma-Präzisionsanomalie und Auflösung

Trotz ihrer weit verbreiteten Verwendung weisen Gleitkommazahlen in C Einschränkungen in der Präzision auf. Betrachten Sie den folgenden Codeausschnitt:

<code class="cpp">double a = 0.3;
std::cout.precision(20);
std::cout << a << std::endl;

Dieser Code gibt 0,2999999999999999889 anstelle der erwarteten 0,3 aus. Diese Diskrepanz tritt auf, weil die Variable a nicht exakt als 0,3-Gleitkommazahl mit doppelter Genauigkeit gespeichert wird, sondern aufgrund der endlichen Darstellung von Gleitkommawerten eher eine Näherung davon.

Ein überraschenderes Verhalten tritt auf, wenn a wird 50 Mal wiederholt hinzugefügt:

<code class="cpp">double a, b;
a = 0.3;
b = 0;
for (char i = 1; i <= 50; i++) {
  b = b + a;
};
std::cout.precision(20);
std::cout << b << std::endl;

Dieser Code gibt überraschenderweise 15,000000000000014211 statt 15,0 aus. Dies liegt daran, dass jede Addition den Näherungsfehler akkumuliert, was zu einem akkumulierten Fehler führt, der größer als die ursprüngliche Präzision ist.

Auflösen der Präzisionsanomalie

Um präzise Ergebnisse zu erhalten, ist es wichtig Dies ist wichtig, um zu vermeiden, dass die Ausgabegenauigkeit größer als die verfügbaren Ziffern für den numerischen Typ eingestellt wird. Dies kann mit der Klasse std::numeric_limits erreicht werden:

<code class="cpp">#include <iostream>
#include <limits>
int main()
{
        double a = 0.3;
        std::cout.precision(std::numeric_limits<double>::digits10);
        std::cout << a << std::endl;
        double b = 0;
        for (char i = 1; i <= 50; i++) {
                  b = b + a;
        };
        std::cout.precision(std::numeric_limits<double>::digits10);
        std::cout << b << std::endl;
}</code>

Dieser Code verwendet die Memberfunktion „digits10“, um die Genauigkeit auf die maximal verfügbaren Ziffern für eine Gleitkommazahl mit doppelter Genauigkeit festzulegen, also 15 Ziffern für Double.

Einschränkungen der Gleitkomma-Arithmetik

Während die bereitgestellte Lösung den Genauigkeitsfehler minimiert, ist es wichtig zu erkennen, dass die Gleitkomma-Arithmetik inhärente Einschränkungen aufweist . Wenn eine Schleife Tausende von Iterationen umfasst, kann der akkumulierte Fehler trotz richtig eingestellter Genauigkeit erheblich werden. In solchen Szenarien sind alternative Datentypen wie Festkommazahlen oder rationale Zahlen möglicherweise besser für die Beibehaltung exakter Werte geeignet.

Das obige ist der detaillierte Inhalt vonWarum führt die C-Gleitkomma-Arithmetik zu unerwarteten Ergebnissen und wie können wir diese Präzisionsanomalien abmildern?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn