Array Minus-Werte



  • Hallo,

    ich bräuchte bitte einen Tipp, wo möglicherweise der Fehler liegen könnte (bin ziemlicher Anfänger).

    Ich habe ein großes Array mittels malloc allokiert und beschreibe den Array mit float-Werten komplett aus. Nachdem gebe ich das Ergebnis an Matlab zurück. Dazu "kopiere" ich den Array in einen anderen mittels memcpy.
    Nun kommt es vor das an einem bestimmten Index ab und zu willkürlich ein Minuswert erscheint, was nicht sein sollte. Um zu kontrollieren, ob der Array versehentlich mit Minuswerten beschrieben wird, habe ich zur Kontrolle den Wert per printf ausgegeben. Jedoch zeigt er mir nie den Minuswert an. Zudem kommt es bei gleichen Parametern nur ab und zu der Minuswert, was eigentlich nicht sein sollte.

    Kann mir bitte jmd einen Tipp geben, wo möglicherweise das Problem liegen könnte? Thx!



  • Wo/wie stellst du die Minuswerte fest?
    In Matlab?
    Wieso kopierst du das vermeintliche Array nochmal bevor zu es weitergibst?
    Wieso gibst du das vermeintliche Array nicht direkt weiter?
    Bist du dir sicher, dass der Typ float von Matlab identisch interpretiert wird wie in deinem C-Programm?



  • ok, ich habs anscheinend einschränken können. Es gibt einen Teil im C-Code, wo ich bei einem Float-Wert nur 5 Kommastellen berücksichtigen will. Das schaut prinzipell so aus:

    floatTmp = oldVal*1000000;
    intTmp = floatTmp;
    floatTmp = (float) intTmp/1000000/CONSTANTE;

    da ich kein C-experte bin, kann es sein das aus einem positiven Wert beim "abschneiden" ein negativer Wert wird? Was kann ich machen, damit ich trotzdem weiterhin nur 5 Kommastellen habe? Tausend Dank!



  • Wutz schrieb:

    Wo/wie stellst du die Minuswerte fest?
    In Matlab?
    Wieso kopierst du das vermeintliche Array nochmal bevor zu es weitergibst?
    Wieso gibst du das vermeintliche Array nicht direkt weiter?
    Bist du dir sicher, dass der Typ float von Matlab identisch interpretiert wird wie in deinem C-Programm?

    1. den Minuswert hab ich jetzt mittlerweile im C-code fest machen können.

    2. ich benutze MEX...ich muss es an einen bestimmten vordefinierten Array weitergeben, die diese als Rückgabewerte bewertet wird. Vielleicht gehts einfacher, aber ich kenn mich da zu wenig aus.

    3. siehe 1)


  • Mod

    Erstell ein Minimalbeispiel. Siehe dritter Link in meiner Signatur.

    Allgemein verrechnen sich Computer eher nicht. Insbesondere wenn eine andere mögliche Fehlerquelle ein Anfänger ist, der mit Fließkommazahlen und Arrays hantiert (sind nun einmal beides etwas schwierige und unintuitive Themen. Das ist ganz normal, dass man am Anfang Fehler macht), dann würde ich eher da den Fehler vermuten.

    floatTmp = oldVal*1000000;
    intTmp = floatTmp;
    floatTmp = (float) intTmp/1000000/CONSTANTE;
    

    Die zweite Zeile ist undefiniert, falls floatTmp > INT_MAX. Das kann auch gerne mal was negatives werden.

    Erklär bitte mal, in welchem Zusammenhang es jemals Sinn machen sollte, in einer Rechnung zu runden. Ich kann mir keinen Reim darauf machen. Wenn du das genauer erklärst, kann man eine bessere Lösung angeben. Für mich macht Runden jedenfalls nur Sinn, wenn man die Zahl ausgeben möchte. Daher gibt es auch schon Rundungsfunktionalität in den Ausgabefunktionen.



  • Durch "Abschneiden" via int-Cast ändert sich das Vorzeichen im Ergebnis nicht. (Überläufe mal unberücksichtigt)
    Das Hantieren und Rumrechnen mit "Kommastellen" bei Fließkommazahlen ist nur sinnvoll in Zusammenhang mit einer String-Repräsentation, und wenn die gewünscht wird, übergib sie eben als String- und nicht im Binärformat.



  • SeppJ schrieb:

    Erstell ein Minimalbeispiel. Siehe dritter Link in meiner Signatur.

    Allgemein verrechnen sich Computer eher nicht. Insbesondere wenn eine andere mögliche Fehlerquelle ein Anfänger ist, der mit Fließkommazahlen und Arrays hantiert (sind nun einmal beides etwas schwierige und unintuitive Themen. Das ist ganz normal, dass man am Anfang Fehler macht), dann würde ich eher da den Fehler vermuten.

    floatTmp = oldVal*1000000;
    intTmp = floatTmp;
    floatTmp = (float) intTmp/1000000/CONSTANTE;
    

    Die zweite Zeile ist undefiniert, falls floatTmp > INT_MAX. Das kann auch gerne mal was negatives werden.

    Erklär bitte mal, in welchem Zusammenhang es jemals Sinn machen sollte, in einer Rechnung zu runden. Ich kann mir keinen Reim darauf machen. Wenn du das genauer erklärst, kann man eine bessere Lösung angeben. Für mich macht Runden jedenfalls nur Sinn, wenn man die Zahl ausgeben möchte. Daher gibt es auch schon Rundungsfunktionalität in den Ausgabefunktionen.

    Hallo Sepp, danke für deine Mühe!
    Ich habs gleich getestet "floattmp > INT_MX", indem ich einfach das "runden" weggelassen habe und seit dem hab ich auch keine Minuswerte mehr. Danke! Aber, der Grund weshalb ich das gemacht habe ist der, weil ich Referenzwerte mit nur bis zu 5 Kommastellen habe. D.h. ich möchte die Berechnungen mit den Referenzwerten abgleichen. Was wäre hier ein vernünftiger Lösungsansatz?


  • Mod

    dummy2k schrieb:

    Was wäre hier ein vernünftiger Lösungsansatz?

    Dazu müsste ich genauer wissen, was es mit den Referenzwerten auf sich hat. Wieso rechnest du nicht einfach mit denen? Wie erfolgt der Abgleich? Wie sind die Referenzwerte berechnet worden?

    Derzeit sieht es so aus, als wolltest du mitten in der Rechnung auf 5 Dezimalstellen runden. Die Referenzwerte sind doch sicherlich nicht von einem Menschen im Dezimalsystem mit Zettel und Stift berechnet worden, oder? Das wäre nämlich der einzige Fall, in dem ich mir eine Rechnung mit 5 Dezimalstellen vorstellen kann.

    Ich mache dir bewusst nicht vor, wie man in der Rechnung auf 5 Deziamlstellen rundet, weil du damit sicherlich Unsinn treiben würdest. Es ist auch prinzipiell gar nicht möglich, da viele Zahlen, die im Dezimalsystem endlich viele Stellen haben, mit einer binären Fließkommazahl gar nicht exakt dargestellt werden können. Beispielsweise 1234.125 wäre gerundet auf 5 Stellen 1234.1, was aber als float 1234.0999755859375 wäre.



  • SeppJ schrieb:

    dummy2k schrieb:

    Was wäre hier ein vernünftiger Lösungsansatz?

    Dazu müsste ich genauer wissen, was es mit den Referenzwerten auf sich hat. Wieso rechnest du nicht einfach mit denen? Wie erfolgt der Abgleich? Wie sind die Referenzwerte berechnet worden?

    Derzeit sieht es so aus, als wolltest du mitten in der Rechnung auf 5 Dezimalstellen runden. Die Referenzwerte sind doch sicherlich nicht von einem Menschen im Dezimalsystem mit Zettel und Stift berechnet worden, oder? Das wäre nämlich der einzige Fall, in dem ich mir eine Rechnung mit 5 Dezimalstellen vorstellen kann.

    Die Referenzwerte dienen als Kontrolle, ob das Skript richtig rechnet. Die habe ich als Txt-File mit 5 Stellen bekommen. Der Abgleich erfolgt, indem ich das Ergebnis ebenfalls in ein Txt-file schreib und dann mit einem Tool das abgleichen lasse. Wie die Referenzwerte berechnet worden sind, weiß ich nicht. Ich hab nur das Sollresultat in Form dieser Txt bekommen.

    Btw: im Netz hat einer geschieben, dass Float-Werte ab ca. der 5,6 Kommastelle sowieso nur Schmafu steht. Oder ist das Blödsinn? Thx!


  • Mod

    dummy2k schrieb:

    Die Referenzwerte dienen als Kontrolle, ob das Skript richtig rechnet. Die habe ich als Txt-File mit 5 Stellen bekommen.

    Also möchtest du nur das Endergebnis gerundet ausgeben, nicht während der Rechnung Rundungsaktionen durchführen. ➡ printf. Das kann jede Menge Formatierung für Zahlen. Unter anderem auch Runden auf eine gewisse Anzahl Dezimalstellen.

    Btw: im Netz hat einer geschieben, dass Float-Werte ab ca. der 5,6 Kommastelle sowieso nur Schmafu steht. Oder ist das Blödsinn?

    Nein, das ist korrekt, was er da schreibt. Ein float enthält 24 Bit Information über die (binären) Stellen (+8 Bit über die Position des Kommas + 1 Bit über das Vorzeichen). Das sind log_10(2^24)~=7.2 Dezimalstellen. Konkret kann man jede Zahl auf 6 Dezimalstellen genau darstellen und braucht höchstens 9 Dezimalstellen, um einen float eindeutig im Dezimalsystem darstellen zu können.



  • SeppJ schrieb:

    dummy2k schrieb:

    Die Referenzwerte dienen als Kontrolle, ob das Skript richtig rechnet. Die habe ich als Txt-File mit 5 Stellen bekommen.

    Also möchtest du nur das Endergebnis gerundet ausgeben, nicht während der Rechnung Rundungsaktionen durchführen. ➡ printf. Das kann jede Menge Formatierung für Zahlen. Unter anderem auch Runden auf eine gewisse Anzahl Dezimalstellen.

    Das habe ich auch gemacht 🙂 Ich habe die "Rundung" auch gemacht, weil in Matlab die Rückgabewerte vom C-Code ab der 5. Stelle verschieden von der C-Berechnung waren und ich nicht mit falschen Werten weiterrechnen wollte. Keine Ahnung wieso, aber da du aber bestätigt hast, dass ab einer gewissen Dezimalstelle nur Unfug steht, brauche ich wohl die Stellen nicht mehr berücksichtigen. D.h. die Rundung werde ich somit weglassen, scheint mir aufgrund deiner Argumentation auch richtig.

    Danke nochmal für deine Mühe und Zeit!! Weiß das echt zu schätzen 🙂

    @wutz
    achja, auch dir ein Danke 🙂


  • Mod

    Rechnet matlab per default nicht mit double precision (auch wenn es nur 5 Stellen anzeigt)? Das kam mir sowieso schon komisch vor, dass du hier mit single precision rechnest. Kein Wunder, wenn du dann was anderes rausbekommst. Rechne mal komplett mit double. Das Ergebnis wird gewiss bis zur letzten Stelle mit dem Ergebnis aus matlab identisch sein (sofern du die Rechnung an sich richtig programmiert hast).


Log in to reply