2016-05-10 12 views
0

Erstens nehme die Daten:Wie verwende ich eps in dieser Situation, wo ich Unterschiede von kumulativen Summen

orig = reshape([0.0000000000000000 0.3480000000000000 0.7570000000000000 1.3009999999999999 2.8300000000000001 4.7519999999999998 5.2660000000000000 5.8120000000000003 14.3360000000000000 15.3390000000000000 ],[10 1]) 

change = reshape([0.0000000000000000 0.3480000000000000 0.0000000000000000 0.9530000000000000 1.5290000000000001 1.9219999999999997 0.5140000000000002 0.5460000000000003 0.0000000000000000 9.5270000000000010 ],[10 1]) 

change = cumsum(change) 

orig ist ein Vektor von Sekunden verstrichen ist. change ist ein Vektor, der abgeleitet wird, indem Unterschiede zwischen (einigen) Elementen von orig genommen werden. Die kumulative Summe von change hat einige Elemente, die tatsächlich dem entsprechenden Element in orig entsprechen.

jedoch durch Präzisions Probleme:

diff = orig - change 

gibt

diff = 

         0 
         0 
        0.409 
         0 
         0 
         0 
         0 
         0 
        8.524 
    -1.77635683940025e-15 

Es scheint, dass, wenn ich den folgenden Befehl ausführen:

diff(abs(diff) <= eps(orig)) = 0 

dann Einträge dieses Sets, die sein sollte Null, aber nicht aufgrund von Genauigkeitsproblemen, um Null zu sein.

Meine Frage ist, ist dies der richtige Weg, es zu tun? Warum ist der Vergleich <= statt <? Sollte die Aussage sein:

diff(abs(diff) < k*eps(orig)) = 0 

für einige k > 1 eine gewisse Toleranz zu geben? Wenn ja, wie würde man wählen k?


Falls es notwendig ist, zu wissen, wie change von orig abgeleitet wird, das folgende alternative Beispiel zeigt auch dieses Verhalten:

orig = reshape([0.0000000000000000 0.3480000000000000 0.7570000000000000 1.3009999999999999 2.8300000000000001 4.7519999999999998 5.2660000000000000 5.8120000000000003 14.3360000000000000 15.3390000000000000 ],[10 1]) 
change = orig - [0; orig(1:end-1)] 
change = cumsum(change) 
diff = orig - change 
+1

'diff' ist eine eingebaute Funktion. Bitte verwenden Sie diese Art von Namen nicht für Ihre Variablen. Dies kann zu unerwartetem oder unbeabsichtigtem Verhalten führen. – Bernhard

Antwort

1

Die folgende Anweisung wird nur, wenn die „fast Null“ wahr sein passiert, weil 1 Bit nicht gesetzt ist.

1 Bit ist eine lächerlich hohe Präzision zu fragen, eine Präzision, die Sie wahrscheinlich nicht erreichen können. Im Allgemeinen müssen Sie Ihren Schwellenwert selbst definieren, z. B.

abs(diff) <= 1e-12 

Sie fragen auch, wie Sie diesen Wert auswählen. Antwort: Das können wir Ihnen unmöglich sagen. Sein Algorithmus, Anwendung, Einheit, Computer, [...] spezifisch.

Sie berechnen die Entfernung zwischen den Partikeln? Vielleicht brauchst du eine kleinere Toleranz. Sie machen Wirtschaftlichkeitsrechnung? 1e-12 ist dann eine Dezimalzahl, die du sicher nicht in bar bekommst. Verwenden Sie stattdessen 1e-4. Oder verwenden Sie einen Algorithmus, der numerische Approximationen durchführt? Dann brauchst du eine höhere Toleranz. Wie viel Toleranz Sie in Ordnung sind, ist und bleibt immer eine Benutzerentscheidung.


Hinweis: Sie müssen wissen, welche Typen Sie verwenden, um diesen Mindestschwellenwert richtig festzulegen. MATLAB verwendet double als Standard, aber wenn Sie andere Typen verwenden, ist dieser Schwellenwert zu streng. Als Alternative können Sie

abs(diff) <= 100*eps(class(diff)) 

verwenden. Wenn Ihr Datentyp nicht fest/bekannt ist.

+1

Ich mag diese Antwort nicht. Die "eps" ist eine Funktion, die den Wert basierend auf dem Typ und System generiert. I.e. 'eps ('single')' für mich ist um '1e-07', und dein hartcodierter Wert wird nicht funktionieren. – Bernhard

+0

@Bernhard Aber das OP verwendet es nicht mit verschiedenen Typen. Ich kann Informationen über Typen bei Bedarf hinzufügen. Das OP verwendet "eps" -Funktionalität als "den kleinsten Unterschied zwischen Zahlen in diesem Maßstab", also 1 Bit Offset zwischen dem, was er will und hat. Persönlich glaube ich, dass das Feststellen Ihrer Toleranzen der beste Weg ist, um sicherzustellen, dass Sie wissen, was los ist. Was ist deine Alternative? 'eps ('double')' ist zu klein, dann 'eps ​​(' double ') * 100'. Wie ist das besser als meine Antwort? –

+0

Nun, @Alex fragt besonders nach dem Faktor 'k'. Was bestimmt den Fehler, den Sie erwarten können? Warum solltest du 'k' größer als nötig setzen? Ich bin an einer allgemeinen Antwort auf diese Frage interessiert. Der Faktor 100 ist jetzt genauso willkürlich, aber gibt es eine Auswahl, die aufgrund bekannter Einschränkungen wirklich Sinn macht? – Bernhard