计算 pi 和方案语法的级数近似值

Calculating a series approximation for pi & scheme syntax

我第一次使用 运行 方案并且正在尝试编写一个简单的递归函数,它将使用 Leibniz formula 计算圆周率。该过程采用所需的精度和 returns 适当的 pi 近似值。

例如:make-pi 0.001 -> 3.14109...

不过我对语法很感兴趣,并且迷失了call/return 方案中变量的语法和正确方法。

; Define count for number of loops, sum for pi estimate, and num/denom for calculating estimation in series
(define count 1.0)
(define sum 4.0)
(define denomenator 3.0)
(define numerator 4.0)

; make-pi gets accuracy needed as input ie (make-pi 0.001 => 3.1410926536210413
(define make-pi
  (lambda (accuracy)
    ; determine if next fraction will be + or - based on number of iterations thus far
    (if (zero? sign count)
        ; add fraction if odd, subtract otherwise
        (+ sum (/ numerator denomenator))
        (- sum (/ numerator denomenator)))
    (define (check-accuracy sum)
      ; use check accuracy with current sum
      (if (zero? check-accuracy)
          ;return sum if within needed accuracy
          sum
          ; update count and new denom values if not accurate enough
          ; loop back if sum is not accurate enough
          (begin
            (+ count 1)
            (+ denomenator 2)
            (make-pi (sum)))))))



; if interation is even return 1 else 0
(define sign
  (lambda (count)
    (if (even? count))
  1
  0))

; if pi - sum is within desired accuracy, return 1 else 0
(define check-sum
  lambda (sum)
  (define check-accuracy
    lambda (accuracy)

  (if ((- 3.14159265358979 sum) < (abs(accuracy))))
  1
  0))

如何调用变量。鉴于符号 add 通过将它们括在括号中来评估您调用的过程:

(add 1 2) ; returns 3 if `add` is like global variable `+`

基本上它是 Algol 语言中 add(1, 2) 的语义等价物。 注意不要使用额外的括号,因为 ((add 1 2)) 与 add(1, 2)() 等相同。

如何 return 一个变量。好吧,你让它成为尾巴表达式。

(define (positive? n)
  (if (> 0 n)
      #t         ; tail that returns true 
      #f))       ; tail that returns false

实际上发生的情况是 if 根据测试执行结果或备选方案。因此,整个 if 形式的结果变为 true 或 false,并且 if 也 returns 该值。最终,恰好是 if 表达式的过程的最后一个表达式作为 positive?.

的结果得到 returned

你用 define

创建了一个全局变量
(define my-value 10) ; my-value is 10

当然一个过程就是一个值:

(define add1 (lambda (n) (+ n 1))) ; value of add1 is a procedure

但是 (define sign (count)) 将创建变量 sign 作为调用不带参数的过程 count 的结果。 var sign = count();(define check-accuracy lambda)var checkAccuracy = lambda; 相同,可能未绑定。

(((- 3.14159265358979 sum) < (abs(accuracy))))) 等同于: sub( 3.14159265358979, sum)(some-variable-<, abs(accuracy()))()

在 Scheme 中,您可能需要 (< (- 3.14159265358979 sum) (abs accuracy))

A define (helper) 在过程中需要在过程主体之前的开头。例如。

(define (fibonacci n)
  ; define a local helper procedure
  (define (helper n a b)
    (if (zero? n)
        a
        (helper (- n 1) b (+ a b))))

  ; use the helper
  (helper n 0 1))

并且由于 (define (proc arg ...) body ...)(define proc (lambda (arg ...) body ...)) 相同,您可以编写相同的内容:

(define fibonacci (lambda (n)
  ; define a local helper procedure
  (define helper (lambda (n a b)
    (if (zero? n)
        a
        (helper (- n 1) b (+ a b)))))

  ; use the helper
  (helper n 0 1)))

不使用自由变量的助手可以是全局的。他们更容易以这种方式自行测试。您可以稍后(或不)将它们作为助手移入

(sign 1) ; ==> is it 0?

记得花时间学习语言。这可能是您第二次学习一门新语言,这与学习您已经知道的语言的新方言不同。

也可以使用'named let'进行递归(描述见内联注释):

(define (myfn acc)
  (let loop ((sum 0)                           ; starting values
             (denom 1)
             (sign 1))
    (if (< (abs (- 3.14159265358979 sum))      ; check accuracy
           (abs acc))
        (exact->inexact sum)                   ; if accurate, end with output
        (loop (+ sum (* 4 sign (/ 1 denom)))   ; else loop again with next values
              (+ 2 denom)                     
              (if (= sign 1)-1 1)))))