【问题标题】:Scheme function: calculating distance of 2 "vectors" of any size方案函数:计算任意大小的 2 个“向量”的距离
【发布时间】:2014-04-08 04:00:55
【问题描述】:

我的向量定义为:

(x1, x2, …, xn) and (y1, y2, …yn)

我正在尝试像这样计算它们:

sqrt((x1-y1)*(x1-y1) + (x2-y2)*(x2-y2) + … + (xn-yn)*(xn-yn))

我在处理超过 2 个元素的向量时遇到了问题。我一直在尝试使用 for-each 循环,但无法使递归正常工作。

此外,除了最终数字的 sqrt 之外,我可以获得所有内容。我试图将最终数字定义为变量,然后取该变量的 sqrt,但我的解释器说了一些关于“在表达式中定义不允许......”。

到目前为止我的工作代码:

(define vectordistance 
  (lambda (v1 v2)
  (if 
   (null? v1) 0
      (+ 
      (*
      (- (car v1) (car v2))
      (- (car v1) (car v2))
      ) 
      (vectordistance (cdr v1) (cdr v2))
      )
  )
))

【问题讨论】:

    标签: scheme


    【解决方案1】:

    首先,您使用的是 lists - vector 是 Scheme 中的另一种野兽。解决方案的关键是您必须对列表进行迭代,并以某种方式累积答案,直到没有更多元素为止。此外,辅助函数在这里也很有用,因为首先我们必须累积加法并仅在最后取平方根。假设两个列表的长度相同:

    ; this is the same as yours, but better formatted
    (define (helper v1 v2)
      (if (null? v1)
          0
          (+ (* (- (car v1) (car v2))
                (- (car v1) (car v2)))
             (helper (cdr v1) (cdr v2)))))
    
    ; call the above as a helper and take the square root of the result    
    (define (vectordistance v1 v2)
      (sqrt (helper v1 v2)))
    

    作为奖励(由 Chris 建议),您可以使用fold 过程以更惯用的方式编写helper。检查您的解释器的文档,它可能称为foldlfold-left 或简称为fold,但这是您使用它的方式 - 其想法是避免使用显式递归并支持使用高阶过程:

    (define (square x)
      (* x x))
    
    (define (helper v1 v2)
      (foldl (lambda (e1 e2 r)
               (+ (square (- e1 e2)) r))
             0
             v1 v2))
    

    【讨论】:

    • 感谢奥斯卡。你一直在救我的命。欣赏它。我不知道 Scheme 有向量。我认为列表是 Scheme 拥有的唯一容器。我认为我的原始代码适用于超过 2 个元素(减去 sqrt),我只是假设它不会导致这种递归,这让我的大脑扭曲了哈哈。
    • 我很想把它改成fold,你不知道。 (fold (lambda (e1 e2 r) (+ (square (- e1 e2)) r)) v1 v2) 或类似的东西(未经测试)。 ;-) 但我知道您试图尽可能地保留 OP 的代码....
    • @ChrisJester-Young 你明白了;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-23
    • 1970-01-01
    相关资源
    最近更新 更多