2013-08-30 45 views
3

我有一個轉換,我試圖執行:64位的溢的數學轉換

uint64_t factor = 2345345345; // Actually calculated at runtime, but roughly this magnitude 

uint64_t Convert(uint64_t num) 
{ 
    return num * 1000ULL/factor; 
} 

對於最大num值由factor將之前乘法包裝。將訂單更改爲num/factor * 1000UL失去了一些不可接受的準確性。

我想重寫Convert()來處理所有可能num值:

uint64_t Convert(uint64_t num) 
{ 
    if(num > MAX_UINT64/1000ULL)  // pseudo code 
    { 
     // Not sure what to put here 
    } 
    else 
    { 
     return num * 1000ULL/factor; 
    } 
} 

我們考慮使用128位數學,但想如果可能的話,以避免它。

執行Convert()的最有效方法是什麼?這樣才能理想地處理最大的num,並且仍能產生正確的結果?

+0

你的意思是ULL?或者,您是否因特定原因使用32位因子? – kfsone

+0

@kfsone爲了清晰起見,我將其更改爲ULL。 – JaredC

+0

@kfsone - 1000是一個'int',它可以是或不是32位。無論如何,它會在使用它的各個地方轉換爲'uint64_t'。 –

回答

1

比化的分工:

r = 1000*(n/factor) + ((n%factor)*1000)/Factor 

你仍然可以運行到如果餘溢出問題(係數大),但是如果係數小於MAX_UINT64/1000你都OK。

3

有點老校友數學,您可以使用%計算仍然存在:

uint64_t Convert(uint64_t num) 
{ 
    uint64_t m = 1000; 
    uint64_t a = num/factor; 
    uint64_t t = num % factor; 
    uint64_t h = m * t/factor; 

    return a * m + h; 
} 

例子:

uint64_t Convert2(uint64_t num) 
{ 
    return num * 1000ULL/factor; 
} 

uint64_t Convert3(uint64_t num) 
{ 
    return num/factor * 1000ULL; 
} 


int main() 
{ 
    cout << Convert(std::numeric_limits<uint64_t>::max()) << endl; 
    cout << Convert2(std::numeric_limits<uint64_t>::max()) << endl; 
    cout << Convert3(std::numeric_limits<uint64_t>::max()) << endl; 
} 

輸出:

7865257077400 <--- // The correct one // 
7865257077  <--- // Value wrapped before multiplication // 
7865257077000 <--- // Low accuracy, loses remaining //