scala習題(11)——操作符
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));
}