2014-03-03 26 views
3

它試圖解決這個問題,給出N,K amd M,找到最大整數T,例如N*(K^T) <= MN,K and M可以是10^18的值。所以long long就足夠了。 我嘗試了用迭代來解決對T變量的值在溢出的情況下始終爲負

int T = 0; 
long long Kpow = 1; 
while(1) 
{ 
    long long prod = N*Kpow; 
    if(prod > M) 
    break; 
    T++; 
    Kpow = Kpow*K; 
} 

但由於N*Kpow可以走出去的long long範圍,有必要使用一些大的整數來處理產品。但是,我發現了一些其他的代碼,巧妙地處理這種情況,

long long prod = N*Kpow; 
if(prod < 0) 
    break; 

即使我一直認爲,在溢出,變量的值變爲負。在溢出情況下,情況總是如此,有時甚至是正值?

+2

「如果表達式的評估過程中,其結果是不數學定義或不是在其類型 表示的值的範圍,該行爲是未定義」。 – PlasmaHH

回答

7

從語言的角度來看,有符號整數溢出的行爲是undefined。這意味着任何事情都可能發生 - 它可能是負面的,它可以保持不變,程序可能會崩潰,或者它可以在線訂購披薩。

在實踐中最可能發生的事情取決於您正在運行的處理器架構 - 因此您必須查閱平臺規格才能知道。

但我猜你不能保證溢出是負面的。作爲一個人爲的例子:

signed char c = 127; 
c += 255; 
std::cout << (int)c << '\n'; 

這正好print 126在x86。但是,它又可以做任何事情。

+3

溢出行爲也可以隨編譯器中的優化級別而改變,因爲編譯器可以假定溢出不會發生在正確的程序中並相應地進行優化。 –

-4

正如在任何其他情況下使用任何長度的帶符號整數一樣......溢出使得數字爲負,當且僅當溢出到符號位的特定位打開時。

意思是說,如果你的算術結果會給你一個溢出,如果你將可變字的長度加倍,會使當前的符號位關閉,你很可能會產生一個錯誤的結果是積極的。

+2

其實並非如此。有符號整數溢出的行爲是未定義的。有一些系統(例如dps)會導致溢出導致最大值。 – bolov

+0

-1 _'overflow使數字消極'_這是完全錯誤的!溢出是未定義的行爲。它可以做任何事情... –

-1

不能將此問題轉換爲K^T < =(M + N-1)/ N?

就溢出檢測而言,通常會進行加法和減法,就好像數字是無符號數一樣,溢出位是基於有符號數學運算設置的,而進位/借位位是基於無符號數學運算設置的。對於乘法,對於有符號或無符號乘法,結果的低階是相同的(這就是爲什麼ARM CPU只對來自32位操作數的64位結果進行有符號/無符號乘法的原因)。如果產品太大而無法安裝在接收產品的寄存器中,就會發生溢出,例如產生39位產品的32位乘法,應該放入32位寄存器。對於除法,如果除數爲零或者商數太大而無法適應接收商的寄存器,例如64位除數除以32位除數,則會產生溢出,從而產生40位商。對於乘法和除法,操作數是否被簽名並不重要,只要結果的大小適合接收結果的寄存器。

+0

這是一個問題,而不是答案。 –

+0

這是解決原始帖子面臨的問題的可能解決方案。 – rcgldr

0

否。變量的值爲而不是在溢出的情況下總是負值。

使用帶符號整數,C11dr §3.7.13未定義行爲「未定義行爲的一個示例是整數溢出行爲。」因此在溢出之後沒有測試,這肯定會在編譯器和平臺上起作用。

檢測到潛在的溢出之前它可能發生。

int T = 0; 
long long Kpow = 1; 
long long Kpow_Max = LLONG_MAX/K; 
long long prod_Max = LLONG_MAX/N; 

while(1) 
{ 
    if (Kpow > prod_Max) Handle_Overflow(); 
    long long prod = N*Kpow; 
    if(prod > M) 
    break; 
    T++; 
    if (Kpow > Kpow_Max) Handle_Overflow(); 
    Kpow = Kpow*K; 
} 
相關問題