Frage

Ich habe einig Code einen Zeitwert von Queryperformancecounter auf einen doppelten Wert in Millisekunden zurück zu konvertieren, da dies bequemer ist, mit zu zählen.

Die Funktion sieht wie folgt aus:

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

Das Problem Ich bin vor kurzem (ich glaube nicht, ich habe dieses Problem vor, und es wird keine Änderungen am Code vorgenommen wurden) ist, dass das Ergebnis nicht sehr genau ist. Das Ergebnis enthält keine Dezimalzahlen, aber es ist noch ungenauer als 1 Millisekunde.

Wenn ich den Ausdruck in dem Debugger eingeben, ist das Ergebnis so genau, wie ich erwarten würde.

Ich verstehe, dass eine Doppel nicht die Genauigkeit eines 64-Bit-Integer halten kann, aber zu diesem Zeitpunkt erforderliche Performance nur 46 Bits (und ein Doppel sollte 52 Bit ohne Verlust speichern kann) Außerdem scheint es seltsam, dass der Debugger ein anderes Format verwenden würde die Teilung zu tun.

Hier sind einige Ergebnisse, die ich bekam. Das Programm wurde im Debug-Modus, Floating Point-Modus in C ++ Optionen kompiliert wurde auf den Standardwert (Precise (/ fp: präzise))

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

Weiß jemand, warum die Genauigkeit in dem Debugger Watch im Vergleich zum Ergebnis in meinem Programm unterscheidet?

Update: Ich habe versucht, 30270310439445 von timerPerformanceCounter.QuadPart Abzug vor der Umwandlung und Spaltung zu tun, und es scheint nun in allen Fällen korrekt. Vielleicht der Grund, warum da sehe ich dieses Verhalten nur könnte nun sein, weil die Verfügbarkeit meines Computers jetzt 16 Tage ist, so dass der Wert größer ist als ich gewohnt bin? So erscheint es eine Teilgenauigkeit Problem mit großen Zahlen zu sein, aber das ist immer noch nicht erklären, warum die Division in den Watch-Fenstern noch richtig war. Ist es verwenden, um eine höhere Präzision Typ als das Doppelte für seine Ergebnisse?

War es hilfreich?

Lösung 2

Danke, dezimal mit würde wahrscheinlich auch eine Lösung sein. Denn jetzt habe ich einen etwas anderen Ansatz, das mein Programm funktioniert auch gut, zumindest solange nicht länger als eine Woche nicht laufen oder so ohne Neustart. Ich erinnere mich nur den Leistungsindikator, wann mein Programm gestartet, und subtrahieren diese von der aktuellen Zähler vor dem Konvertieren der Teilung zu verdoppeln und zu tun.

Ich bin nicht sicher, welche Lösung am schnellsten sein würde, ich denke, ich Benchmark haben würde, dass zuerst.

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();
}

Andere Tipps

Adion,

Wenn Sie nicht die Leistung Hit ausmacht, werfen Sie Ihre Quadpart Zahlen anstelle von Doppel dezimal bevor die Division durchgeführt wird. Dann warf die resultierende Zahl zurück zu verdoppeln.

Sie sind richtig über die Größe der Zahlen. Es wirft die Genauigkeit der Fließkommaberechnungen aus.

Für mehr darüber, als Sie wahrscheinlich schon immer mal wissen wollten, finden Sie unter:

Was jeder Informatiker wissen sollten über Gleitpunktarithmetik http://docs.sun.com/source/806-3568/ncg_goldberg. html

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top