1

1)

Sum := 0;
for J in 1 .. N loop
Sum := Sum + J;
end loop;

2)

Sum := ((N + 1) * N) / 2;

ここに画像の説明を入力してください

最初の(左)ソリューションは、2番目(右)のソリューションよりも「一般的」であり、幅広い値に適用できることを読みました。「一般」とはどういう意味ですか?オーバーフローなしで計算できますか?

4

2 に答える 2

4

「より一般的」とは、「より広い範囲の数値に対してオーバーフローなしで計算できる」ことを意味する必要があると思います。

(2)の中間積は、2 ^ 31-1でオーバーフローします(Integerほとんどの最新のマシンで得られる32ビットの場合)。つまり、最大の法的な結果は2 ^ 30-1よりもいくらか少なくなります。( 1)ほぼ同じ距離まで続けることができます(長く待つことができれば!)

このプログラムは限界を探ります:

with Ada.Exceptions;
with Ada.Text_IO; use Ada.Text_IO;
procedure Summation is
   N : Integer := 1;
   Sum : Integer;
begin
   loop
      Put (Integer'Image (N) & " => ");
      Sum := ((N + 1) * N) / 2;
      Put_Line (Integer'Image (Sum));
      N := N + 1;
   end loop;
exception
   when E : others =>
      Put_Line (Ada.Exceptions.Exception_Message (E));
end Summation;

でコンパイルしgnatmake -gnato summation.adbて実行すると、で終わります

46337 =>  1073581953
46338 =>  1073628291
46339 =>  1073674630
46340 =>  1073720970
46341 => summation.adb:9 overflow check failed

-gnato省略して、GNATが数値オーバーフローチェックを実行しないようにすると(残念ながらデフォルトで、効率のために覚えているように選択されます)、これは次のようになります。

46337 =>  1073581953
46338 =>  1073628291
46339 =>  1073674630
46340 =>  1073720970
46341 => -1073716337
46342 => -1073669995
46343 => -1073623652

N掛け算をする前に、偶数とN + 1偶数(1つは明らかにそうです!)のどちらかを2で割ることで、より長い範囲を得ることができると思います。

これは実際にはAdaの問題ではありません(ただし-gnato、他の言語で発生する可能性がある場合よりも、問題が発生した場合に簡単に確認できます)。また、階乗ではありません。タイトルを編集することはできますか?

于 2012-01-11T00:00:48.787 に答える
2

構文はさておき(これは概念的には構文的にではありません)、

ここでは本当に総和について話しているので、それに応えます。

左がより一般的である理由の私の最初の推測は、おそらくほとんどの人が1からnまでのiの合計へのショートカットがあることを忘れているためです。両方の方程式は数学的に同等であるため。あなたのシステムでどちらが速いですか?

1からnまでの個々の数を追加するという面倒な作業を行います。

ウィキペディアの合計の記事を見ると、1から100までの合計には99の追加が必要であることがわかります。 http://en.wikipedia.org/wiki/Summation

一方、右の式(ショートカット)は、除算と乗算、および単一の加算のみを実行します。

私の2番目の推測は、おそらく特定の(おそらくそれ以上の)状況では、n個の追加を行う方が速いでしょう....これはシステムに依存する状況であり、問​​題に依存するため、その可能性は低いと思います。

このドキュメントに関するリファレンスを教えていただけますか。コンテキストは非常に役立ちます。

于 2012-01-10T23:26:09.353 に答える