Ada 中 Sum 的实现

发布于 2024-12-26 04:22:32 字数 296 浏览 2 评论 0原文

1)

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

2)

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

在此处输入图像描述

我读到第一个(左)解决方案更“通用” - 适用比第二个(右)解决方案更广泛的值。 “一般”是什么意思——可以计算而不会溢出?

1)

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

2)

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

enter image description here

I've read that the first(left) solution is more "general" - applicable to a wide range of values ​​- than second(right) solution. What does "general" mean - can be computed without overflow?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

自控 2025-01-02 04:22:32

我认为“更通用”必须意味着“可以在更大范围的数字的情况下进行计算而不会溢出”。

(2) 中的中间乘积将在 2^31 - 1 处溢出(对于大多数现代机器上将得到的 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 进行编译> 和运行它,它以“如果你省略了 -gnato”结尾

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

,这样 GNAT 就不会进行数字溢出检查(一个令人遗憾的默认值,我记得是为了提高效率而选择的),这种情况会发生:

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

我想你可以得到在进行乘法之前,通过将 NN + 1 中的偶数(显然必须是偶数)除以 2 来获得更长的范围。

这并不是真正的 Ada 问题(尽管 -gnato 比其他语言更容易发现问题),而且它当然不是阶乘!可以修改标题吗?

I think “more general” must mean “can be computed without overflow for a larger range of numbers”.

The intermediate product in (2) will overflow at 2^31 - 1 (for a 32-bit Integer as you will get on most modern machines), which means that the largest legal result will be somewhat less than 2^30 - 1. (1) will let you continue almost as far again (if you can wait that long!)

This program explores the limits:

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;

and if you compile with gnatmake -gnato summation.adb and run it it ends with

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

If you leave out the -gnato, so that GNAT doesn’t do numeric overflow checks (a regrettable default, chosen as I remember for efficiency) this happens:

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

I suppose you could get the longer range by dividing whichever of N and N + 1 was even (one clearly must be!) by 2 before doing the multiplication.

This isn’t really an Ada problem (though -gnato makes it easier to see when things go wrong than might happen with some other languages), and it’s certainly not a factorial! Is it possible to edit the title?

梦太阳 2025-01-02 04:22:32

撇开语法不谈(我们是从概念上而不是语法上看待这个问题),

因为我们在这里真正讨论的是求和,所以我会对此做出回应。

我的第一个猜测为什么左边更通用,可能是因为大多数人忘记了 i 从 1 到 n 求和的捷径。因为两个方程在数学上是等价的。您的系统上哪一个速度更快?

人们需要完成将 1 到 n 中的每个数字相加的繁琐任务。

如果你看一下维基百科上的求和文章,你会发现从1到100的求和需要99次加法。
http://en.wikipedia.org/wiki/Summation

而右边的等式(快捷方式)只会执行除法、乘法和一次加法。

我的第二个猜测是,在某些(也许更多)情况下,进行添加会更快......这是一个依赖于系统的情况,以及依赖于问题的情况,所以我认为这种可能性较小。

您能否提供有关此文档的参考信息,上下文会非常有帮助。

Syntax aside (we're looking at this conceptually not syntatically),

Since we are really talking about summations here, I'll respond to that.

My first guess why the left is more general is possibly because most people forget that there is a shortcut to a summation of i from 1 to n. Since both equations are mathematically equivalent. Which one is the faster on your system?

One does the tedious task of adding each individual number from 1 to n.

If you take a look at the summation article on wikipedia, you will see that the summation from 1-100 requires 99 additions.
http://en.wikipedia.org/wiki/Summation

Whereas the equation on the right (the shortcut) will only do a division and a multiplication and a single addition.

My second guess is perhaps in certain (maybe more) situations it would be faster to do n additions....that's a system dependent situation, as well as problem dependent, so I think that's less likely.

Could you give a reference as to this document, context would be really helpful.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文