1

这是一个相对简单的代码,用于“在半径为 2 个单位的圆的象限上使用中坐标规则评估 pi”。

main.alg

BEGIN
REAL x, y, sumy, pi;
INT n := lowerlimit, p := 1, lowerlimit := 10, upperlimit := 100, interval := 10;

FOR n BY interval TO upperlimit DO
    sumy := 0.0;

    FOR p BY 2 TO n+n-1 DO 
        x := p/n;
        y := sqrt(4.0 - x**2);
        sumy := sumy + y;
    OD
    pi := sumy * (2.0 / n);
    print((n,pi))
OD
END

我收到以下错误:

a68g: syntax error: 1: possibly a missing or erroneous separator nearby.                                                                             
sh-4.3$ a68g main.alg                                                                                                                                
13                sumy := sumy + y;                                                                                                                  
                              1                                                                                                                  
a68g: warning: 1: skipped superfluous semi-symbol.                                                                                                   
15            pi := sumy * (2.0 / n);                                                                                                                
          1                                                                                                                                      
a68g: syntax error: 1: possibly a missing or erroneous separator nearby.  

住在这里试试。

我究竟做错了什么?如何纠正它?


4

1 回答 1

4

简短的回答: 以下代码解决了您的具体问题......

要记住的是一个“;” 是“语句分隔符”......所以所有“复合语句”都应该用“;”分隔每个语句......例如考虑:

statement; statement; statement # is a valid program #
statement; statement statement; # is not valid #

(statement; statement; statement) # is a valid program #
(statement; statement; statement;) # is not valid #
(statement; statement; statement); # is not valid #

道德是......用“;”分隔所有陈述 并且不要放一个“;” 在最后一条语句之后。(例如在 END、FI、DO、")" 或 ESAC 之前)

BEGIN
REAL x, y, sumy, pi;
INT n := lowerlimit, p := 1, lowerlimit := 10, upperlimit := 100, interval := 10;

FOR n BY interval TO upperlimit DO
    sumy := 0.0;

    FOR p BY 2 TO n+n-1 DO 
        x := p/n;
        y := sqrt(4.0 - x**2);
        sumy := sumy + y
    OD;
    pi := sumy * (2.0 / n);
    print((n,pi))
OD
END

有趣的是,您通常可以使用“,”而不是“;”,这告诉编译器您不在乎语句的运行顺序。它被称为GOMMA。(继续逗号的缩写)

例如,应该谨慎使用 GOMMA,因为编译器不需要警告您副作用......例如(理论上)

#!/usr/bin/a68g --script #
# -*- coding: utf-8 -*- #

INT x:=0;
(x+:=1, x+:=2); # allow the compiler the choice of threading #
PAR(x+:=10, x+:=20); # force statements into different threads #
printf(($"Answer="gl$,x))

答案是什么?...它可能是 33,但也可能是 21 或 12 等,具体取决于您的编译器。

在这种情况下,+:= 操作是如此的小而快,以至于答案可能是 33。

长答案: 语言中语句分隔符的位置多年来一直引起悲伤。例如,考虑以下缺少逗号的 FORTRAN 代码:

DO 999 I=1 1000
  PRINT *,I
999 CONTINUE

这个错误是在Project Mercury启动之前发现并纠正的。都市神话传说,水手计划有一个类似的错误导致它崩溃。

请注意,拥有“假”语句通常很有用,这用于满足语法/语义要求。Python 作为各种示例,例如:“None”、“NoneType”和“pass”。Algol68 有“VOID”、“SKIP”和“~”

演示 SKIP(或“~”)的用法。

BEGIN
REAL x, y, sumy, pi;
INT n := lowerlimit, p := 1, lowerlimit := 10, upperlimit := 100, interval := 10;

FOR n BY interval TO upperlimit DO
    sumy := 0.0;

    FOR p BY 2 TO n+n-1 DO 
        x := p/n;
        y := sqrt(4.0 - x**2);
        sumy := sumy + y; SKIP # insert a "fake statement after the ";" #
    OD; # the ";" is still needed #
    pi := sumy * (2.0 / n);
    print((n,pi))
OD
END

SKIP 通常用于允许代码被干净地注释掉:

statement1;
statement2;
SKIP COMMENT
statement3;
statement4 # eg. no ";" on the last statement #
END COMMENT

如果没有SKIP,程序将无法编译。

在 Algol68 的案例中,有一个奇怪的案例Yoneda的模棱两可。从那以后,这种模糊性一直困扰着许多编程语言,包括 Ada 和 python,甚至可能是 C...

要了解更多信息,请访问您的大学图书馆并阅读:“ALGOL 68 的历史” - CH Lindsey - [包括对语言设计过程的坦率反映“通过邮件进行修订”,语言功能在“弯道”中挣扎并包括/排除歧义(例如米田的歧义和乱伦的结合)]

在python中,他们试图通过使其成为可选并用缩进隐藏它来避开“分隔符”......但逗号歧义仍然存在......例如。发现以下语法/语义错误和运行时错误...

print [i for i in ()]
print [i for i in (1)]
print [i for i in (1,2)]
print [i for i in (1,2,3)]
ab="ab etc etc etc"
print "first 2 only: %c,%c"%ab[0:2]

C 也受到“我在哪里放分号和逗​​号”的影响......逻辑是“;” 永远不需要跟随“}”,例如总是“;}”但永远不要跟随“};”......事实证明,有时确实需要“;};”

然后C完全在逗号的作品中抛出了一个扳手,从不“,)”但有时是“),”。

1968 年的 Algol68 确实为此类歧义产生了错误消息。这个故事的寓意可能是:如果您的编译器在编译时没有发现这种歧义,那么(也许)您应该选择另一种语言。

顺便说一句:你可以在这里找到一些示例 Algol68 程序......接下来是你的代码,去掉了锋利的边缘。

INT lower limit = 10, upper limit = 100, interval = 10;

PROC circle = (REAL x)REAL: sqrt(4 - x**2);

FOR n FROM lower limit BY interval TO upper limit DO
    REAL sum y := 0;

    FOR p FROM 1 BY 2 TO 2*n DO
        REAL x = p/n;
        REAL y = circle(x);
        sum y +:= y
    OD;
    REAL pi := sum y * 2 / n;
    printf(($g(0)": "g(-real width,real width-2)l$,n,pi))
OD

比较代码更改,看看您是否可以弄清楚效果以及它们提供的提示...... :-)

或者......这是一个标准的数值正交程序如何编码以进行共享。请注意使用传递函数作为参数,特别是这里有一个称为 Currying 的概念circle(2,)......其中逗号很重要!

INT lower limit = 10, upper limit = 100, interval = 10;

PROC circle = (REAL radius, x)REAL: sqrt(radius**2 - x**2);

PROC mid point integrate = (PROC(REAL)REAL f, REAL lwb, upb, INT num steps)REAL: (
  REAL dx := (upb - lwb ) / num steps;
  REAL x := lwb + dx/2;
  REAL sum y := 0;

  FOR p TO num steps DO
      REAL y = f(x);
      sum y +:= y;
      x +:= dx
  OD;
  sum y * dx
);

FOR num steps FROM lower limit BY interval TO upper limit DO
  REAL pi := mid point integrate(circle(2,),0,2,num steps);
  printf(($g(0)": "g(-real width,real width-2)l$,num steps,pi))
OD
于 2017-03-31T02:16:04.960 回答