Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Functional programming 标准ML:计算给定集合的平均值_Functional Programming_Average_Sml - Fatal编程技术网

Functional programming 标准ML:计算给定集合的平均值

Functional programming 标准ML:计算给定集合的平均值,functional-programming,average,sml,Functional Programming,Average,Sml,我最近的任务是用标准ML计算一个集合(由输入给出)的平均值 其想法是使用如下函数,在该函数中,您输入实数列表并接收这些数字的平均值(也是实数),以便终端在您输入函数时将其作为返回答案: average = fn : real list -> real 我们在教程中也讨论了这一点,但我想知道在标准ML中创建此类函数时是否有一些技巧 提前谢谢 将数字相加,然后除以长度。简单的递归求和通常是您在任何SML教程中看到的第一个示例之一。您需要将空列表基本情况下的sum计算为0.0,而不是0,以确保

我最近的任务是用标准ML计算一个集合(由输入给出)的平均值

其想法是使用如下函数,在该函数中,您输入实数列表并接收这些数字的平均值(也是实数),以便终端在您输入函数时将其作为返回答案:

average = fn : real list -> real
我们在教程中也讨论了这一点,但我想知道在标准ML中创建此类函数时是否有一些技巧


提前谢谢

将数字相加,然后除以长度。简单的递归
求和
通常是您在任何SML教程中看到的第一个示例之一。您需要将空列表基本情况下的
sum
计算为
0.0
,而不是
0
,以确保返回类型为
real
。一旦定义了一个
sum
函数,就可以使用
sum
和内置的
length
函数在一行中定义
average
。一个微妙之处是SML不允许将实数除以整数。在将总和除以整数之前,可以对长度使用转换函数
real.fromInt
。将同一个列表传递两次,一次求和,一次计算长度,会有一些低效,但是当你第一次学习语言时,没有理由担心这些事情

关于编辑:由于您已经找到了一个自然的解决方案,并在评论中分享了它,下面是一个更为惯用的版本,它计算列表中一次通过的平均值:

fun average nums =
    let
        fun av (s,n,[]) = s/Real.fromInt(n)
        |   av (s,n,x::xs) = av (s+x,n+1,xs)
    in
        av (0.0, 0, nums)
    end;

它通过定义一个辅助函数来完成繁重的工作。这些在函数式编程中被广泛使用。在没有可变状态的情况下,一个常见的技巧是显式地将数量作为参数传递,这些数量将由命令式语言中的相应循环依次修改。此类参数通常称为
累加器
,因为它们通常累加增长列表、运行总和、运行乘积等。此处
s
n
为累加器,其中
s
为元素之和
n
为列表长度。在
(s,n,[])
的基本情况下,没有更多可累积的内容,因此返回最终答案。在非基准情况下,
(s,n,x::xs)
s
n
会被适当修改,并随列表的尾部一起传递给helper函数。因此,
av
的定义将以循环的速度运行,而不会增加堆栈。整体
average
函数需要做的唯一一件事就是使用适当的初始值调用helper函数。
让。。。助手定义。。。在里面用启动值调用helper…end
是一种常用的习惯用法,用于防止程序的顶层被helper函数弄得乱七八糟。

由于只有非空列表才能有平均值,John Coleman的另一个答案是:

fun average [] = NONE
  | average nums =
    let
        fun av (s,n,[]) = s/Real.fromInt(n)
          | av (s,n,x::xs) = av (s+x,n+1,xs)
    in
        SOME (av (0.0, 0, nums))
    end;

计算平均值的函数是否应该考虑非空列表取决于您是打算导出它,还是只在您在其他地方保证输入列表非空的范围内使用它。

a+用于向学生提供指导/解释,而不是仅仅给出一个没有教什么的答案。@john谢谢你的帮助!在本教程中,我们讨论了如何使用几个函数来实现这一点。我们不应该使用任何内置库(即Real.fromInt)。所以我尝试了多函数方法,得到了如下结果(有效):sum函数:
fun sum(h::t)=h+sum(t)| sum(nil)=0.0长度函数:
fun length(h::t)=1.0+长度(t)| length(nil)=0.0完整函数:
fun平均值(l)=总和(l)/长度(l)@opheliaxo Nice。我发现将基本情况放在递归情况之前稍微自然一些,但这主要是一个品味问题,也许是惯例问题。因为我不必再担心别人的家庭作业,在他们有兴趣自己解决之前,我编辑了我的答案,包括我认为最惯用、最有效的计算SML平均值的方法。