2010-06-25 6 views
0

J'ai besoin de convertir l'heure d'un format à un autre en C++ et elle doit être compatible avec plusieurs plates-formes. J'ai créé une structure comme mon conteneur de temps. Les champs de structure doivent également être unsigned int comme spécifié par le code existant.C++ Problème de débordement d'entier lors de la conversion d'un entier double en un entier non signé

struct time{ 
unsigned int timeInteger; 
unsigned int timeFraction; 
} time1, time2; 

Mathématiquement la conversion est la suivante:

time2.timeInteger = time1.timeInteger + 2208988800

time2.timeFraction = (time1.timeFraction * 20E-6) * 2e32

Voici mon code original en C++ mais quand j'essaye d'écrire dans un fichier binaire, le temps converti ne correspond pas aux données de vérité. Je pense que ce problème est dû à une erreur de type de casting? Ce code sera compilé dans VS2008 et sera exécuté.

void convertTime(){ 
    time2.timeInteger = unsigned int(time1.timeInteger + 2209032000); 
    time2.timeFraction = unsigned int(double(time1.timeFraction) * double(20e-6)*double(pow(double(2),32))); 
} 
+1

@ shuttle87: "better" est ouvert à l'interprétation, mais dans ce cas, se traduit par "will not compile", ce que peu de gens trouvent une amélioration en soi. –

+2

@ shuttle87: 'reinterpret_cast' ne fonctionnera pas pour la conversion de types numériques; vous avez besoin de 'static_cast' pour cela. Et ce n'est pas en utilisant la conversion en style C, c'est en utilisant la conversion de style d'initialisation C++. Personnellement, je trouve cela plus facile à regarder que static_cast pour les conversions numériques. –

+0

Bien que je crois 'non signé int (value)' est invalide pour des raisons techniques, mais accepté par la plupart des compilateurs. –

Répondre

2

Juste une supposition, mais êtes-vous en supposant que 2e32 == 2^32? Cette hypothèse serait logique si vous essayez d'escalader le résu Dans un entier de 32 bits. En fait 2e32 == 2 * 10^32

+0

Bonne prise. Merci! – Elpezmuerto

1

Légèrement sans lien, je pense que vous devriez repenser votre définition de type. Vous parlez essentiellement de deux différents types ici. Ils arrivent à stocker les mêmes données, mais dans des résultats différents.

Pour minimiser les erreurs dans leur utilisation, vous devez les définir comme deux types complètement distincts qui ont une conversion bien définie entre eux.

Tenir compte par exemple:

struct old_time { 
    unsigned int timeInteger; 
    unsigned int timeFraction; 
}; 

struct new_time { 
public: 
    new_time(unsigned int ti, unsigned int tf) : 
     timeInteger(ti), timeFraction(tf) { } 

    new_time(new_time const& other) : 
     timeInteger(other.timeInteger), 
     timeFraction(other.timeFraction) { } 

    new_time(old_time const& other) : 
     timeInteger(other.timeInteger + 2209032000U), 
     timeFraction(other.timeFraction * conversion_factor) { } 

    operator old_time() const { 
     old_time other; 
     other.timeInteger = timeInteger - 2209032000U; 
     other.timeFraction = timeFraction/conversion_factor; 
     return other; 
    } 

private: 
    unsigned int timeInteger; 
    unsigned int timeFraction; 
}; 

(EDIT: bien sûr ce code ne fonctionne pas pour les raisons indiquées ci-dessous

Maintenant, ce code peut être utilisé d'une manière sans friction sûre:.

time_old told; /* initialize … */ 

time_new tnew = told; // converts old to new format 
time_old back = tnew; // … and back. 
+0

Je pense que je vais suivre votre conseil et les définir comme des types distincts, mais cela n'aide pas le problème de moulage parce que dans le code ci-dessus, le facteur de conversion crée le débordement d'entier. Mais s'il vous plaît ne pas supprimer le code ci-dessus, il est très utile – Elpezmuerto

+0

@Elpezmuerto: oui, je suis désolé, je ne pouvais pas aider avec le problème original ... en ce moment j'ai du mal à envelopper ma tête autour de la conversion facteur ne correspond manifestement pas à un «entier non signé». –

+0

Je pense que le but est de gérer correctement le débordement d'entier qui en C et C++ se traduira par "enrouler autour". Peut-être que je peux créer une variable séparée pour tous les zéros associés à 2^32 et diviser timeFraction en 'char' ou' short' et écrire dans mon fichier binaire en morceaux plutôt qu'un complet 'unsigned int' complet? – Elpezmuerto

0

Le problème est que (20^-6) * (2 e32) est beaucoup plus grand que UINT_MAX. Peut-être que vous vouliez dire 2 à la puissance de 32, ou UINT_MAX, plutôt que 2e32.

En outre, votre première ligne avec l'entier, la valeur initiale doit être inférieure à (2^32 - 2209032000), et en fonction de ce que cela est mesuré, il pourrait enrouler aussi. À mon avis, définissez la première valeur pour être un long long (normalement 64 bits) et changer 2e32.

Si vous ne pouvez pas modifier le type, il peut s'avérer nécessaire de stocker le champ car il en résulte un double, disons, puis un cast en unsigned int avant utilisation.

Questions connexes