Matlab und c unterscheiden sich mit der cos-Funktion

8

Ich habe ein Programm in Matlab und das gleiche Programm in c implementiert, und die Ergebnisse unterscheiden sich.

Ich bin etwas verwirrt, dass die cos-Funktion nicht das exakt gleiche Ergebnis liefert.

Ich benutze in beiden Fällen denselben Computer, Intel Core 2 Duo und den doppelten Datentyp mit 8 Bytes.

Warum unterscheidet sich das Ergebnis?

Hier ist der Test:

%Vor%

Ich benutze den gleichen Computer, Intel Core 2 Duo und 8 Bytes doppelten Datentyp.

Warum unterscheidet sich das Ergebnis?

verwendet Matlab nicht die in Intel eingebaute cos-Funktionshardware?

Gibt es eine einfache Möglichkeit, die gleiche cos-Funktion in Matlab und c (mit genauen Ergebnissen) zu verwenden, auch wenn sie etwas langsamer ist, damit ich die Ergebnisse meines Matlab- und C-Programms sicher vergleichen kann?

Aktualisierung:

vielen Dank für Ihre Antworten!

Wie Sie bereits bemerkt haben, unterscheidet sich die cos-Funktion für Matlab und c. Das ist erstaunlich! Ich dachte, dass sie die cos-Funktion verwenden, die im Intel-Mikroprozessor eingebaut ist.

Die cos-Version von Matlab ist (zumindest für diesen Test) gleich der von Matlab. Sie können von Matlab auch versuchen: b = java.lang.Math.cos (a)

Dann habe ich eine kleine MEX-Funktion verwendet, um die cos-c-Version aus Matlab zu verwenden, und es funktioniert gut; Dies ermöglicht mir das Debuggen des my-Programms (dasselbe implementiert in Matlab und c) und sehen, an welchem ​​Punkt sie sich unterscheiden, was der Zweck dieses Posts war.

Das einzige Problem ist, dass der Aufruf der MEX c cos Version von Matlab viel zu langsam ist.

Ich versuche jetzt, die Java-cos-Funktion von c aufzurufen (wie es von Matlab gleich ist), ob das schneller geht.

    
user974735 01.10.2011, 18:07
quelle

4 Antworten

5

Verwenden Sie das Skript unter Ссылка

Der Unterschied zwischen den beiden Zahlen besteht nur im letzten Bit:

%Vor%

Einer von ihnen muss näher an der "richtigen" Antwort sein, vorausgesetzt, der für a angegebene Wert ist exakt.

%Vor%

Das Ergebnis der C-Bibliothek ist also genauer.

Für die Zwecke Ihrer Frage sollten Sie jedoch nicht erwarten, die gleiche Antwort in Matlab und der C-Bibliothek, mit der Sie verbunden sind, zu erhalten.

    
stardt 01.10.2011, 19:20
quelle
6

Fließkommazahlen werden binär und nicht dezimal gespeichert. Ein double precision float hat 52 Bits Genauigkeit, was ungefähr 15 signifikanten Dezimalstellen entspricht. Mit anderen Worten, die ersten 15 Dezimalziffern eines double , die in Dezimalzahlen gedruckt sind, reichen aus, um eindeutig zu bestimmen, welche double gedruckt wurde.

Als diadisches rationales hat double eine genaue Repräsentation im Dezimalformat, die viel mehr Dezimalstellen als 15 benötigt (in Ihrem Fall 52 oder 53 Orte, glaube ich). Die Standards für printf und ähnliche Funktionen erfordern jedoch nicht, dass die Ziffern nach dem 15. korrekt sind. sie könnten völliger Unsinn sein. Ich vermute, dass eine der beiden Umgebungen den exakten Wert druckt, und der andere druckt eine schlechte Näherung, und das entspricht in Wirklichkeit dem exakt gleichen binären double -Wert.

    
R.. 01.10.2011 18:44
quelle
4

Das Ergebnis ist das gleiche bis zu 15 Dezimalstellen, ich vermute, dass es für fast alle Anwendungen ausreicht und wenn Sie mehr benötigen, sollten Sie wahrscheinlich trotzdem Ihre eigene Version von Cosine implementieren, so dass Sie die Kontrolle über die Besonderheiten und Ihre haben Code ist über verschiedene C-Compiler portierbar.

Sie werden sich unterscheiden, weil sie zweifellos unterschiedliche Methoden verwenden, um die Annäherung an das Ergebnis zu berechnen oder eine andere Anzahl von Malen zu durchlaufen. Da Kosinus als eine unendliche Reihe von Termen definiert ist, muss eine Approximation für seine Softwareimplementierung verwendet werden. Der CORDIC -Algorithmus ist eine gängige Implementierung.

Leider kenne ich die Details der Implementierung in beiden Fällen nicht, tatsächlich hängt die C davon ab, welche C-Standard-Bibliotheksimplementierung Sie verwenden.

    
Charles Keepax 01.10.2011 18:15
quelle
2

Wie andere erklärt haben, werden nicht alle Bruchzahlen verwendet, wenn Sie diese Zahl direkt in Ihren Quellcode eingeben, da Sie nur 15/16 Dezimalstellen für die Genauigkeit erhalten. Tatsächlich werden sie binär in den nächsten doppelten Wert konvertiert (alles, was über die feste Grenze der Ziffern hinausgeht, wird gelöscht).

Um die Dinge noch schlimmer zu machen, und @R , IEEE 754 toleriert Fehler im letzten Bit bei Verwendung der Cosinus-Funktion. Bei der Verwendung verschiedener Compiler ist mir das tatsächlich aufgefallen.

Um zu veranschaulichen, habe ich mit der folgenden MEX-Datei getestet, einmal mit dem Standard-LCC-Compiler kompiliert und dann mit VS2010 (ich bin auf WinXP 32-Bit).

In einer Funktion rufen wir direkt die C-Funktionen auf ( mexPrintf ist einfach ein Makro #define als printf ). In der anderen rufen wir mexEvalString auf, um Zeug in der MATLAB-Engine auszuwerten (entspricht der Verwendung der Eingabeaufforderung in MATLAB).

prec.c

%Vor%

zusammen mit LCC

%Vor%

mit VS2010 kompiliert

%Vor%

Ich kompiliere das obige mit: mex -v -largeArrayDims prec.c , und wechsle zwischen den Backend-Compilern mit: mex -setup

Beachten Sie, dass ich auch versucht habe, die hexadezimale Darstellung der Zahlen zu drucken. Ich habe es nur geschafft, die untere Hälfte der binären Doppelzahlen in C zu zeigen (vielleicht kann man die andere Hälfte mit Bitmanipulationen umgehen, aber ich bin mir nicht sicher, wie!)

Wenn Sie mehr Genauigkeit in Ihren Berechnungen benötigen, sollten Sie schließlich eine Bibliothek für die Arithmetik mit variabler Genauigkeit verwenden. Wenn Sie in MATLAB Zugriff auf die Symbolic Math Toolbox haben, versuchen Sie Folgendes:

%Vor%

Sie können also sehen, dass der tatsächliche Wert irgendwo zwischen den zwei verschiedenen Annäherungen liegt, die ich oben bekommen habe, und tatsächlich sind sie alle gleich bis der 15. Dezimalstelle:

%Vor%

UPDATE:

Wenn Sie die hexadezimale Darstellung von Fließkommazahlen in C korrekt anzeigen möchten, verwenden Sie stattdessen diese Hilfsfunktion (ähnlich wie bei NUM2HEX Funktion in MATLAB):

%Vor%     
Amro 02.10.2011 17:29
quelle

Tags und Links