计算大型斐波那契数的Scala矩阵库

计算大型斐波那契数的Scala矩阵库,scala,matrix,Scala,Matrix,扩展这个类的最好方法是使用幂方法,将矩阵提升到n次方 我想做的是用矩阵计算大的斐波那契数 这些是我到目前为止对原始代码所做的更改。我收到StackOverflow异常 文件Row.scala /* * Copyright (c) 2010 Eamonn O'Brien-Strain, eob@well.com * All rights reserved. This program and the accompanying materials * are made available unde

扩展这个类的最好方法是使用幂方法,将矩阵提升到n次方

我想做的是用矩阵计算大的斐波那契数

这些是我到目前为止对原始代码所做的更改。我收到StackOverflow异常

文件Row.scala

/*
* Copyright (c) 2010 Eamonn O'Brien-Strain, eob@well.com
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which is available at http://www.eclipse.org/legal/epl-v10.html
*/

package org.eamonn.published_matrix

import Row._

/** Methods that are added to List[BigInt] by an implicit conversion */
case class RichRow(v:Row){

  /** dot product */
  def *(that:RichRow) = dotProd( this.v, that.v )

  /** vector addition */
  def add(that:RichRow) = vPlusV( this.v, that.v )

  /** convert to column vector */
  def T = v.map{ List(_) }

  /** As row matrix */
  def asMatrix = List( v )
}

object Row{

  /** A convenient alias */
  type Row = List[BigInt]

  def dotProd(v1:Row,v2:Row) = 
              v1.zip( v2 ).map{ t:(BigInt,BigInt) => t._1 * t._2 }.reduceLeft(_ + _)

  def vPlusV(v1:Row,v2:Row) = 
             v1.zip( v2 ).map{ t:(BigInt,BigInt) => t._1 + t._2 }

  /** effectively add RichRow methods to List[Double] */
  implicit def pimp(v:Row) = new RichRow(v)
}
文件Matrix.scala

/*
* Copyright (c) 2010 Eamonn O'Brien-Strain, eob@well.com
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which is available at http://www.eclipse.org/legal/epl-v10.html
*/

package org.eamonn.published_matrix

import Matrix._
import Row._
import Seq.Projection

/** Methods that are added to List[List[BigInt]] by an implicit conversion */
case class RichMatrix(m:Matrix){

  def T = transpose(m)

  def *(that:RichMatrix) = mXm( this.m, that.m )

  def power (exp:Int) = recPower(this.m, exp)

  def recPower(m:Matrix, exp:BigInt) : Matrix = 
         if (exp == 1) m else mXm(m, recPower(m, exp - 1))

  def apply(i:Int,j:Int) = m(i)(j)

  def rowCount = m.length
  def colCount = m.head.length

  def toStr = "\n" + m.map { _.map{"\t" + _}.reduceLeft(_ + _) + "\n" }.reduceLeft(_ + _)
}

object Matrix{

  /** A convenient alias */
  type Matrix = List[Row]

  def apply( rowCount:Int, colCount:Int )( f:(Int,Int) => BigInt ) = (
     for(i <- 1 to rowCount) yield
        ( for( j <- 1 to colCount) yield f(i,j) ).toList
     ).toList

  def transpose(m:Matrix):Matrix =
      if(m.head.isEmpty) Nil else m.map(_.head) :: transpose(m.map(_.tail))

  def mXv(m:Matrix, v:Row) = m.map{ dotProd(_,v) } reduceLeft ( _ + _ )

  def mXm( m1:Matrix, m2:Matrix ) =
     for( m1row <- m1 ) yield
        for( m2col <- transpose(m2) ) yield
           dotProd( m1row, m2col )

  def rowCount(m:Matrix) = m.length
  def colCount(m:Matrix) = m.head.length

  /** effectively add RichMatrix methods to List[List[BigInt]] */
  implicit def pimp1(m:Matrix) = new RichMatrix(m)
  implicit def pimp2(m:List[Projection[BigInt]]) = new RichMatrix(m.map{_.toList})
  implicit def pimp1(m:Projection[List[BigInt]]) = new RichMatrix(m.toList)
  implicit def pimp2(m:Projection[Projection[BigInt]]) = new RichMatrix(m.map{_.toList}.toList)

  // Suggested by Travis Brown - Not working
  //  implicit def toRichMatrixWithPower(m: Matrix) = new {
  //    val matrix = new RichMatrix(m)
  //    def power(n: Int) = {
  //      require(matrix.rowCount == matrix.colCount)
  //      Iterator.iterate(matrix)(_ * matrix).drop(n - 1).next
  //    }
  //  }

  def main(args: Array[String]): Unit =
  {
    val m = List(List[BigInt](1, 1), List[BigInt](1, 0))

    println((m power 9999)(0)(1)) //java.lang.StackOverflowError
  }
}
/*
* Copyright (c) 2010 Eamonn O'Brien-Strain, eob@well.com
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which is available at http://www.eclipse.org/legal/epl-v10.html
*/

package org.eamonn.published_matrix

import Matrix._
import Row._

/** Methods that are added to List[List[Double]] by an implicit conversion */
case class RichMatrix(m:Matrix){

  def T = transpose(m)

  def *(that:RichMatrix) = mXm( this.m, that.m )

  def apply(i:Int,j:Int) = m(i)(j)

  def rowCount = m.length
  def colCount = m.head.length

  def toStr = "\n" + m.map { _.map{"\t" + _}.reduceLeft(_ + _) + "\n" }.reduceLeft(_ + _)
}

object Row{

  /** A convenient alias */
  type Row = List[BigInt]

  def dotProd(v1:Row,v2:Row) = v1.zip( v2 ).map{ t:(BigInt,BigInt) => t._1 * t._2 }.reduceLeft(_ + _)
}

object Matrix{

  /** A convenient alias */
  type Matrix = List[Row]

  def transpose(m:Matrix):Matrix =
    if(m.head.isEmpty) Nil else m.map(_.head) :: transpose(m.map(_.tail))

  def mXm( m1:Matrix, m2:Matrix ) =
    for( m1row <- m1 ) yield
      for( m2col <- transpose(m2) ) yield
        dotProd( m1row, m2col )

  def rowCount(m:Matrix) = m.length
  def colCount(m:Matrix) = m.head.length


  /** effectively add RichMatrix methods to List[List[Double]] */
  implicit def pimp1(m:Matrix) = new RichMatrix(m)

  implicit def matrixPower(m: Matrix) = new {
    //val matrix = new RichMatrix(m)
    def power(n: Int) = {
      require(m.rowCount == m.colCount)
      Iterator.iterate(m)(_ * m).drop(n - 1).next
    }
  }


  def main(args: Array[String]): Unit =
  {
    val m = List(List[BigInt](1, 1), List[BigInt](1, 0))

    println(m.power(9)(1)(0))
  }
}
/*
*版权所有(c)2010埃蒙恩·奥布莱恩·斯特恩,eob@well.com
*版权所有。本计划及随附材料
*根据Eclipse公共许可证v1.0的条款提供
*可于http://www.eclipse.org/legal/epl-v10.html
*/
包org.eamonn.published\u矩阵
导入矩阵_
导入行_
导入顺序投影
/**通过隐式转换添加到List[List[BigInt]]的方法*/
案例类别矩阵(m:矩阵){
def T=转置(m)
def*(that:RichMatrix)=mXm(this.m,that.m)
def power(exp:Int)=recPower(this.m,exp)
def recPower(m:Matrix,exp:BigInt):矩阵=
if(exp==1)m else mXm(m,recPower(m,exp-1))
def应用(i:Int,j:Int)=m(i)(j)
def rowCount=m.length
def colCount=米头长度
def toStr=“\n”+m.map{{t+}.reduceLeft(++++++“\n”}.reduceLeft(++)
}
对象矩阵{
/**方便的别名*/
类型矩阵=列表[行]
def apply(rowCount:Int,colCount:Int)(f:(Int,Int)=>BigInt)=(

对于(i扩展像
RichMatrix
这样的case类,这是一个坏主意,在Scala的最新版本中被弃用。但是,您可以按照作者的模式使用以下方法:

import org.eamonn.published_matrix._
import org.eamonn.published_matrix.Matrix._

implicit def toRichMatrixWithPower(m: Matrix) = new {
  val matrix = new RichMatrix(m)
  def power(n: Int) = {
    require(matrix.rowCount == matrix.colCount)
    Iterator.iterate(matrix)(_ * matrix).drop(n - 1).next
  }
}
现在
List(List(2.0,0.0),List(0.0,2.0))。例如,power(3)
应该给出以下内容:

RichMatrix(List(List(8.0, 0.0), List(0.0, 8.0)))

不过,您最好使用严肃的或矩阵库。

扩展像
RichMatrix
这样的case类这是一个坏主意,在Scala的最新版本中被弃用。但是,您可以按照作者的模式使用以下方法:

import org.eamonn.published_matrix._
import org.eamonn.published_matrix.Matrix._

implicit def toRichMatrixWithPower(m: Matrix) = new {
  val matrix = new RichMatrix(m)
  def power(n: Int) = {
    require(matrix.rowCount == matrix.colCount)
    Iterator.iterate(matrix)(_ * matrix).drop(n - 1).next
  }
}
现在
List(List(2.0,0.0),List(0.0,2.0))。例如,power(3)
应该给出以下内容:

RichMatrix(List(List(8.0, 0.0), List(0.0, 8.0)))

不过,您最好使用严肃的或矩阵库。

这是最后的工作代码。谢谢@travis brown

文件Matrix.scala

/*
* Copyright (c) 2010 Eamonn O'Brien-Strain, eob@well.com
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which is available at http://www.eclipse.org/legal/epl-v10.html
*/

package org.eamonn.published_matrix

import Matrix._
import Row._
import Seq.Projection

/** Methods that are added to List[List[BigInt]] by an implicit conversion */
case class RichMatrix(m:Matrix){

  def T = transpose(m)

  def *(that:RichMatrix) = mXm( this.m, that.m )

  def power (exp:Int) = recPower(this.m, exp)

  def recPower(m:Matrix, exp:BigInt) : Matrix = 
         if (exp == 1) m else mXm(m, recPower(m, exp - 1))

  def apply(i:Int,j:Int) = m(i)(j)

  def rowCount = m.length
  def colCount = m.head.length

  def toStr = "\n" + m.map { _.map{"\t" + _}.reduceLeft(_ + _) + "\n" }.reduceLeft(_ + _)
}

object Matrix{

  /** A convenient alias */
  type Matrix = List[Row]

  def apply( rowCount:Int, colCount:Int )( f:(Int,Int) => BigInt ) = (
     for(i <- 1 to rowCount) yield
        ( for( j <- 1 to colCount) yield f(i,j) ).toList
     ).toList

  def transpose(m:Matrix):Matrix =
      if(m.head.isEmpty) Nil else m.map(_.head) :: transpose(m.map(_.tail))

  def mXv(m:Matrix, v:Row) = m.map{ dotProd(_,v) } reduceLeft ( _ + _ )

  def mXm( m1:Matrix, m2:Matrix ) =
     for( m1row <- m1 ) yield
        for( m2col <- transpose(m2) ) yield
           dotProd( m1row, m2col )

  def rowCount(m:Matrix) = m.length
  def colCount(m:Matrix) = m.head.length

  /** effectively add RichMatrix methods to List[List[BigInt]] */
  implicit def pimp1(m:Matrix) = new RichMatrix(m)
  implicit def pimp2(m:List[Projection[BigInt]]) = new RichMatrix(m.map{_.toList})
  implicit def pimp1(m:Projection[List[BigInt]]) = new RichMatrix(m.toList)
  implicit def pimp2(m:Projection[Projection[BigInt]]) = new RichMatrix(m.map{_.toList}.toList)

  // Suggested by Travis Brown - Not working
  //  implicit def toRichMatrixWithPower(m: Matrix) = new {
  //    val matrix = new RichMatrix(m)
  //    def power(n: Int) = {
  //      require(matrix.rowCount == matrix.colCount)
  //      Iterator.iterate(matrix)(_ * matrix).drop(n - 1).next
  //    }
  //  }

  def main(args: Array[String]): Unit =
  {
    val m = List(List[BigInt](1, 1), List[BigInt](1, 0))

    println((m power 9999)(0)(1)) //java.lang.StackOverflowError
  }
}
/*
* Copyright (c) 2010 Eamonn O'Brien-Strain, eob@well.com
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which is available at http://www.eclipse.org/legal/epl-v10.html
*/

package org.eamonn.published_matrix

import Matrix._
import Row._

/** Methods that are added to List[List[Double]] by an implicit conversion */
case class RichMatrix(m:Matrix){

  def T = transpose(m)

  def *(that:RichMatrix) = mXm( this.m, that.m )

  def apply(i:Int,j:Int) = m(i)(j)

  def rowCount = m.length
  def colCount = m.head.length

  def toStr = "\n" + m.map { _.map{"\t" + _}.reduceLeft(_ + _) + "\n" }.reduceLeft(_ + _)
}

object Row{

  /** A convenient alias */
  type Row = List[BigInt]

  def dotProd(v1:Row,v2:Row) = v1.zip( v2 ).map{ t:(BigInt,BigInt) => t._1 * t._2 }.reduceLeft(_ + _)
}

object Matrix{

  /** A convenient alias */
  type Matrix = List[Row]

  def transpose(m:Matrix):Matrix =
    if(m.head.isEmpty) Nil else m.map(_.head) :: transpose(m.map(_.tail))

  def mXm( m1:Matrix, m2:Matrix ) =
    for( m1row <- m1 ) yield
      for( m2col <- transpose(m2) ) yield
        dotProd( m1row, m2col )

  def rowCount(m:Matrix) = m.length
  def colCount(m:Matrix) = m.head.length


  /** effectively add RichMatrix methods to List[List[Double]] */
  implicit def pimp1(m:Matrix) = new RichMatrix(m)

  implicit def matrixPower(m: Matrix) = new {
    //val matrix = new RichMatrix(m)
    def power(n: Int) = {
      require(m.rowCount == m.colCount)
      Iterator.iterate(m)(_ * m).drop(n - 1).next
    }
  }


  def main(args: Array[String]): Unit =
  {
    val m = List(List[BigInt](1, 1), List[BigInt](1, 0))

    println(m.power(9)(1)(0))
  }
}
/*
*版权所有(c)2010埃蒙恩·奥布莱恩·斯特恩,eob@well.com
*保留所有权利。本计划及随附资料
*根据Eclipse公共许可证v1.0的条款提供
*可于http://www.eclipse.org/legal/epl-v10.html
*/
包org.eamonn.published\u矩阵
导入矩阵_
导入行_
/**通过隐式转换添加到List[List[Double]]的方法*/
案例类别矩阵(m:矩阵){
def T=转置(m)
def*(that:RichMatrix)=mXm(this.m,that.m)
def应用(i:Int,j:Int)=m(i)(j)
def rowCount=m.length
def colCount=米头长度
def toStr=“\n”+m.map{{t+}.reduceLeft(++++++“\n”}.reduceLeft(++)
}
对象行{
/**方便的别名*/
类型行=列表[BigInt]
def dotProd(v1:Row,v2:Row)=v1.zip(v2.map{t:(BigInt,BigInt)=>t._1*t._2}.reduceLeft(uu+)
}
对象矩阵{
/**方便的别名*/
类型矩阵=列表[行]
def转置(m:矩阵):矩阵=
if(m.head.isEmpty)Nil else m.map(u.head)::转置(m.map(u.tail))
def mXm(m1:矩阵,m2:矩阵)=

对于(m1row这是最后的工作代码。谢谢@travis brown

文件Matrix.scala

/*
* Copyright (c) 2010 Eamonn O'Brien-Strain, eob@well.com
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which is available at http://www.eclipse.org/legal/epl-v10.html
*/

package org.eamonn.published_matrix

import Matrix._
import Row._
import Seq.Projection

/** Methods that are added to List[List[BigInt]] by an implicit conversion */
case class RichMatrix(m:Matrix){

  def T = transpose(m)

  def *(that:RichMatrix) = mXm( this.m, that.m )

  def power (exp:Int) = recPower(this.m, exp)

  def recPower(m:Matrix, exp:BigInt) : Matrix = 
         if (exp == 1) m else mXm(m, recPower(m, exp - 1))

  def apply(i:Int,j:Int) = m(i)(j)

  def rowCount = m.length
  def colCount = m.head.length

  def toStr = "\n" + m.map { _.map{"\t" + _}.reduceLeft(_ + _) + "\n" }.reduceLeft(_ + _)
}

object Matrix{

  /** A convenient alias */
  type Matrix = List[Row]

  def apply( rowCount:Int, colCount:Int )( f:(Int,Int) => BigInt ) = (
     for(i <- 1 to rowCount) yield
        ( for( j <- 1 to colCount) yield f(i,j) ).toList
     ).toList

  def transpose(m:Matrix):Matrix =
      if(m.head.isEmpty) Nil else m.map(_.head) :: transpose(m.map(_.tail))

  def mXv(m:Matrix, v:Row) = m.map{ dotProd(_,v) } reduceLeft ( _ + _ )

  def mXm( m1:Matrix, m2:Matrix ) =
     for( m1row <- m1 ) yield
        for( m2col <- transpose(m2) ) yield
           dotProd( m1row, m2col )

  def rowCount(m:Matrix) = m.length
  def colCount(m:Matrix) = m.head.length

  /** effectively add RichMatrix methods to List[List[BigInt]] */
  implicit def pimp1(m:Matrix) = new RichMatrix(m)
  implicit def pimp2(m:List[Projection[BigInt]]) = new RichMatrix(m.map{_.toList})
  implicit def pimp1(m:Projection[List[BigInt]]) = new RichMatrix(m.toList)
  implicit def pimp2(m:Projection[Projection[BigInt]]) = new RichMatrix(m.map{_.toList}.toList)

  // Suggested by Travis Brown - Not working
  //  implicit def toRichMatrixWithPower(m: Matrix) = new {
  //    val matrix = new RichMatrix(m)
  //    def power(n: Int) = {
  //      require(matrix.rowCount == matrix.colCount)
  //      Iterator.iterate(matrix)(_ * matrix).drop(n - 1).next
  //    }
  //  }

  def main(args: Array[String]): Unit =
  {
    val m = List(List[BigInt](1, 1), List[BigInt](1, 0))

    println((m power 9999)(0)(1)) //java.lang.StackOverflowError
  }
}
/*
* Copyright (c) 2010 Eamonn O'Brien-Strain, eob@well.com
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which is available at http://www.eclipse.org/legal/epl-v10.html
*/

package org.eamonn.published_matrix

import Matrix._
import Row._

/** Methods that are added to List[List[Double]] by an implicit conversion */
case class RichMatrix(m:Matrix){

  def T = transpose(m)

  def *(that:RichMatrix) = mXm( this.m, that.m )

  def apply(i:Int,j:Int) = m(i)(j)

  def rowCount = m.length
  def colCount = m.head.length

  def toStr = "\n" + m.map { _.map{"\t" + _}.reduceLeft(_ + _) + "\n" }.reduceLeft(_ + _)
}

object Row{

  /** A convenient alias */
  type Row = List[BigInt]

  def dotProd(v1:Row,v2:Row) = v1.zip( v2 ).map{ t:(BigInt,BigInt) => t._1 * t._2 }.reduceLeft(_ + _)
}

object Matrix{

  /** A convenient alias */
  type Matrix = List[Row]

  def transpose(m:Matrix):Matrix =
    if(m.head.isEmpty) Nil else m.map(_.head) :: transpose(m.map(_.tail))

  def mXm( m1:Matrix, m2:Matrix ) =
    for( m1row <- m1 ) yield
      for( m2col <- transpose(m2) ) yield
        dotProd( m1row, m2col )

  def rowCount(m:Matrix) = m.length
  def colCount(m:Matrix) = m.head.length


  /** effectively add RichMatrix methods to List[List[Double]] */
  implicit def pimp1(m:Matrix) = new RichMatrix(m)

  implicit def matrixPower(m: Matrix) = new {
    //val matrix = new RichMatrix(m)
    def power(n: Int) = {
      require(m.rowCount == m.colCount)
      Iterator.iterate(m)(_ * m).drop(n - 1).next
    }
  }


  def main(args: Array[String]): Unit =
  {
    val m = List(List[BigInt](1, 1), List[BigInt](1, 0))

    println(m.power(9)(1)(0))
  }
}
/*
*版权所有(c)2010埃蒙恩·奥布莱恩·斯特恩,eob@well.com
*保留所有权利。本计划及随附资料
*根据Eclipse公共许可证v1.0的条款提供
*可于http://www.eclipse.org/legal/epl-v10.html
*/
包org.eamonn.published\u矩阵
导入矩阵_
导入行_
/**通过隐式转换添加到List[List[Double]]的方法*/
案例类别矩阵(m:矩阵){
def T=转置(m)
def*(that:RichMatrix)=mXm(this.m,that.m)
def应用(i:Int,j:Int)=m(i)(j)
def rowCount=m.length
def colCount=米头长度
def toStr=“\n”+m.map{{t+}.reduceLeft(++++++“\n”}.reduceLeft(++)
}
对象行{
/**方便的别名*/
类型行=列表[BigInt]
def dotProd(v1:Row,v2:Row)=v1.zip(v2.map{t:(BigInt,BigInt)=>t._1*t._2}.reduceLeft(uu+)
}
对象矩阵{
/**方便的别名*/
类型矩阵=列表[行]
def转置(m:矩阵):矩阵=
if(m.head.isEmpty)Nil else m.map(u.head)::转置(m.map(u.tail))
def mXm(m1:矩阵,m2:矩阵)=

以下是我对这个问题的观点:

def fibonacci(n: Int): Int = {
  def loop(a: Int, b: Int, c: Int, d: Int, n: Int, 
           e: Int, f: Int, g: Int, h: Int): Int =
    if (n == 0) f
    else if (n % 2 != 0)
      loop(a * a + b * c, a * b + b * d, c * a + d * c, c * b + d * d, n / 2, 
           e * a + g * b, f * a + h * b, e * c + g * d, f * c + h * d)
    else 
      loop(a * a + b * c, a * b + b * d, c * a + d * c, c * b + d * d, n / 2, 
           e, f, g, h)

  loop(1, 1, 1, 0, n + 1, 1, 0, 0, 1)
}

这是一个纯功能性的解决方案,没有可变数组和使用尾部递归的副作用。请参阅我的收藏中的更多此类代码示例。

以下是我对这个问题的观点:

def fibonacci(n: Int): Int = {
  def loop(a: Int, b: Int, c: Int, d: Int, n: Int, 
           e: Int, f: Int, g: Int, h: Int): Int =
    if (n == 0) f
    else if (n % 2 != 0)
      loop(a * a + b * c, a * b + b * d, c * a + d * c, c * b + d * d, n / 2, 
           e * a + g * b, f * a + h * b, e * c + g * d, f * c + h * d)
    else 
      loop(a * a + b * c, a * b + b * d, c * a + d * c, c * b + d * d, n / 2, 
           e, f, g, h)

  loop(1, 1, 1, 0, n + 1, 1, 0, 0, 1)
}
这是一个纯功能性的解决方案,没有可变数组和使用尾部递归的副作用