2012-03-09 5 views
1
あり三つの変数は、以下のタイプ

「uint_64t」と「INT」を追加

uint64_t old_addr, new_addr; 
int delta; 

であり、私はこの割り当て

問題があるしかし
new_addr = old_addr + delta; 

old_addr=915256delta=-6472064をしたい

new_addr18446744069414584325

いくつか確認する必要があることを修正する:

if (delta < 0) { 
if (old_addr < abs(delta)) 
    new_addr = 0; 
    else 
     new_addr = old_addr + delta; 
} 

より効率的な方法がありますか?

+0

私は2番目は 'new_addr' ...そうでなければ、あなたが編集した....右 – xanatos

+0

:-)元の問題に戻る前に、他にあり願うポスト – mahmood

+0

あなたはこれらの変数'呼ばれてきたことを考えます_addr'はメモリアドレスですか?もしそうなら、 'intptr_t'(署名されています)と' delta'の 'ptrdiff_t'を使うべきです。 –

答えて

2

質問はold_addrnew_addrのどちらの値が取れるのですか?そしてなぜ 彼らは単にintよりもuint64_tです。

new_addr = old_addr + std::min(delta, -static_cast<int>(old_addr)); 

が、old_addrINT_MAXよりも大きくすることができるならば、これは動作しません。最も単純な式 は次のようになります。 それ以外の場合は、C/C++での符号付き/符号なしの算術演算の規則が であり、おそらく明示的なifを使用して最も安全であり、値を確認する前に混合演算をにしないでください。

そして deltaINT_MINに等しい場合、ほとんどのマシンでは、abs(delta)は依然としてマイナスになることに注意してください。

if (delta > 0) { 
    new_addr = std::numeric_limits<uin64_t>::max() - delta > old_addr 
      ? old_addr + delta 
      : std::numeric_limits<uint64_t>::max(); 
} else if (delta < 0) { 
    new_addr = old_addr != 0 && -(delta + 1) < old_addr - 1 
      ? old_addr + delta 
      : 0; 
} else { 
    new_addr = old_addr; 
} 

(。。ちょうど私の頭の上から簡単にそこに1つのエラー によってオフがあるかもしれません)

4

これは飽和加算と呼ばれ、一部のプロセッサには特別な機械命令があります。そのコードをインライン関数に抽出し、ターゲット実行環境に応じてマシン命令を使用することができます。

を既に知っているので、abs(delta)の代わりに、-deltaと書くことができます。

+0

しかし、私はold_addrがデルタの絶対値よりも小さいことを確認する必要があります。さもなければ、彩度の加算は検出されません – mahmood

+0

'delta == MIN_INT'なら' abs(delta) 'も' -delta'も動作しません。少なくとも2つの補完機械で。 –

0

:正しく例すべてを処理するには、 you'ldのような何かを必要としますこのコードは非常に簡単で、両方向のオーバーフローを処理します。

#include <assert.h> 
#include <inttypes.h> 
#include <stdint.h> 

static uint64_t saturated_add(uint64_t a, int delta) { 
    uint64_t result = a + delta; 
    if (delta < 0 && result > a) { 
    return 0; 
    } else if (delta > 0 && result < a) { 
    return -1; 
    } else { 
    return result; 
    } 
} 

int main() { 
    assert(saturated_add(915256, -6472064) == 0); 
    assert(saturated_add(100, -99) == 1); 
    assert(saturated_add(100, -100) == 0); 
    assert(saturated_add(100, -101) == 0); 
    assert(saturated_add(UINT64_C(0x1111222233334444), -0x33334445) == UINT64_C(0x11112221FFFFFFFF)); 
    assert(saturated_add(-5, 6) == UINT64_C(-1)); 
    assert(saturated_add(-5, 5) == UINT64_C(-1)); 
    assert(saturated_add(-5, 4) == UINT64_C(-1)); 
    assert(saturated_add(-5, 3) == UINT64_C(-2)); 
    return 0; 
} 
関連する問題