scala习题(11)——操作符

本文探讨了Scala中操作符的优先级规则,并通过实例解释了如何根据优先级进行计算。文章提到了BigInt类的pow方法,Fraction类的实现,Money类的设计,以及如何创建ASCIIArt、BigSequence和Matrix类。此外,还讨论了RichFile类的unapply和unapplySeq方法,用于提取文件路径信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

scala操作符优先级
*/%
+-
:
<>
!=
&
^
|-
非操作符
最低优先级赋值操作符
从高到低优先级逐渐降低,同一层属同等优先级,按照从左到右的顺序进行计算(除了以冒号结尾的操作符和赋值操作符)

1.根据优先级规则,3+4 ->5 和 3 ->4+5是如何被求值的
(3+4 ->5)因为+号和->号的优先级在同一层次上(组合操作符按照组合中的最高级别操作符来定义优先级,+,-号在同一层,所以优先级一样),所以按照从左到右的运算方式来运算即为(7,5)
第二个算式存在问题,不能直接这么加减,因为元组和int相加时会先转换成字符串,而5的类型并不是字符串,直接repl中输入就会上报一个type missmatch的错误

2.BigInt类有一个pow方法,但没有用操作符字符。Scala类库的设计者为什么没有选用**(像Fortran那样)或者^(像Pascal那样)作为乘方操作符呢?

一般乘方的操作符是优于乘法操作的,如果使用**作为乘方的话,那么其优先级则与*相同,而如果使用^的话则属于非操作符,则优先级低于*操作。优先级都是有问题的。故没有使用这两种操作符

3.实现Fraction类,支持+*/操作。支持约分,例如将15/-6变为-5/2。除以最大公约数,像这样:

class Fraction(n:Int,d:Int){
    private val num:Int = if(d==0) 1 else n * sign(d)/gcd(n,d);
    private val den:Int = if(d==0) 0 else d * sign(d)/gcd(n,d);
    override def toString = num + "/" + den
    def sign(a:Int) = if(a > 0) 1 else if (a < 0) -1 else 0
    def gcd(a:Int,b:Int):Int = if(b==0) abs(a) else gcd(b,a%b)
    ...
}
class Fraction(n:Int,d:Int){
      private val num:Int = if(d==0) 1 else n * sign(d)/gcd(n,d);
      private val den:Int = if(d==0) 0 else d * sign(d)/gcd(n,d);
      override def toString = num + "/" + den
      def sign(a:Int) = if(a > 0) 1 else if (a < 0) -1 else 0
      def gcd(a:Int,b:Int):Int = if(b==0) abs(a) else gcd(b,a%b)
      def +(other:Fraction):Fraction={

         new Fraction((this.num*other.den+this.den*other.num),this.den*other.den);

      }
      def -(other:Fraction):Fraction={
        new Fraction((this.num*other.den-this.den*other.num),this.den*other.den);
      }
      def *(other:Fraction):Fraction={
        new Fraction((this.num*other.num),this.den*other.den);
      }
      def /(other:Fraction):Fraction={
        new Fraction((this.num*other.den),this.den*other.num);
      }
  }
  object Fraction {
     def apply(n:Int,d:Int):Fraction={
       new Fraction(n,d);
     }
     def unapply(input:Fraction):Option[(Int,Int)]={
        if(input.den==0) None else Some((input.num,input.den));
     }
  }
  1. 实现一个Money类,加入美元和美分字段。提供+,-操作符以及比较操作符==和<。举例来说,Money(1,75)+Money(0,50)==Money(2,25)应为true。你应该同时提供*和/操作符吗?为什么?

不需要提供,因为对于金额来说,乘除并没有意义

class Money(y:Int,f:Int){
    private val yuan:Int= if(f<100&&f>=0) y else if(f>=100) y+f/100 else { if(abs(f)>=100) y-abs(f)/100 else y-1};
    private val fen:Int=if(f<100&&f>=0) f else if(f>=100) f%100 else { if(abs(f)>=100) abs(f)/100*100+f else f+100};
    def +(other:Money):Money={
      new Money(this.yuan+other.yuan,this.fen+other.fen);
    }
    def -(other:Money):Money={
     if(this>other){
      new Money(this.yuan-other.yuan,this.fen-other.fen);
     }else{
       println("not much money");
       null
     }
    }
    def >(other:Money):Boolean={
      if(this.yuan>other.yuan){
        true;
      }else if(this.yuan<other.yuan){
        false
      }else{
        if(this.fen>other.fen) true else false;
      }

    }
    def <(other:Money):Boolean={
      if(this.yuan<other.yuan){
        true;
      }else if(this.yuan>other.yuan){
        false
      }else{
        if(this.fen>other.fen) false else true;
      }

    }
    override def toString()="yuan:"+yuan+" fen:"+fen;
  }
  object Money{
    def apply(y:Int,f:Int):Money={
      new Money(y,f);
    }
  }
  1. 提 供操作符用于构造HTML表格。例如:Table() | “Java” | “Scala” || “Gosling” | “Odersky” || “JVM” | “JVM,.NET”应产出:
    JavaScala
    Gosling…
    注意操作符无论何时都是针对于对象来说的,所以要返回的数据只能是该对象
 class Table{
    var s:String="";

    def |(txt:String):Table={
      s=s+"<td>"+txt+"</td>";
      this;
    }
    def ||(txt:String):Table={       
        s=s+"</tr>"+"<tr><td>"+txt+"</td>";
        this;
    }
    override def toString="<table><tr>"+s+"</tr></table>";
  }
  object Table{
    def apply():Table={
      new Table();
    }
  }

6.提供一个ASCIIArt类,其对象包含类似这样的图形:
/_/\
( ’ ’ )
( - )
| | |
(|)
提供将两个ASCIIArt图形横向或纵向结合的操作符。选用适当优先级的操作符命名。纵向结合的实例
/_/\ —–
( ’ ’ ) / Hello \
( - ) < Scala |
| | | \ Coder /
(|) —–

class ASCIIArt(str:String){
      var markstr:ArrayBuffer[ArrayBuffer[String]]=new ArrayBuffer[ArrayBuffer[String]]();
      if(str!=null){
        str.split("[\r\n]+").foreach { line => var a=new ArrayBuffer[String]();a+=line;markstr+=a; }
      }
      override def toString()={
        var s="";
        markstr.foreach { s+=_.mkString+"\n"; }
        s;
      }
      def +(other:ASCIIArt)={
        var Str="";
        var j=0;
        for(i<- 0 until this.markstr.length){
          if(i<=other.markstr.length){
            Str=Str+markstr(i).mkString+other.markstr(i).mkString+"\n";
          }else{
            Str=Str+markstr(i).mkString+"\n";
          }
          j=j+1;
        }
        if(j<other.markstr.length){
          for(i<- j until other.markstr.length){
                Str=Str+other.markstr(i).mkString+"\n";
          }
        }
        new ASCIIArt(Str);
      }

  }

7.实现一个BigSequence类,将64个bit的序列打包在一个Long值中。提供apply和update操作来获取和设置某个具体的bit

class BigSequence{
     var SeqNum=new Array[Int](64);
     for(i<- (0 until SeqNum.length)){
       SeqNum(i)= -1;
     }
     def pack():Long={
        SeqNum.filter(_ >= 0).mkString.toLong
     }




  }
  object BigSequence{
    def apply(num:Int,input:BigSequence):Int={
        input.SeqNum(num);
    }
    def apply(num:Int)={
      val b = new BigSequence
      var i = 0
      num.toString.foreach{
      n=>
      b.SeqNum(i) = n.getNumericValue
      i+=1
    }
    b
    }
     def update(num:Int,input:BigSequence,value:Int)={
       input.SeqNum(num)=value;
     }
  }

8.提供一个Matrix类—你可以选择需要的是一个2*2的矩阵,任意大小的正方形矩阵,或m*n的矩阵。支持+和操作。操作应同样适用于单值,例如mat*2。单个元素可以通过mat(row,col)得到

class Matrix(row:Int=2,col:Int=2,content:Array[Int]){
     private val rowIndex=row;
     private val colIndex=col;
     private val co:Array[Int]=if(content.length<row*col) {
        val s=for(i <- (0 until row*col)) yield {
          if(i<content.length){ 
            content(i) 
          }else 0
        }
        s.toArray;
     }else{
       val s = for(i <- (0 until row*col)) yield {
         content(i)
       }
       s.toArray
     }
     def +(other:Matrix):Matrix={
       if((this.rowIndex==other.rowIndex)&&(this.colIndex == other.colIndex)){
         val s=for(i<-(0 until this.co.length)) yield {
            this.co(i)+other.co(i);
         }
         new Matrix(rowIndex,colIndex,s.toArray);
       }else null;

     }
     def -(other:Matrix):Matrix={
       if((this.rowIndex==other.rowIndex)&&(this.colIndex == other.colIndex)){
         val s=for(i<-(0 until this.co.length)) yield {
            this.co(i)-other.co(i);
         }
         new Matrix(rowIndex,colIndex,s.toArray);
       }else null;
     }
     def *(other:Matrix):Matrix={
        if(this.colIndex==other.rowIndex){
          val s:Array[Int]=new Array[Int](this.rowIndex*other.colIndex);
          for(i<-(0 until this.rowIndex )){
             for(j<- (0 until other.colIndex)){
                var sum=0;
                for(m<-( 0 until this.colIndex)){
                  val e=this.co(i*this.colIndex+m)
                  val d=other.co(m*other.colIndex+j)
                  sum=sum+e*d;
                }
                s(i*this.rowIndex+j)=sum;
             }
          }
          new Matrix(this.rowIndex,other.colIndex,s)
        }else null
     }
     def *(mat:Int):Matrix={
       val s=for(i<- (0 until this.co.length)) yield{
         this.co(i)*mat;
       }
       new Matrix(this.rowIndex,this.colIndex,s.toArray);
     }
     def show()={
       for(i<- (0 until this.co.length)){
         print(co(i)+",");
       }
     }

  }
  object Matrix{
     def apply(row:Int=2,col:Int=2,content:Array[Int])={
       new Matrix(row,col,content:Array[Int]);
     }
  }

9.为RichFile类定义unapply操作,提取文件路径,名称和扩展名。举例来说,文件/home/cay/readme.txt的路径为/home/cay,名称为readme,扩展名为txt

  def unapply(path:String)={
    val pa=path.split("/");
    val index=pa(pa.length-1).indexOf(".")
    Some((pa(pa.length-1).substring(0, index),pa(pa.length-1).substring(index+1,pa(pa.length-1).length())));

  }

10.为RichFile类定义一个unapplySeq,提取所有路径段。举例来说,对于/home/cay/readme.txt,你应该产出三个路径段的序列:home,cay和readme.txt

 def unapplyseq(path:String):Option[Seq[String]]={
    Some(path.split("/"));

  }

9和10中unapply的使用方法,这里给个例子

 val Fraction(r)=f;
 println(r);
 def unapply(input:Fraction):Option[(Int,Int)]={
        if(input.den==0) None else Some((input.num,input.den));
     }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值