Warum gibt pow(n,2) bei meinem Compiler und Betriebssystem 24 zurück, wenn n=5 ist?
Lesezeit: 7 Minuten
Ex-Schlange
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
int n,i,ele;
n=5;
ele=pow(n,2);
printf("%d",ele);
return 0;
}
Die Ausgabe ist 24.
Ich verwende GNU/GCC in Code::Blocks.
Was ist los?
Ich kenne die pow Funktion gibt a zurück double aber 25 passt zu einem int-Typ, warum druckt dieser Code also a 24 anstelle einer 25? Wenn n=4; n=6; n=3; n=2; der Code funktioniert, aber mit den fünf nicht.
Sie können versuchen, den Rückgabewert von zu nehmen pow in einem float oder double Variable, und versuchen Sie dann, sie zu typisieren int. Mal sehen, ob das auch produziert 24 oder die richtige Antwort 25
– Mach dir keine Sorgen, Kind
5. September 2014 um 4:25 Uhr
@exsnake – Die pow Funktion macht nicht einfach eine Multiplikation von 5 * 5. Das Endergebnis ist wahrscheinlich 24.9999999 oder ähnliches Ergebnis. Das pow Die Funktion verwendet wahrscheinlich Logarithmen, um das Ergebnis zu berechnen, da sie auch mit gebrochenen Potenzen umgehen muss. Sehen Sie sich zur Bestätigung die Implementierung Ihres Compilers an pow.
– Paul McKenzie
5. September 2014 um 4:35 Uhr
Sie sollten klären, welches Betriebssystem Sie verwenden, da dies mit ziemlicher Sicherheit ein Fehler in der Implementierung des mathematischen Teils der Standardbibliothek ist. Ich vermute, Sie verwenden mingw mit MSVCRT unter Windows …
– R.. GitHub HÖR AUF, EIS ZU HELFEN
5. September 2014 um 4:55 Uhr
Können Sie die Ausgabe von teilen printf("%.25lf\n", pow(n,2)); auf Ihrer Implementierung wo n=5?
– Mohit Jain
5. September 2014 um 5:08 Uhr
Eine gute pow(n,2) würde genau korrekte Ergebnisse liefern. C gibt nicht an, wie gutpow() muss sein.
– chux – Wiedereinsetzung von Monica
5. September 2014 um 14:35 Uhr
Paul McKenzie
Hier ist, was hier passieren kann. Sie sollten dies bestätigen können, indem Sie sich die Implementierung des Compilers ansehen pow Funktion:
Angenommen, Sie haben die richtigen #includes (alle vorherigen Antworten und Kommentare dazu sind korrekt – nehmen Sie nicht die #include Dateien selbstverständlich), der Prototyp für den Standard pow Funktion ist diese:
double pow(double, double);
und du rufst an pow so was:
pow(5,2);
Das pow Die Funktion durchläuft einen Algorithmus (wahrscheinlich unter Verwendung von Logarithmen), verwendet also Gleitkommafunktionen und -werte, um den Leistungswert zu berechnen.
Das pow Funktion geht nicht durch ein naives “Multipliziere den Wert von xa insgesamt n-mal”, da sie auch rechnen muss pow mit gebrochenen Exponenten, und Sie können auf diese Weise keine gebrochenen Potenzen berechnen.
Also mehr als wahrscheinlich, die Berechnung von pow Die Verwendung der Parameter 5 und 2 führte zu einem leichten Rundungsfehler. Wenn Sie einem zugewiesen haben inthaben Sie den Bruchwert abgeschnitten und so 24 erhalten.
Wenn Sie Ganzzahlen verwenden, können Sie auch Ihre eigene “intpow”- oder ähnliche Funktion schreiben, die den Wert einfach mit der erforderlichen Anzahl multipliziert. Die Vorteile davon sind:
Sie werden nicht in die Situation geraten, in der Sie bei der Verwendung von subtilen Rundungsfehlern auftreten können pow.
Dein intpow -Funktion wird höchstwahrscheinlich schneller ausgeführt als ein äquivalenter Aufruf von pow.
Wenn Sie Ihre eigene Integer-Power würfeln, sollten Sie wahrscheinlich verwenden Potenzieren durch Quadrieren eher als wiederholte Multiplikation, da letzteres ist An) und ersteres ist O(log n).
– aruisdante
9. Oktober 2014 um 20:43 Uhr
@aruisdante: Vorsicht, die Notation deutet auf eine Verschiebung von linearer zu logarithmischer Komplexität hin, wenn es sich tatsächlich um eine Verschiebung handelt pseudolinear zu linearer Komplexität.
– Ben Voigt
2. November 2016 um 2:54 Uhr
@BenVoigt Technisch hätte der vorherige Kommentar genauer sein sollen: Der naive Algorithmus erfordert O (n) arithmetische Operationen (Multiplikation oder Addition), wobei n der Exponent ist; Quadrieren reduziert dies auf O(log(n)). Wenn wir die Anzahl der Bits in n als Problemgröße nehmen, möchten wir möglicherweise auch die Anzahl der Bits in jedem Produkt zählen und die Multiplikation nicht als Operation mit konstanter Zeit betrachten. Für die praktischen Belange von Leuten, die numerische Berechnungen durchführen, denke ich, dass die Wikipedia-Seite zu pedantisch ist; aus komplexitätstheoretischen Gründen ist ihre Korrektheit fraglich.
– David K
10. Dezember 2016 um 17:50 Uhr
Sie möchten ein int-Ergebnis einer Funktion, die für Doubles gedacht ist.
Besser zu verwenden ele = round(0.5 + pow(n,2));. Obwohl in diesem Fall pow(n,2) sollte keine Ergebnisse kleiner als Null zurückgeben, y = (int)(0.5 +x) ist ein Problem für negativ x.
– chux – Wiedereinsetzung von Monica
5. September 2014 um 14:30 Uhr
Nicht besser! solltest du einfach verwenden round(pow(n,2)). Das Hinzufügen von 0,5 vor dem Runden rundet effektiv auf die nächste ganze Zahl. Wenn pow(n,2) Wenn Sie 25 plus Epsilon zurückgeben, erhalten Sie 26.
– chqrlie
24. Februar 2015 um 1:55 Uhr
Fließkomma-Arithmetik ist nicht exakt.
Obwohl kleine Werte exakt addiert und subtrahiert werden können, sind die pow() Funktion funktioniert normalerweise durch Multiplizieren von Logarithmen, so dass selbst wenn die Eingaben beide exakt sind, das Ergebnis es nicht ist. Zuordnung zu int schneidet immer ab, wenn also die Ungenauigkeit negativ ist, erhalten Sie 24 statt 25.
Die Moral dieser Geschichte ist, ganzzahlige Operationen mit ganzen Zahlen zu verwenden und misstrauisch zu sein <math.h> funktioniert, wenn die eigentlichen Argumente heraufgestuft oder abgeschnitten werden sollen. Es ist bedauerlich, dass GCC nicht warnt, es sei denn, Sie fügen hinzu -Wfloat-conversion (ist nicht drin -Wall -Wextrawahrscheinlich weil es viele Fälle gibt, in denen eine solche Konvertierung erwartet und gewünscht wird).
Für ganzzahlige Potenzen ist es immer sicherer und schneller, die Multiplikation (Division, wenn negativ) zu verwenden, anstatt pow() – letzteres dort reservieren, wo es gebraucht wird! Seien Sie sich jedoch des Überlaufrisikos bewusst.
Jayesh Bhoi
Wenn Sie pow mit Variablen verwenden, ist das Ergebnis double. Zuordnung zu einem int schneidet es ab.
Sie können diesen Fehler also vermeiden, indem Sie result of zuweisen pow zu double oder float Variable.
Also im Prinzip
Es übersetzt zu exp(log(x) * y) was zu einem Ergebnis führt, das nicht genau dasselbe ist wie x^y – nur eine annähernde Annäherung als Fließkommawert. Also zum Beispiel 5^2 wird werden 24.9999996 oder 25.00002
Wenn Sie nicht #include <math.h> dann kennt der Compiler die Typen der Argumente nicht pow() das sind beides double nicht int — Sie erhalten also ein undefiniertes Ergebnis. Sie bekommen 24, ich bekomme 16418.
OP beinhaltet math.h. keine Chance, ein leicht abweichendes Ergebnis zu erzielen, indem math.h nicht einbezogen wird. also uns ein ganz anderes thema.
– Jean-Francois Fabre ♦
31. August 2017 um 6:31 Uhr
@Jean-FrançoisFabre (seufzen) Das OP enthielt NICHT math.h, die Frage wurde bearbeitet, um sie hinzuzufügen.
– John Hascall
3. März 2020 um 17:48 Uhr
(a) Die Frage wurde am 2014-09-05 4:17:25Z bearbeitet, um ein vollständiges Programm anzuzeigen, einschließlich #include <math.h>, und diese Antwort wurde danach am 05.09.2014 04:19:08Z eingegeben. (b) Der ursprüngliche Code war eindeutig ein Fragment eines Programms. Es enthielt nicht einmal main und kann daher nicht mit einem vollständigen Programm verwechselt werden, daher keine Schlussfolgerung, dass der tatsächliche Code von OP nicht enthalten war #include <math.h> war gerechtfertigt. (c) Nicht enthalten #include <math.h> aber es ist sehr unwahrscheinlich, dass das Kompilieren und Ausführen trotzdem 24 als Ergebnis erzeugt, während a pow das ergibt ein Ergebnis mit Rundungsfehlern.
– Eric Postpischil
5. September um 12:16 Uhr
OP beinhaltet math.h. keine Chance, ein leicht abweichendes Ergebnis zu erzielen, indem math.h nicht einbezogen wird. also uns ein ganz anderes thema.
– Jean-Francois Fabre ♦
31. August 2017 um 6:31 Uhr
@Jean-FrançoisFabre (seufzen) Das OP enthielt NICHT math.h, die Frage wurde bearbeitet, um sie hinzuzufügen.
– John Hascall
3. März 2020 um 17:48 Uhr
(a) Die Frage wurde am 2014-09-05 4:17:25Z bearbeitet, um ein vollständiges Programm anzuzeigen, einschließlich #include <math.h>, und diese Antwort wurde danach am 05.09.2014 04:19:08Z eingegeben. (b) Der ursprüngliche Code war eindeutig ein Fragment eines Programms. Es enthielt nicht einmal main und kann daher nicht mit einem vollständigen Programm verwechselt werden, daher keine Schlussfolgerung, dass der tatsächliche Code von OP nicht enthalten war #include <math.h> war gerechtfertigt. (c) Nicht enthalten #include <math.h> aber es ist sehr unwahrscheinlich, dass das Kompilieren und Ausführen trotzdem 24 als Ergebnis erzeugt, während a pow das ergibt ein Ergebnis mit Rundungsfehlern.
– Eric Postpischil
5. September um 12:16 Uhr
13707300cookie-checkWarum gibt pow(n,2) bei meinem Compiler und Betriebssystem 24 zurück, wenn n=5 ist?yes
Sie können versuchen, den Rückgabewert von zu nehmen
pow
in einemfloat
oderdouble
Variable, und versuchen Sie dann, sie zu typisierenint
. Mal sehen, ob das auch produziert24
oder die richtige Antwort25
– Mach dir keine Sorgen, Kind
5. September 2014 um 4:25 Uhr
@exsnake – Die
pow
Funktion macht nicht einfach eine Multiplikation von 5 * 5. Das Endergebnis ist wahrscheinlich24.9999999
oder ähnliches Ergebnis. Daspow
Die Funktion verwendet wahrscheinlich Logarithmen, um das Ergebnis zu berechnen, da sie auch mit gebrochenen Potenzen umgehen muss. Sehen Sie sich zur Bestätigung die Implementierung Ihres Compilers anpow
.– Paul McKenzie
5. September 2014 um 4:35 Uhr
Sie sollten klären, welches Betriebssystem Sie verwenden, da dies mit ziemlicher Sicherheit ein Fehler in der Implementierung des mathematischen Teils der Standardbibliothek ist. Ich vermute, Sie verwenden mingw mit MSVCRT unter Windows …
– R.. GitHub HÖR AUF, EIS ZU HELFEN
5. September 2014 um 4:55 Uhr
Können Sie die Ausgabe von teilen
printf("%.25lf\n", pow(n,2));
auf Ihrer Implementierung won=5
?– Mohit Jain
5. September 2014 um 5:08 Uhr
Eine gute
pow(n,2)
würde genau korrekte Ergebnisse liefern. C gibt nicht an, wie gutpow()
muss sein.– chux – Wiedereinsetzung von Monica
5. September 2014 um 14:35 Uhr