scala习题(11)——操作符

来源:互联网 发布:模拟整容软件 编辑:程序博客网 时间:2024/06/15 09:50

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”应产出:JavaScalaGosling…
    注意操作符无论何时都是针对于对象来说的,所以要返回的数据只能是该对象
 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));     }
0 0
原创粉丝点击