Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.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
摆脱Scala中的for循环_Scala_Functional Programming - Fatal编程技术网

摆脱Scala中的for循环

摆脱Scala中的for循环,scala,functional-programming,Scala,Functional Programming,这里有一个问题涉及到一个阶乘。对于给定的数字,n,请找到以下问题的答案: (1 / n!) * (1! + 2! + 3! + ... + n!) Scala中的迭代解非常简单——一个简单的for循环就足够了 object MyClass { def fsolve(n: Int): Double = { var a: Double = 1 var cum: Double = 1 for (i <- n to 2 by -1) { a = a *

这里有一个问题涉及到一个阶乘。对于给定的数字,
n
,请找到以下问题的答案:

(1 / n!) * (1! + 2! + 3! + ... + n!)
Scala中的迭代解非常简单——一个简单的for循环就足够了

object MyClass {

def fsolve(n: Int): Double = {
    var a: Double = 1
    var cum: Double = 1
    for (i <- n to 2 by -1) { 
        a = a * (1.0/i.toDouble)
        cum += a
    }
    scala.math.floor(cum*1000000) / 1000000
}

def main(args: Array[String]) {
    println(fsolve(7))     // answer 1.173214
}

有任何解决方案的建议或指针吗?

结果从
foldLeft
返回,如下所示:

val cum = (n to 2 by -1).foldLeft(1.toDouble) (_*_)
只有在您的情况下,函数才需要不同,因为上面的折叠会将所有
i
值相乘。您将传递折叠的
cum
a
值:

def fsolve(n: Int): Double = {
  val (cum, _) = (n to 2 by -1).foldLeft(1.0, 1.0) { case ((sum, a),i) =>
    val newA = a * (1.0/i.toDouble)
    (sum + newA, newA)
  }
  scala.math.floor(cum*1000000) / 1000000
}

结果从
foldLeft
返回,如下所示:

val cum = (n to 2 by -1).foldLeft(1.toDouble) (_*_)
只有在您的情况下,函数才需要不同,因为上面的折叠会将所有
i
值相乘。您将传递折叠的
cum
a
值:

def fsolve(n: Int): Double = {
  val (cum, _) = (n to 2 by -1).foldLeft(1.0, 1.0) { case ((sum, a),i) =>
    val newA = a * (1.0/i.toDouble)
    (sum + newA, newA)
  }
  scala.math.floor(cum*1000000) / 1000000
}

我将尝试实现一个解决方案,但不填补空白,而是提出一种不同的方法

def fsolve(n: Int): Double = {
  require(n > 0, "n must be positive")
  def f(n: Int): Long = (1 to n).fold(1)(_ * _)
  (1.0 / f(n)) * ((1 to n).map(f).sum)
}
在函数中,我使用
require
确保无效输入失败,我定义阶乘(如
f
),然后使用它,只需以最接近我们想要实现的原始表达式的方式写下函数:

(1.0 / f(n)) * ((1 to n).map(f).sum)
如果确实要显式折叠,可以按如下方式重写此表达式:

(1.0 / f(n)) * ((1 to n).map(f).fold(0L)(_ + _))
另外,请注意,由于您正在执行的所有操作(求和和和乘法)都是可交换的,因此可以使用
fold
而不是
foldLeft
:使用前者不会规定操作的运行顺序,从而允许集合的特定实现并行运行计算


您可以随意使用这段代码。

我将尝试实现一个解决方案,但不填补空白,而是提出一种不同的方法

def fsolve(n: Int): Double = {
  require(n > 0, "n must be positive")
  def f(n: Int): Long = (1 to n).fold(1)(_ * _)
  (1.0 / f(n)) * ((1 to n).map(f).sum)
}
在函数中,我使用
require
确保无效输入失败,我定义阶乘(如
f
),然后使用它,只需以最接近我们想要实现的原始表达式的方式写下函数:

(1.0 / f(n)) * ((1 to n).map(f).sum)
如果确实要显式折叠,可以按如下方式重写此表达式:

(1.0 / f(n)) * ((1 to n).map(f).fold(0L)(_ + _))
另外,请注意,由于您正在执行的所有操作(求和和和乘法)都是可交换的,因此可以使用
fold
而不是
foldLeft
:使用前者不会规定操作的运行顺序,从而允许集合的特定实现并行运行计算


您可以使用此代码。

您提供的公式很好地映射到
scanleet
函数。它的工作原理有点像
foldLeft
map
的组合,运行折叠操作,但将生成的每个值存储在输出列表中。下面的代码生成从
1
n
的所有阶乘,将它们相加,然后除以
n。请注意,通过在末尾执行单个浮点除法,而不是在每个中间步骤,可以降低浮点错误的几率

def fsolve(n: Int): Double =
{
  val factorials = (2 to n).scanLeft(1)((cum: Int, value: Int) => value*cum)
  scala.math.floor(factorials.reduce(_+_)/factorials.last.toDouble*1000000)/1000000
}

您提供的公式很好地映射到
scanLeft
函数。它的工作原理有点像
foldLeft
map
的组合,运行折叠操作,但将生成的每个值存储在输出列表中。下面的代码生成从
1
n
的所有阶乘,将它们相加,然后除以
n。请注意,通过在末尾执行单个浮点除法,而不是在每个中间步骤,可以降低浮点错误的几率

def fsolve(n: Int): Double =
{
  val factorials = (2 to n).scanLeft(1)((cum: Int, value: Int) => value*cum)
  scala.math.floor(factorials.reduce(_+_)/factorials.last.toDouble*1000000)/1000000
}

请注意:由于阶乘的计算方式,此解决方案的复杂性为O(N^2)。原始代码是O(N)。这可能是一个问题,也可能不是,这取决于使用情况。请注意:由于阶乘的计算方式,此解决方案的复杂性为O(N^2)。原始代码是O(N)。这可能是问题,也可能不是问题,具体取决于使用情况。此解决方案适用于大数字和小数字,例如200。谢谢。此解决方案适用于大数字和小数字,例如200。非常感谢。