2010-01-07 16 views
1

使用整數計數器時,你如何解決最大值問題,看起來像整數計數器 - 最大值時該怎麼辦?

​​

當此達到最大值,你怎麼知道這事?你是否增加了另一個計數器來計算髮生這種事情的頻率?

我的問題關注java。

+0

嗨大衛, 我這樣做,但有些仍然打開,用戶想要稍後編輯或關閉。所以沒有太多的問題要檢查和回答。 :) – 2010-01-07 00:12:26

+0

@Andreas:不用擔心編輯部分 - 如果用戶想編輯他們的答案,他們仍然可以在接受它之後做到這一點。 – 2010-01-07 01:51:10

回答

4

對於一個快速飽和int增量(一個當它到達MAX_VALUE即停止工作),我想你可以寫:

counters = (counter+1) + ((counter+1)>>31); 

或者

counters = (counter+1) - ((counter+1)>>>31); 

還是在開心的利益,爲AtomicInteger,我認爲:

private final AtomicInteger counter = new AtomicInteger(0); 

public void increment() { 
    int count; 
    do { 
     count = counter.get(); 
     if (count == Integer.MAX_VALUE) { 
      return; 
     } 
    } while (!counter.compareAndSet(count, count+1)); 
} 
4

選擇一個數值類型,其範圍足以滿足您的要求。因此,如果int不夠大,請使用longBigInteger

當您的int超過Integer.MAX_VALUE時,您會知道它會溢出並變爲負值。

1

那麼,你做什麼取決於你需要什麼。

如果您是通過網絡發送請求消息的一種ID生成器,那麼根據您的需要,您可能不會在意溢出,因爲最早的ID將在此時過期。如果以前從未見過該值是重要的,那麼您使用的數據類型較大 - 一個64位長的數據類型,你有9個以上的值,所以應該是很多的(儘管在很多情況下,21億美元詮釋應該是足夠了!)

+0

只是將事情看得很透徹:如果你在一秒內耗盡了大約43億個無符號32位整數的值,假定速度恆定需要大約68年的時間 - 這大約是每3人2個ID在地球*每秒*,這是瘋狂的不切實際的。 – 2010-01-07 00:42:39

+0

在長時間翻身時,您不需要關心它,因爲ID可能已經過期並且可以重複使用,或者您有更大的問題能夠存儲許多EB字節數 - 如果不是Z字節或甚至yottabytes - 數據(某人使用ID作爲事物,所以必須有一些與之相關的數據)。 – 2010-01-07 00:43:14

1

有一個int作爲計數器和另一個int來計數溢出給你相同的範圍作爲長(實際上,因爲整數簽名,這是一個溢出計數器浪費位)。

如果您希望計數器溢出,您可能需要使用BigIntegers。

7

您可以通過比較Integer.MAX_VALUE來判斷您是否達到了最大值。

+2

有時候「簡單就是最好的」:) – akuhn 2010-01-07 00:32:10

2

丹的答案是正確的。但是,如果你肯定每次遞增1,並且出於某種原因需要使用int(無法想象爲什麼),那麼你確實需要第二個計數器,比如說b,每次都增加一個++ == max_value (或++%max_value == 0)。你可以爲b等做同樣的事情。本質上,你只是在基礎max_value算術,而不是基數爲10.

+0

不錯的想法 - 雖然它會很有趣,試圖將所有這些計數器結合在一起:int total = c * Integer.MAX_VALUE * Integer.MAX_VALUE + b * Integer .MAX_VALUE + a' ... ;-) – 2010-01-07 01:52:52

3

你必須知道'counter'變量可能增長的大小。

  • Integer.MAX_VALUE的是2147483647
  • Long.MAX_VALUE是9223372036854775807L(相當大)

如果沒有這些2的足夠大,BigInteger的沒有最大(除非你的機器能處理) 。

在實踐中,你想要計算的大部分東西很容易適合int。

-2

您可以從Integer.MAX_VALUE開始counter並關閉。你可以停在Zero或去-Integer.MAX_VALUE

+2

但這並不能解決檢測或應對溢出的問題。無論如何,從MAX_VALUE到MAX_VALUE的相同數量的滴答數量將從MAX_VALUE降到零。此外,計數器的值會很難處理(我可以保證在任何非平凡的情況下,有人會忘記「真實」值是「MAX_VALUE - counter」)。 – 2010-01-07 01:55:09

1

Java沒有解決ct也不會導致整數溢出發生任何事情,無論是負值還是正值,使用int或long類型。

原始類型int和long及其對應的類類型Int和Long根據二進制補碼算法在正方向或負方向溢出。最大正值之後的第一個值是最大負值。對於整數,它是Integer.MIN_VALUE。長期以來,它是Long.MIN_VALUE。反過來發生負溢出。最大負值之後的第一個值是最大正值。對於整數,它是Integer.MAX_VALUE。長期以來,它是Long.MAX_VALUE。

使用遞增+1的計數器,檢測溢出的一種非常簡單的方法是檢查它是否已達到Integer.MAX_VALUE(對於int或Long.MAX_VALUE很長時間),並採取一些優雅動作,如啓動從0開始。另一種方法是停止處理或容納二進制補碼運算的行爲,該運算將滾動到最大負值並從那裏繼續。如果溢出確實是一個問題,因爲您使用的是非常大的整數,那麼請使用BigInteger類的實例。它幾乎和int一樣有效,並且可能比在自己的代碼中處理二進制補碼翻轉更有效率。

0

回答這個問題可能有點晚,但我傾向於做這樣的事情。

if (atomicInt.get() < 0 || atomicInt.incrementAndGet() > MAX) { 
     // ... 
    } 

一旦溢出就停止遞增。