オーバーフロー安全合計


13

合計が幅レジスタにも収まるように、固定幅整数(幅レジスタに収まる)、が与えられたとします。w a 1a 2a n a 1 + a 2 + + a n = S wnwa1,a2,ana1+a2++an=Sw

各プレフィックスの和も幅レジスタに収まるように番号をいつでも置換できるように思えます。S i = b 1 + b 2 + + b i wb1b2bnS=b1+b2++bw

基本的に、動機は、中間段階で整数オーバーフローを心配することなく、固定幅レジスタマシンで合計を計算することです。S=Sn

そのような置換を見つけるための高速(好ましくは線形時間)アルゴリズムがあります(が入力配列として与えられていると仮定して)?(または、そのような順列が存在しない場合に言います)。a


3
フォローアップ:合計のオーバーフローの検出 —典型的なプロセッサ機能を考慮したより高速な方法はありますか?
ジル「SO-悪であるのをやめる」

1
2の補数レジスタを使用して、それらを合計するだけです。途中でオーバーフローした場合でも、前提条件により、オーバーフローがキャンセルされ、結果が正しいことが保証されます。:P
CodesInChaos

@CodeInChaos:それは本当ですか?
アリヤバータ

1
私はそう思う。あなたは、本質的にあなたから標準的な表現を選択し、グループ法2 ^ nは、で作業している-2^(n-1)2^(n-1)-1。もちろん、2の補数と明確に定義されたオーバーフロー動作が必要ですが、C#のような言語では動作するはずです。
-CodesInChaos

@CodeInChaos:法として同じ剰余を与える2つの可能性はありませんか?あなたは基本的に、順序に関係なく、そのうちの1つは決して起こり得ないと言っています。それとも何か不足していますか?2n
アルヤバタ

回答:


10

戦略
次の線形時間アルゴリズムは、部分和の符号に基づいて正または負の数を選択することにより、中心にホバリングする戦略を採用しています。数字のリストを前処理します。加算を実行しながら、入力の順列をオンザフライで計算します。0

アルゴリズム

  1. を、正の要素と負の要素 2つのリストに分割します。ゼロは除外できます。 P Ma1anPM
  2. してみましょう。Sあなたはm=0
  3. 両方のリストは空ではありませんが
  4.       もし {。 ; }S u m = S u m + M M = M Sあなたはm>0Sあなたはm:=Sあなたはm+MM:=M
  5.        else { ; ; }P = tail P Sあなたはm:=Sあなたはm+PP:=P
  6. 2つのリストのいずれかが空になったら、残りのリストの残りをに追加します。S

正しさ
正しさは、数字のリストの長さに関する簡単な帰納的引数を使用して確立できます。

まず、がすべて正(またはすべて負)であり、それらの合計がオーバーフローを引き起こさないか、接頭辞の合計も行わないことを証明します。これは簡単です。a1an

次に、が範囲内であることをアルゴリズムのループの不変式であることを証明します。明らかに、ように、これはループに入るときに当てはまります。さて、あれば、の範囲内にある負の数の追加しない原因範囲外行くことを。同様に、合計に境界内にある正の数を追加することが発生しない境界の外出します。したがって、ループを終了すると、は範囲内になります。SあなたはmSあなたはm=0Sあなたはm>0SあなたはmSあなたはmSあなたはm0SあなたはmSあなたはm

これで、最初の結果を適用できます。これらを合わせることで、合計が範囲外にならないことを証明できます。


効率的なインプレース実装に向けて、a)暗黙的なピボットでクイックソートパーティション(2ポインターバリアント)を実行し、次にb)合計して、負の応答を持つ領域をそれぞれ移動します。正の数。0
ラファエル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.