【转载】计算机程序的思惟逻辑 (3) - 基本运算

运算html

第一节咱们谈了经过变量定义数据,上节咱们介绍了给数据赋值,有了初始值以后,能够对数据进行运算。计算机之因此称为"计算"机,是由于发明它的主要目的就是运算。运算有不一样的类型,不一样的数据类型支持的运算也不同,本文介绍Java中基本类型数据的主要运算。程序员

  • 算术运算:主要是平常的加减乘除
  • 比较运算:主要是平常的大小比较
  • 逻辑运算:针对布尔值进行运算

算术运算swift

算术运算符有加减乘除,符号分别是+-*/,另外还有取模运算符%,以及自增(++)和自减(--)运算符。取模运算适用于整数和字符类型,其余算术运算适用于全部数值类型和字符类型,其余都符合常识,但字符类型看上去比较奇怪,后续文章解释。c#

减号(-)一般用于两个数相减, 但也能够放在一个数前面,例如 -a, 这表示改变a的符号,原来的正数会变为负数,原来的负数会变为正数,这也是符合咱们常识的。数组

取模(%)就是数学中的求余数,例如,5%3是2,10%5是0。spa

自增(++)和自减(--),是一种快捷方式,是对本身进行加一或减一操做。设计

加减乘除大部分状况和直观感受是同样的,都很容易理解,但有一些须要注意的地方,而自增自减稍微复杂一些,下面咱们解释下。code

加减乘除注意事项htm

运算时要注意结果的范围,使用恰当的数据类型。两个正数均可以用int表示,但相乘的结果可能就会超,超出后结果会使人困惑,例如:对象

int a = 2147483647*2; //2147483647是int能表示的最大值

a的结果是-2。为何是-2咱们暂不解释,要避免这种状况,咱们的结果类型应使用long,但只改成long也是不够的,由于运算仍是默认按照int类型进行,须要将至少一个数据表示为long形式,即在后面加L或l,下面这样才会出现指望的结果:

long a = 2147483647*2L;

另外,须要注意的是,整数相除不是四舍五入,而是直接舍去小数位,例如:

double d = 10/4;

结果是2而不是2.5,若是要按小数进行运算,须要将至少一个数表示为小数形式,或者使用强制类型转化,即在数字前面加(double),表示将数字看作double类型,以下所示任意一种形式均可以:

double d = 10/4.0;
double d = 10/(double)4;

以上一些注意事项,我想也没什么特别的理由,大概是方便语言设计者实现语言吧。

小数计算结果不精确

不管是使用float仍是double,进行运算时都会出现一些很是使人困惑的现象,好比:

float f = 0.1f*0.1f;
System.out.println(f);

 这个结果看上去,不言而喻,应该是0.01,但实际上,屏幕输出倒是0.010000001,后面多了个1。换用double看看:

double d = 0.1*0.1;
System.out.println(d);

屏幕输出0.010000000000000002,一连串的0以后多了个2,结果也不精确。

这是怎么回事?看上去这么简单的运算,计算机怎么能计算不精确呢?但事实就是这样,究其缘由,咱们须要理解float和double的二进制表示,后续文章进行分析。

自增(++)/自减(--)

自增/自减是对本身作加一和减一操做,但每一个都有两种形式,一种是放在变量后,例如a++, a--,另外一种是放在变量前,例如++a, --a。

若是只是对本身操做,这两种形式也没什么差异,区别在于还有其余操做的时候。放在变量后(a++),是先用原来的值进行其余操做,而后再对本身作修改,而放在变量前(++a),是先对本身作修改,再用修改后的值进行其余操做。例如,快捷运算和其等同的运算分别是:

快捷运算 等同运算
b=a++-1

b=a-1

a=a+1

c = ++a-1

a=a+1

c=a-1

arrA[i++]=arrB[++j]

j=j+1

arrA[i]=arrB[j]

i=i+1

自增/自减是"快捷"操做,是让程序员少写代码的,但遗憾的是,因为比较奇怪的语法和诡异的行为,带给了初学者一些困惑。

比较运算

比较运算就是计算两个值之间的关系,结果是一个布尔类型(boolean)的值。比较运算适用于全部数值类型和字符类型。数值类型容易理解,但字符怎么比呢?后续文章解释。

比较操做符有:大于(>),大于等于(>=),小于(<),小于等于(<=),等于(==),不等于(!=)。

大部分也都是比较直观的,须要注意的是等于。

首先,它使用两个等号==,而不是一个等号(=),为何不用一个等号呢?由于一个等号(=)已经被占了,表示赋值操做。

另外,对于数组,==判断的是两个数组是否是同一个数组,而不是两个数组的元素内容是否同样,即便两个数组的内容是同样的,但若是是两个不一样的数组,==依然会返回false,以下所示:

int[] a = new int[] {1,2,3};
int[] b = new int[] {1,2,3};

// a==b的结果是false

若是须要比较数组的内容是否同样,须要逐个比较里面存储的每一个元素。

逻辑运算

逻辑运算根据数据的逻辑关系,生成一个布尔值true或者false。逻辑运算只可应用于boolean类型的数据,但比较运算的结果是布尔值,因此其余类型数据的比较结果可进行逻辑运算。

逻辑运算符具体有:

  • 与(&):两个都为true才是true,只要有一个是false就是false
  • 或(|):只要有一个为true就是true,都是false才是false
  • 非(!):针对一个变量,true会变成false, false会变成true
  • 异或(^):两个相同为false, 两个不相同为true
  • 短路与(&&): 和&相似,不一样之处立刻解释
  • 短路或 (||):与|相似,不一样之处立刻解释

逻辑运算的大部分都是比较直观的,须要注意的是&和&&,以及|和||的区别。若是只是进行逻辑运算,它们也都是相同的,区别在于同时有其余操做的状况下,例如:

boolean a = true;
int b = 0;
boolean flag = a | b++>0; 

由于a为true,因此flag也为true,但b的结果为1,由于|后面的式子也会进行运算,即便只看a已经知道flag的结果,仍是会进行后面的运算。而||则不一样,若是最后一句的代码是:

boolean flag = a || b++>0; 

则b的值仍是0,由于||会"短路",即在看到||前面部分就能够断定结果的状况下,忽略||后面的运算。

这个例子咱们还能够看出,自增/自减操做带给咱们的困扰,别的操做都干干脆脆,赋值就赋值,加法就加法,比较就比较,它非混在一块儿,可能会少写些代码,但若是使用不当,会使理解困难不少。

运算符优先级

一个稍微复杂的运算可能会涉及多个变量,和多种运算,那哪一个先算,哪一个后算呢?程序语言规定了不一样运算符的优先级,有的会先算,有的会后算,大部分状况下,这个优先级与咱们的常识理解是相符的。

但在一些复杂状况下,咱们可能会搞不明白其运算顺序。但这个咱们不用太操心,可使用括号()来表达咱们想要的顺序,括号里的会先进行运算,简单的说,不肯定顺序的时候,就使用括号。

序列号

符号

名称

结合性(与操做数)

目数

说明

1

.

从左到右

双目

 

( )

圆括号

从左到右

 

 

[ ]

方括号

从左到右

 

 

2

+

正号

从右到左

单目

 

-

负号

从右到左

单目

 

++

自增

从右到左

单目

前缀增,后缀增

- -

自减

从右到左

前缀减,后缀减

~

按位非/取补运算

从右到左

单目

 

逻辑非

从右到左

单目

!”不能够与“=”联用

3

*

从左到右

双目

 

/

从左到右

双目

整数除法:取商的整数部分,小数部分去掉,不四舍五入

%

取余

从左到右

双目

 

4

+

从左到右

双目

 

-

从左到右

双目

 

5

<< 

左移位运算符

从左到右

双目

 

>> 

带符号右移位运算符

从左到右

双目

 

>>> 

无符号右移

从左到右

双目

 

6

小于

从左到右

双目

关系运算符“大于”说明

<=

小于或等于

从左到右

双目

 

大于

从左到右

双目

 

>=

大于或等于

从左到右

双目

 

instanceof

肯定某对象是否属于指定的类

从左到右

双目

 

7

==

等于

从左到右

双目

关系运算符“==”说明

!=

不等于

从左到右

双目

 

8

&

按位与

从左到右

双目

 

9

|

按位或

从左到右

双目

 

10

^

按位异或

从左到右

双目

 

11

&&

短路与

从左到右

双目

 

12

||

短路或

从左到右

双目

 

13

? :

条件运算符

从右到左

三目

 

14

=

赋值运算符

从右到左

双目

 

+=

混合赋值运算符

 

-=

 

*=

 

/=

 

%=

 

&=

 

|=

 

^=

 

<<=

 

>>=

 

>>>=

 

小结

本节咱们介绍了算术运算,比较运算和逻辑运算,但咱们遗留了一些问题,好比:

  • 正整数相乘的结果竟然出现了负数
  • 很是基本的小数运算结果竟然不精确
  • 字符类型怎么也能够进行算术运算和比较 

这是怎么回事呢?

相关文章
相关标签/搜索