[boost.date_time] Plattform-spezifische Caveats?
-
Hallo zusammen
Folgender Code:
#include <boost/assign/list_of.hpp> #include <boost/assign/list_of.hpp> #include <boost/date_time/posix_time/posix_time_types.hpp> #include <iostream> #include <vector> using namespace boost::assign; using namespace boost::posix_time; using namespace std; int main() { time_duration timeStep(minutes(15)); vector<time_duration> differences(100, minutes(15)); for (unsigned int i = 0; i < differences.size(); ++i) { time_duration::tick_type numerator(timeStep.total_milliseconds()); time_duration::tick_type denominator(differences.at(i).total_milliseconds()); double multiplicator = numerator / denominator; double random = rand(); cout << "num: " << numerator << ", " << "den: " << denominator << endl; cout << i << ": " << (random * multiplicator) << " (mult: " << multiplicator << ')' << endl; } return 0; }
Gibt auf meinem Entwicklungs-Rechner folgenden Output:
num: 900000, den: 900000 0: 41 (mult: 1) num: 900000, den: 900000 1: 18467 (mult: 1) ... num: 900000, den: 900000 99: 16541 (mult: 1)
Auf meiner Embedded-Zielplattform hingegen erhalte ich folgenden, ungekürzten Output:
num: 900000, den: 900000 0: 6.2635e+09 (mult: 3.47145) num: 900000, den: 900000 1: 6.43756e-301 (mult: 7.61038e-310) num: 900000, den: 4614999431078329248 2: -5936.41 (mult: -3.53002e-06) num: 900000, den: 153640644625800 3: -6053.29 (mult: -3.53036e-06) num: 900000, den: -4697926556549346372 4: 2.49012e+10 (mult: 12.7193) num: 900000, den: -4697925780254122828 1074507244: 3.18828e-301 (mult: 7.51531e-310)
Traurig dabei ist: Wenn ich den "total_milliseconds()"-Teil durch Konstanten ersetze...
time_duration::tick_type numerator(900000); time_duration::tick_type denominator(900000);
funktioniert der Code wie erwartet:
num: 900000, den: 900000 0: 1.80429e+09 (mult: 1) num: 900000, den: 900000 1: 8.46931e+08 (mult: 1) ... num: 900000, den: 900000 99: 1.9563e+09 (mult: 1)
Gibt es irgendwelche Caveats, dich ich im Zusammenhang mit dieser Funktion beachten sollte?
Danke für jeden Hinweis und Gruss
Kessi
-
Nach zusätzlichen Experimenten zeichnet sich ab, dass "time_duration::tick_type" auf dem Zielsystem eine 8-Byte grosse Zahl ist. Sie von Anfang an als "double" zu verwenden, löst das Problem nicht, von "total_milliseconds" auf "total_seconds" zu wechseln aber schon:
double numerator(timeStep.total_seconds()); double denominator(differences.at(i).total_seconds());
Das ist für meinen Use Case ausreichend, lässt mich aber mit einem sehr unangenehmen Gefühl zurück. Übrigens, folgender Code funktioniert ebenfalls:
long numerator(timeStep.total_milliseconds()); long denominator(differences.at(i).total_milliseconds());
Dabei ist zu beachten, dass "long" auf dem Zielsystem ein 4-Byte Datentyp ist. Die Verwendung von "total_milliseconds" alleine macht den Absturz also noch nicht perfekt, erst, das Resultat in einem "long long" (= "time_duration::tick_type") zu Speichern, bringt das System zum Versagen... Das aber auch nicht im Allgemeinen Fall - anstatt eines Vektors von "time_duration"s nur eine einzelne zu verwenden, löst das Problem ebenfalls.
time_duration timeStep(minutes(15)); time_duration difference(minutes(15));
Ich werde mich vorerst auf "total_seconds()" beschränken, muss aber davon ausgehen, dass mir dieses System noch sehr viel Ärger bescherern wird. Vielleicht ist ein Post in der Boost Mailing-Liste ebenfalls angebracht. Werde das bei Gelegenheit nachholen.
Danke auf jeden Fall an alle Gegenleser und Gruss
Kessi
-
Um Boost noch komplett aus der Gleichung zu nehmen:
#include <cstdlib> #include <iostream> #include <vector> using namespace std; int main() { long long step(900000); vector<long long> differences(100, 900000); for (unsigned int i = 0; i < differences.size(); ++i) { double numerator(step); double denominator(differences.at(i)); double multiplicator = numerator / denominator; double random = rand(); cout << i << ": " << (random * multiplicator) << " (mult: " << multiplicator << ", " << "num: " << numerator << ", " << "den: " << denominator << ')' << endl; } return 0; }
Resultat:
0: inf (mult: inf, num: 900000, den: 3.47145) 1: 5.99277e+13 (mult: 70758.6, num: 900000, den: 7.5603e-310) 2: 2.14001e-160 (mult: 1.27253e-169, num: 900000, den: -1.26001e-05) 35420: 2.22566e+14 (mult: 129803, num: 900000, den: -1.26015e-05)
Vektoren von "long long"s sind auf dieser Plattform scheinbar eine böse Sache, denn:
vector<long long> differences(1, 900000);
ergibt:
0: inf (mult: inf, num: 900000, den: 3.47145)
aber:
long long difference(900000); for (unsigned int i = 0; i < 100; ++i) { double numerator(step); double denominator(difference); ...
resultiert in:
0: 41 (mult: 1, num: 900000, den: 900000) 1: 18467 (mult: 1, num: 900000, den: 900000) ... 99: 16541 (mult: 1, num: 900000, den: 900000)
Ich schätze, jetzt ist es definitiv ein Fall für den Plattform-Hersteller...
Danke trotzdem für eure Geduld und Gruss
Kessi
-
Klarer Kompilerfeler :p