Scala的数学运算、关系和逻辑操作及位操作符

开发 后端
本文节选自Martin Odersky,Lex Spoon和Bill Venners所著,Regular翻译的《Programming in Scala》的第五章。Scala是一种针对 JVM 将函数和面向对象技术组合在一起的编程语言。

数学运算

你可以通过中缀操作符,加号(+),减号(-),乘号(*),除号(/)和余数(%),在任何数类型上调用数学方法。以下是一些例子:

51CTO编辑推荐:Scala编程语言专题

  1. scala> 1.2 + 2.3 
  2. res6: Double = 3.5 
  3. scala> 3 - 1 
  4. res7: Int = 2 
  5. scala> 'b' - 'a' 
  6. res8: Int = 1 
  7. scala> 2L * 3L  
  8. res9: Long = 6 
  9. scala> 11 / 4 
  10. res10: Int = 2 
  11. scala> 11 % 4 
  12. res11: Int = 3 
  13. scala> 11.0f / 4.0f  
  14. res12: Float = 2.75 
  15. scala> 11.0 % 4.0 
  16. res13: Double = 3.0 
当左右两个操作数都是整数类型时(Int,Long,Byte,Short,或Char),/操作符将返回给你商的整数部分,去掉余数部分。%操作符指明它的余数。

用%符号得到的浮点数余数部分并不遵循IEEE754标准的定义。IEEE754在计算余数时使用四舍五入除法,而不是截尾除法,因此余数的计算与整数的余数操作会有很大的不同。如果你的确想要IEEE754的余数,可以调用scala.Math里的IEEEremainder,例如:

  1. scala> Math.IEEEremainder(11.04.0)  
  2. res14: Double = -1.0 
数类型还提供了一元前缀+和-操作符(方法unary_+和unary_-),允许你指示文本数是正的还是负的,如-3或+4.0。如果你没有指定一元的+或-,文本数被解释为正的。一元符号+也存在只是为了与一元符号-相协调,不过没有任何效果。一元符号-还可以用来使变量变成负值。举例如下:

  1. scala> val neg = 1 + -3 
  2. neg: Int = -2 
  3. scala> val y = +3 
  4. y: Int = 3 
  5. scala> -neg  
  6. res15: Int = 2 
关系和逻辑操作

你可以用关系方法:大于(>),小于(< ),大于等于(>=)和小于等于(< =)比较数类型,像等号操作符那样,产生一个Boolean结果。另外,你可以使用一元操作符!(unary_!方法)改变Boolean值。以下是一些例子:

  1. scala> 1 > 2 
  2. res16: Boolean = false 
  3. scala> 1 <  2 
  4. res17: Boolean = true 
  5. scala> 1.0 < = 1.0 
  6. res18: Boolean = true 
  7. scala> 3.5f >= 3.6f  
  8. res19: Boolean = false 
  9. scala> 'a' >= 'A' 
  10. res20: Boolean = true 
  11. scala> val thisIsBoring = !true 
  12. thisIsBoring: Boolean = false 
  13. scala> !thisIsBoring  
  14. res21: Boolean = true 
逻辑方法,逻辑与(&&)和逻辑或(||),以中缀方式带Boolean操作数并产生Boolean结果。如:

  1. scala> val toBe = true 
  2. toBe: Boolean = true 
  3. scala> val question = toBe || !toBe  
  4. question: Boolean = true 
  5. scala> val paradox = toBe && !toBe  
  6. paradox: Boolean = false 
与Java里一样,逻辑与和逻辑或有短路:short-circuit的概念:用这些操作符建造的表达式仅评估最少能决定结果的部分。换句话说,逻辑与和逻辑或表达式的右手侧部分在左手侧部分能决定结果时就不再被评估了。举个例子,如果逻辑与表达式的左手侧计算结果为false,那么表达式的结果将注定是false,因此右手侧部分不再做评估。与之类似,如果逻辑或表达式的左手侧部分计算结果为true,那么表达式的结果将必然是true,于是右手侧部分不再被计算。下面是一些例子:

  1. scala> def salt() = { println("salt"); false }  
  2. salt: ()Boolean  
  3. scala> def pepper() = { println("pepper"); true }  
  4. pepper: ()Boolean  
  5. scala> pepper() && salt()  
  6. pepper  
  7. salt  
  8. res22: Boolean = false 
  9. scala> salt() && pepper()  
  10. salt  
  11. res23: Boolean = false 
***个表达式中,pepper和salt都被调用,但第二个里,只有salt被调用。因为salt返回false,所以就没必要调用pepper了。

注意

或许你会想知道如果操作符都只是方法的话短路机制是怎么工作的呢。通常,进入方法之前所有的参数都会被评估,因此方法怎么可能选择不评估他的第二个参数呢?答案是因为所有的Scala方法都有延迟其参数评估乃至取消评估的设置。

位操作符

Scala让你能够使用若干位方法对整数类型的单个位执行操作。有:按位与运算(&),按位或运算(|)和按位异或运算(^)。按位异或方法对它的操作数执行互斥或:exclusive or操作。一致的位产生0。差异的位产生1。因此0011 ^ 0101产生0110。一元按位取补操作符(~,方法unary_~),反转它的操作数的每一位。例如:

  1. scala> 1 & 2 
  2. res24: Int = 0 
  3. scala> 1 | 2 
  4. res25: Int = 3 
  5. scala> 1 ˆ 3 
  6. res26: Int = 2 
  7. scala> ~1 
  8. res27: Int = -2 
***个表达式,1 & 2,与运算了1(0001)和2(0010)的每一个位,并产生了0(0000)。第二个表达式,1 | 2,对同样的操作数的每一个位执行或运算,并产生3(0011)。第三个表达式,1 ^ 3,异或1(0001)和3(0011)的每一个位,产生2(0010)。***的表达式,~1,转换了1(0001)的每一个位,产生了-2,二进制看起来是1111 1111 1111 1111 1111 1111 1111 1111 1111 1110。

Scala整数类型还提供了三个位移方法:左移(< < ),右移(>>)和无符号右移(>>>)。使用在中缀操作符方式时,位移方法会按照右侧指定的整数值次数逐位移动左侧的整数。左移和无符号右移在移动的时候填入零。右移则在移动时填入左侧整数的***位(符号位)。举例如下:

  1. scala> -1 >> 31 
  2. res38: Int = -1 
  3. scala> -1 >>> 31 
  4. res39: Int = 1 
  5. scala> 1 < <  2 
  6. res40: Int = 4 

二进制的-1是1111 1111 1111 1111 1111 1111 1111 1111。***个例子里,-1 >> 31,-1被右移了31个位。由于Int包括32位,这个操作实际就是把最左侧的一位移到了最右侧。数字类型的最左侧位是符号位。如果最左侧位是1,数字就是负的,如果是0,数字就是正的。由于>>方法在不断右移的时候填入的是1,-1最左侧的一位是1,导致结果与原来左侧的数字一模一样,32位个1,或者说是-1。第二个例子里,-1 >>> 31,最左侧的位再一次不断向右移直至最右侧的位置,但是这次填入的是0。因此这次的结果是二进制的0000 0000 0000 0000 0000 0000 0000 0001,或者说是1。***一个例子里,1 < <  2,左操作数,1,被向左移动2个位置(填入0),产生结果是二进制的0000 0000 0000 0000 0000 0000 0000 0100,或者说是4。

【相关阅读】

  1. Scala的操作符:任何方法都可以是操作符
  2. Scala的基本类型及文本化
  3. Scala程序及其Application特质
  4. Scala程序中的分号推断和Singleton对象
  5. 学习Scala类的定义,字段和方法

责任编辑:book05 来源: Artima
相关推荐

2009-07-21 12:47:04

Scala私有字段定义操作符

2009-07-21 09:31:00

Scala操作符

2009-12-11 10:43:00

Scala讲座操作符函数

2010-07-14 14:55:07

Perl操作符

2009-07-21 08:41:05

Scala操作符优先级

2019-12-18 09:45:24

BashshellLinux

2009-08-19 17:26:28

C# 操作符

2023-10-12 09:58:45

操作符C++

2009-08-19 17:38:17

C# 操作符分类

2021-10-31 18:59:55

Python操作符用法

2010-01-28 11:16:28

C++操作符

2011-04-12 15:03:26

C语言编程位操作

2009-08-19 17:33:35

C# 操作符

2012-02-06 09:13:23

LINQ

2009-09-15 17:16:58

LINQ查询操作符

2009-09-16 09:09:23

Linq Contai

2010-07-14 14:18:51

Perl操作符

2024-01-07 20:15:49

Python编程语言

2009-08-21 09:30:05

is和as操作符

2010-07-13 11:11:39

Perl标量
点赞
收藏

51CTO技术栈公众号