Question

J'ai un code pour convertir une valeur de temps de retour QueryPerformanceCounter à une double valeur en millisecondes, car cela est plus commode de compter avec.

La fonction ressemble à ceci:

double timeGetExactTime() {
    LARGE_INTEGER timerPerformanceCounter, timerPerformanceFrequency;
    QueryPerformanceCounter(&timerPerformanceCounter);
    if (QueryPerformanceFrequency(&timerPerformanceFrequency)) {
        return (double)timerPerformanceCounter.QuadPart / (((double)timerPerformanceFrequency.QuadPart) / 1000.0);
    }
    return 0.0;
}

Le problème que je vais avoir récemment (je ne pense pas que j'ai eu ce problème avant, et aucune modification n'a été apportée au code) est que le résultat est pas très précis. Le résultat ne contient pas de décimales, mais il est encore moins précis que 1 milliseconde.

Quand j'entre l'expression dans le débogueur, le résultat est aussi précis que je me attends.

Je comprends qu'une double ne peut pas maintenir la précision d'un entier de 64 bits, mais à ce moment, le PerformanceCounter seulement requis 46 bits de (et un double devrait être en mesure de stocker 52 bits sans perte) En outre, il semble étrange que le débogueur utiliserait un format différent pour faire la division.

Voici quelques résultats que j'ai eu. Le programme a été compilé en mode débogage, flottant en mode point dans les options C ++ a été défini sur la valeur par défaut (Précision (/ fp: précis))

timerPerformanceCounter.QuadPart: 30270310439445
timerPerformanceFrequency.QuadPart: 14318180
double perfCounter = (double)timerPerformanceCounter.QuadPart;
30270310439445.000

double perfFrequency = (((double)timerPerformanceFrequency.QuadPart) / 1000.0);
14318.179687500000

double result = perfCounter / perfFrequency;
2114117248.0000000

return (double)timerPerformanceCounter.QuadPart / (((double)timerPerformanceFrequency.QuadPart) / 1000.0);
2114117248.0000000

Result with same expression in debugger:
2114117188.0396111

Result of perfTimerCount / perfTimerFreq in debugger:
2114117234.1810646

Result of 30270310439445 / 14318180 in calculator:
2114117188.0396111796331656677036

Quelqu'un sait-il pourquoi la précision est différent du débogueur montre par rapport au résultat dans mon programme?

Mise à jour: J'ai essayé de déduire 30270310439445 timerPerformanceCounter.QuadPart avant de faire la conversion et la division, et il ne semble pas être précis dans tous les cas maintenant. Peut-être la raison pour laquelle je ne vois que ce comportement pourrait maintenant être parce que mon temps de fonctionnement de l'ordinateur est maintenant 16 jours, la valeur est plus grande que je suis habitué? Donc, il ne semble pas être un problème de précision de la division avec un grand nombre, mais cela n'explique pas pourquoi la division était toujours correcte dans la fenêtre Watch. Est-il utiliser un type plus précision que le double des résultats de it?

Était-ce utile?

La solution 2

Merci, en utilisant décimal serait probablement une solution aussi. Pour l'instant j'ai pris une approche légèrement différente, qui fonctionne aussi bien, au moins aussi longtemps que mon programme ne fonctionne pas plus d'une semaine ou sans redémarrer. Je me souviens du compteur de performance quand mon programme a commencé, et soustrayez du contre-courant avant de se convertir à doubler et de faire la division.

Je ne suis pas sûr quelle solution serait la plus rapide, je suppose que je dois référence que le premier.

bool perfTimerInitialized = false;
double timerPerformanceFrequencyDbl;
LARGE_INTEGER timerPerformanceFrequency;
LARGE_INTEGER timerPerformanceCounterStart;
double timeGetExactTime()
{
    if (!perfTimerInitialized) {
        QueryPerformanceFrequency(&timerPerformanceFrequency);
        timerPerformanceFrequencyDbl = ((double)timerPerformanceFrequency.QuadPart) / 1000.0;
        QueryPerformanceCounter(&timerPerformanceCounterStart);
        perfTimerInitialized = true;
    }

    LARGE_INTEGER timerPerformanceCounter;
    if (QueryPerformanceCounter(&timerPerformanceCounter)) {
        timerPerformanceCounter.QuadPart -= timerPerformanceCounterStart.QuadPart;
        return ((double)timerPerformanceCounter.QuadPart) / timerPerformanceFrequencyDbl;
    }

    return (double)timeGetTime();
}

Autres conseils

Adion,

Si cela ne vous dérange pas le coup de performance, jeter vos numéros de QuadPart en décimal au lieu de la double avant d'effectuer la division. Rabattre ensuite le nombre résultant sur double.

Vous avez raison de la taille des chiffres. Il jette la précision des calculs en virgule flottante.

Pour en savoir plus sur ce que vous avez probablement jamais voulu savoir, voir:

Ce que tout informaticien doit savoir sur Virgule flottante Arithmétique http://docs.sun.com/source/806-3568/ncg_goldberg. html

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top