code1:

object factorial{
  def main(args:Array[String])={
    println(factorial(args(0).toInt))
  }

  def factorial(x:Int):Int =
    if (x==0) 1 else x * factorial(x-1)
}

这个实现的执行过程如下,比如我们计算4的阶乘factorial(4)

factorial(4)

--> if (4==0) 1 else 4 * factorial(4-1)

-->4*factorial(3)

-->4*(3*factorial(2))

-->4*(3*(2*factorial(1)))

-->4*(3*(2*(1*factorial(0))))

-->4*(3*(2*(1*1)))

-->24

计算机在执行上述计算的过程中,需要用到“栈”,并且我们不难看到为了计算factorial(4),栈不断增大。

为了避免像这样的计算可能导致“栈溢出”,可以采用一个小技巧,就是将上述的递归转化为“尾”递归。

关于尾递归,可以参考:http://en.wikipedia.org/wiki/Tail_call

code2:

object factorial{
  def main(args:Array[String])={
    println(factorial(args(0).toInt,1))
  }

  def factorial(x:Int,result:Int):Int =
    if (x==0) result else factorial(x-1,x*result)
}

思路也很简单,不再赘述。

但是code2有个缺点,那就是factorial函数的参数多了一个:result,并且,每次调用factorial函数,都要给result传一个实参:1

因为将code2修改如下:

code3:

object factorial{
  def main(args:Array[String])={
    println(factorial(args(0).toInt))
  }

  def factorial(x:Int):Int ={
     def loop(x:Int,acc:Int):Int = {
       if(x==0) acc
       else loop(x-1,x*acc)
     }
     loop(x,1)
  }
}

The End..........

Thinking in scala (4)----阶乘与尾递归的更多相关文章

  1. Scala进阶之路-尾递归优化

    Scala进阶之路-尾递归优化 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 递归调用有时候能被转换成循环,这样能节约栈空间.在函数式编程中,这是很重要的,我们通常会使用递归方法来 ...

  2. Java8之旅(六) -- 使用lambda实现尾递归

    前言 本篇介绍的不是什么新知识,而是对前面讲解的一些知识的综合运用.众所周知,递归是解决复杂问题的一个很有效的方式,也是函数式语言的核心,在一些函数式语言中,是没有迭代与while这种概念的,因为此类 ...

  3. Scala详解

    1       快速入门... 4 1.1             分号... 4 1.2             常变量声明... 4 1.2.1         val常量... 4 1.2.2  ...

  4. Java8函数之旅 (六) -- 使用lambda实现Java的尾递归

    前言 本篇介绍的不是什么新知识,而是对前面讲解的一些知识的综合运用.众所周知,递归是解决复杂问题的一个很有效的方式,也是函数式语言的核心,在一些函数式语言中,是没有迭代与while这种概念的,因为此类 ...

  5. Scala总结

    Scala总结 ===概述 scala是一门以Java虚拟机(JVM)为目标运行环境并将面向对象和函数式编程的最佳特性结合在一起的静态类型编程语言. scala是纯粹的面向对象的语言.java虽然是面 ...

  6. Scala学习十五——注解

    一.本章要点 可以为类.方法.字段.局部变量.参数.表达式.类型参数以及各种类型定义添加注解 对于表达式和类型,注解跟在被注解的条目之后 注解的形式有@Annotation.@Annotation(v ...

  7. scala编程(八)——函数和闭包

    当程序变得庞大时,你需要一些方法把它们分割成更小的,更易管理的片段.为了分割控制流,Scala 提供了所有有经验的程序员都熟悉的方式:把代码分割成函数.实际上,Scala 提供了许多 Java 中没有 ...

  8. 递归、尾递归和使用Stream延迟计算优化尾递归

    我们在学数据结构的时候必然会接触栈(Stack),而栈有一个重要的应用是在程序设计语言中实现递归.递归用途十分广泛,比如我们常见的阶乘,如下代码: 1234 public static int (in ...

  9. Android ViewTreeObserver简介

    Android ViewTreeObserver简介   一.结构 public final class ViewTreeObserver extends Object java.lang.Objec ...

随机推荐

  1. 转:WebDriver(Selenium2) 处理可能存在的JS弹出框

    在自动化测试过程中,有些情况下我们会遇到一些潜在的Javascript弹出框.(即某些条件下才会出现,不是固定出现),然后如果当这种弹出框出现,我们没有加以处理,WebDriver将无法进行下一步的操 ...

  2. (二)、Struts第二天

    (二).Struts第二天 回顾: 问题: 1. Struts2的Action类是单例还是多例? Filter? Servlet? Listener? 2. 介绍struts2框架引入的相关jar包及 ...

  3. opencart配置税率

    1.System->Localisation->Geo Zones新增税收区域 2.System->Localisation->Taxes->Tax Rates新增税率 ...

  4. hdu_5718_Oracle(大数模拟)

    题目连接:hdu_5718_Oracle 题意: 给你一串数,让你分出两个正整数,使其和最大,若不能分出来就输出"Uncertain" 题解: 当时比赛的时候还天真的去搞大数模版, ...

  5. Tomcat数据源

    Tomcat数据源原理,配置,使用 在程序中,使用数据源是可以提升操作性能的,这种性能 的提升依靠运行的操作原理. 传统的JDBC操作: 1. 加载数据库驱动,通过CLASSPATH配置 2. 通过D ...

  6. Android的Activity跳转动画各种效果整理

    Android的Activity跳转就是很生硬的切换界面.其实Android的Activity跳转可以设置各种动画,本文整理了一些,还有很多动画效果,就要靠我们发挥自己的想象力 大家使用Android ...

  7. 认识和选用常用的几种 GPRS 模块(转)

    源:http://blog.sina.com.cn/s/blog_4d80055a0100e8kr.html 我在这里把常见的GPRS模块分成3种: (1)GPRS DTU(GPRS数传单元,常称GP ...

  8. 我也谈“the difference between Factory, Service, and Provider in Angular”

    看完这篇文章之后的理解与实践:原文地址:http://tylermcginnis.com/angularjs-factory-vs-service-vs-provider/ <!doctype ...

  9. applicationContext.xml文件配置模板

    <?xml version="1.0" encoding="gb2312"?><!--  Spring配置文件的DTD定义-->< ...

  10. 磁盘寻道时间算法之----------------SCAN算法和最短寻道时间优先调度算法

    若干个等待访问磁盘者依次要访问的柱面编号为:80,40,74,14,60,31,61,假设每移动一个柱面需要4毫秒时间,移动到当前位于35号柱面,且当前的移动方向向柱面号增加的方向.请计算: (1)若 ...