Penjumlahan penjumlahan aman

13

Misalkan saya mengingat tetap lebar bilangan bulat (yaitu mereka cocok dalam register lebar w ), seorang 1 , sebuah 2 , ... sebuah n sehingga jumlah mereka yang 1 + a 2 + + a n = S juga cocok dalam register dengan lebar w .nwa1,a2,ana1+a2++an=Sw

Sepertinya saya bahwa kita selalu dapat mengubah angka ke sehingga setiap jumlah awalan S i = b 1 + b 2 + + b saya juga cocok dalam register lebar w .b1,b2,bnSi=b1+b2++biw

Pada dasarnya, motivasinya adalah untuk menghitung jumlah pada mesin register lebar tetap tanpa harus khawatir tentang bilangan bulat bilangan bulat pada setiap tahap menengah.S=Sn

Apakah ada algoritma yang cepat (lebih disukai waktu linier) untuk menemukan permutasi seperti itu (dengan asumsi diberikan sebagai array input)? (atau katakan jika permutasi seperti itu tidak ada).ai

Aryabhata
sumber
3
Tindak lanjut: Mendeteksi overflow dalam penjumlahan - adakah metode yang lebih cepat yang mempertimbangkan fitur-fitur prosesor yang khas?
Gilles 'SO- stop being evil'
1
Cukup gunakan register pelengkap dua dan jumlah mereka. Bahkan jika meluap di tengah, pra-kondisi Anda menjamin bahwa luapan akan dibatalkan, dan hasilnya akan benar. : P
CodesInChaos
@ CodeInChaos: Apakah itu benar?
Aryabhata
1
Aku pikir begitu. Anda pada dasarnya bekerja dalam modulo grup 2 ^ n, tempat Anda memilih representasi kanonik dari -2^(n-1)hingga 2^(n-1)-1. Tentu saja membutuhkan komplemen dua dan perilaku overflow yang terdefinisi dengan baik, tetapi dalam bahasa seperti C # itu harus bekerja.
CodesInChaos
@CodeInChaos: Apakah tidak ada dua kemungkinan yang memberikan modulo ? Anda pada dasarnya mengatakan, terlepas dari urutannya, salah satunya tidak akan pernah terjadi. Atau apakah saya melewatkan sesuatu? 2n
Aryabhata

Jawaban:

10

Strategi
Algoritma linear-waktu berikut mengadopsi strategi melayang di sekitar , dengan memilih angka positif atau negatif berdasarkan tanda jumlah parsial. Ini memproses daftar angka; itu menghitung permutasi dari input on-the-fly , sambil melakukan penambahan.0

Algoritma

  1. Partisi menjadi dua daftar, unsur-unsur positif P dan unsur-unsur negatif M . Nol dapat disaring.a1,,anPM
  2. Biarkan .Sum=0
  3. Sementara kedua daftar tidak kosong
  4.       Jika { S u m : = S u m + head ( M ) ; M : = ekor ( M ) ; }Sum>0Sum:=Sum+head(M)M:=tail(M)
  5.       lain { ; P : = tail ( P ) ; }Sum:=Sum+head(P)P:=tail(P)
  6. Ketika salah satu dari dua daftar menjadi kosong, tambahkan sisa daftar tersisa untuk .S

Correctness
Correctness dapat dibangun dengan menggunakan argumen induktif langsung pada panjang daftar angka.

Pertama, buktikan bahwa jika semuanya positif (atau semuanya negatif), dan jumlahnya tidak menyebabkan overflow, maka jumlah awalan juga tidak. Ini mudah.a1,,an

Kedua, buktikan bahwa berada dalam batas adalah invarian dari loop algoritma. Jelas, ini benar saat masuk ke loop, karena S u m = 0 . Sekarang, jika S u m > 0 , menambahkan angka negatif yang berada dalam batas ke S u m tidak menyebabkan S u m keluar dari batas. Demikian pula, ketika S u m 0 menambahkan angka positif yang ada di dalam batas-batas untuk jumlah tidak menyebabkan S u m untuk pergi keluar batas. Jadi saat keluar dari loop,SumSum=0Sum>0SumSumSum0SumSum

Sekarang, hasil pertama dapat diterapkan, dan bersama-sama ini cukup untuk membuktikan bahwa jumlah tidak pernah keluar batas.

Dave Clarke
sumber
Menuju implementasi in-place yang efisien, lakukan a) Quicksort-partisi (varian dua-pointer) dengan pivot implisit 0dan kemudian b) jumlahkan, pindahkan masing-masing pointer melalui area dengan resp negatif. angka positif.
Raphael