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));
}
}
- 实现一个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);
}
}
- 提 供操作符用于构造HTML表格。例如:Table() | “Java” | “Scala” || “Gosling” | “Odersky” || “JVM” | “JVM,.NET”应产出:
Java Scala 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));
}