2012-04-16 12 views
1

多くの場合、は40億の番号の中から欠けている番号を検出しようとしています。
推奨されるアプローチは、(メモリの制約が問題の一部である)ビットセットを使用するように見えます。
投稿の例はfind-an-integer-not-among-four-billion-given-onesで、私はここのSOにリンクすることもできます。
40億からの欠けている番号を見つける

私の問題は次のとおりです。ビットセットのアプローチは暗黙のうちに数字がではない - 否定であると思われます。私がリンクしている記事の例として、Javaでこのコードスニペットがあります。

int radix = 8; 
byte[] bitfield = new byte[0xffffffff/radix]; 
void F() throws FileNotFoundException{ 
    Scanner in = new Scanner(new FileReader("a.txt")); 
    while(in.hasNextInt()){ 
     int n = in.nextInt(); 
     bitfield[n/radix] |= (1 << (n%radix)); 
    } 

    for(int i = 0; i< bitfield.lenght; i++){ 
     for(int j =0; j<radix; j++){ 
      if((bitfield[i] & (1<<j)) == 0) System.out.print(i*radix+j); 
     } 
    } 
} 

しかし、Javaではすべての整数が署名されています。その結果、ポストされたコードは負の数で壊れます。このint n = in.nextInt();は、ネガを返すことができます。

このような問題/演習では、何とか私の混乱は約2部です:
1)負数を表すためにビットセットを使用できますか?どうやって?
2)問題の解決策は、どういうわけか特定のプログラミング言語に関係していますか?例えば。 C++では、符号なしの数値があるので、範囲が負ではないという仮定を受け入れることができます。

誰かが私にこれを理解してもらえますか?

+0

単純に数値を「long」として扱い、2^31を加算してすべて正の値にすることはできません。 –

+0

@OliCharlesworth:これを行った場合、2つの数字(正と負)のビットインデックスは同じになりませんか?見つからない場合はどうすればよいでしょうか?スキャンの対応するビットインデックスはtrueに設定されますが、存在するでしょう – Cratylus

+0

私は、すべての値に負の値だけでなく、オフセットを加えることを提案しています。 –

答えて

4

long n = in.nextInt() & 0xFFFFFFFFL; 
bitfield[(int) (n/radix)] |= (1 << (n%radix)); 

または

final int bits = 3; 

bitfield[(int) (n >>> bits)] |= (1 << (n & ((1 << bits) -1))); 

その後

System.out.print((int) (i*radix+j)); 
使用してみてください

int[]またはlong[]を使用した場合よりも少し速いbyte[]

+0

ビットフィールド[(int)(n/radix)]をダウンキャストすると、最終的に負数で終わることはできませんか? – Cratylus

+0

'[0、2^32]の範囲があり、それを8で割った場合、' [0,2^29] 'の範囲または最大約51200万の範囲が得られます。 –

+0

+1:私は今参照してください。私は 'ビット= 3'で解決策を把握することはできません。私はこのaproachでも' n'はaproach 1として計算されると思いますか? 'byte []'より速いでしょうか? – Cratylus

3

明白な解決策があります:すべての数値に特定の範囲[a、b]があることを知っているので、保証された正の数を得るためにすべての数値に下限を追加することができます。

今では、任意の長さの数字では動作しませんが、その後、それは通常は問題ではありません

+0

'保証された正の数を得るためにすべての数値に下限を追加する.' [[a、b]の範囲では-2.147.483.648,2,147,483,648)あなたが指摘している下限は何ですか? – Cratylus

+1

@ user384706まあかなり明らかに-2^31(あなたも同じ記法を使った?)。 javaには符号なしの数値がないので、次に大きなサイズを使用する必要があります。整数範囲に-2^31を追加すると、期待通りに[0,2^32]になります。 – Voo

+0

あなたは[0,2^32]に翻訳していると言っています。私は今あなたが意味することを理解しています。しかし、「任意に長い数字のためには機能しませんが、それは通常問題ではありません。この点についてもっと説明してください。 – Cratylus

関連する問題