如何处理数据

数据的运算

既然是“计算机”,那么其主要功能就是“计算”了。我们平时使用计算机打游戏、看电影、听音乐、上网、处理文档、科学研究等行为,本质上都是将各种问题转换成了计算的问题。
常用的计算包括算术运算、赋值运算、比较运算、逻辑运算、位运算等。表示运算的符号就是运算符。
下面我们来一一学习各种运算和对应的运算符。

算术运算

Java中的算术运算,是以加减乘除为基础的一些运算方法。包括:

运算符说明示例结果
+正号i=10; m=+i;m为10
-负号i=10; m=-i;m为-10
+8+412
-8-44
*8*432
\8\24
%取模(求余)9 % 41
++自增(变量前)i=4;m=++i;i为5,m为5
++自增(变量后)i=4;m=i++;i为5,m为4
自减(变量前)i=4;m=–i;i为3,m为3
自减(变量后)i=4;m=i–;i为3,m为4

大多数运算都和数学所学相同,不再赘述。着重介绍除法和自增自减运算。

注意:在Java中,实数(float和double类型)是可以进行取模操作的。

除法和求余

我们先来看一个程序(只显示主方法内的代码):

public class Arithmetic01 {
    public static void main(String[] args) {
        System.out.println("8/4="+8/4);//数学计算中结果为2,结果为2
        System.out.println("9/4="+9/4);//数学计算中结果为2.25,结果为2
        System.out.println("11/4="+11/4);//数学计算中结果为2.75,结果为2
        System.out.println("11.0/4="+11.0/4);//数学计算中结果为2.75,结果为2.75
        System.out.println("11%4="+11%4);//余数为3
        System.out.println("11.5%3.5="+11.5%3.5);//余数为1.0
    }
}

运行结果为:

8/4=2
9/4=2
11/4=2
11.0/4=2.75
11%4=3
11.5%3.2=1.0

通过这个程序,我们可以看到,8除以4结果为2,这符合我们的预期;但9除以4和11除以4,结果均只有整数部分,这就是整数除法的特点:整数除以整数,结果还是整数
如果我们希望得到期望中的小数,将除法运算中任何一个数改为实数类型即可。
这个特性是由计算机中整数的存储和处理方法决定的,因此我们在使用除法时一定要特别注意。
此外,在Java中,实数(float和double类型)是可以进行取模操作的。

自增和自减

自增、自减,顾名思义,就是为使用这个运算的变量自身增加1或者减少1。例如变量x原来的值是40,使用自增运算后,x的值为41;如果变量x原来的值是40,使用自减运算后,x的值为39。让上面的表中,最令人迷惑的就是:当自增|自减运算是其它运算的一部分时,变量和自增|自减运算的位置不同,会导致最终结果的不同。由于自增和自减的规则相同,所以下面这个例子中只使用了自增运算:

public class Arithmetic02 {
    public static void main(String[] args) {
        int x = 10;
        int y;
        System.out.println("x=" + x);//x的初始值为10
        x++;
        System.out.println("进行x++运算后,x=" + x);//自增运算一次,x值为11
        ++x;
        System.out.println("进行++x运算后,x=" + x);//再自增运算一次,x值为12
        //先提取x的值进行赋值运算,再进行自增运算
        System.out.println("x+++y=" + (x+++y)+",x="+x+",y="+y);
        //先进行自增运算,再提取x的值进行赋值运算
        System.out.println("++x+y=" + (++x+y)+",x="+x+",y="+y);

    }
}

运行结果是:

x=10,y=20
进行x++运算后,x=11
进行++x运算后,x=12
x+++y=32,x=13,y=20
++x+y=34,x=14,y=20

通过这个例子,不难总结:如果自增|自减运算是单独进行的,那么变量和运算符的位置关系不影响最终结果;如果自增|自减运算是其它运算中的一部分,那么变量在前面时,就先把变量的值代入到整个运算中,运算完毕后再进行自增|自减运算,运算符在前面时,就先进行自增|自减运算,然后把结果代入到整个运算中。

赋值运算

赋值运算我们一直在用,前面的程序中:int x=10;。这可不能读作“整型变量x等于10”,而是“把10赋给整型变量x”。这个=在数学上是“等号”,但在Java中是“赋值运算符”,它的作用是把运算符右边的赋给左边的变量。所以:

  • 赋值运算是从右向左进行的。a=a+1这样的代码在执行时,就会先把右边的变量a的值提取出来,加1,再将和存入到变量a中。同时,代码int a,b,c;a=b=c=10;是正确的,因为从右向左赋值;但int a=b=c=10;是错误的,因为10先赋给了c,但c还没有定义。
  • 右边必须是一个确定的值或能求出确定值的运算式,左边则必须、只能是个变量

为了简化代码,还有以下赋值运算符:

运算符说明示例相当于
+=加等于a+=3a=a+3
-=减等于a-=3a=a-3
*=乘等于a*=3a=a*3
\=除等于a\=3a=a\3
%=模等于a%=3a=a

02

 

比较运算

在Java中可以对两个数值进行大小比较,其结果为一个布尔值,true表示比较成立,false表示不成立。比较运算包括:

运算符说明示例结果
==等于50==23false
!=不等于50!=23true
>大于50>23true
<小于50<23true
>=大于等于50>=23true
<=小于等于50<=23true

大家可以编写并运行以下程序(只显示主要部分):

public class Compare {
    public static void main(String[] args) {
        System.out.println("50==23?"+(50==23));
        System.out.println("50!=23?"+(50!=23));
        System.out.println("50>23?"+(50>23));
        System.out.println("50<23?"+(50<23));
        System.out.println("50>=23?"+(50>=23));
        System.out.println("50<=23?"+(50<=23));
    }
}

结果为:

50==23?false
50!=23?true
50>23?true
50<23?false
50>=23?true
50<=23?false

逻辑运算

逻辑运算是针对逻辑值(布尔类型)的运算,其结果还是一个布尔类型的值。逻辑运算包括:

运算符说明示例结果
&和&&a&b(a&&b)当a和b均为true时,结果为true,其他情况均为false
| 和 ||a|b(a||b)当a和b均为false时,结果为false,其他情况均为true
!!a取相反值,a为true时,!a为false;a为false时,!a为true
^异或a^ba、b值相同时为false,不相同时为true

与和或运算均出现了两个符号。其中,&和|中包含其它运算时,所有的运算都会被执行;&&和||中包含其它运算时,如果在不完成所有运算的情况下就能得出结论,那么不再执行剩下的运算。
由于短路与和短路或情况类似,我们这里只看短路或的例子。对于短路与,大家可以编写下面的程序:


public class LogicDemo {
    public static void main(String[] args) {
        int a=100;
        int b=200;
        boolean c=true;
        boolean d=false;
        System.out.println("逻辑或:"+(c|d));
        System.out.println("逻辑与:"+(c&d));
        System.out.println("逻辑异或:"+(c^d));
        System.out.println("逻辑非:"+(!c));
        System.out.println("使用普通或运算:");
        System.out.println((a>20)|(++b>500));//a>20值为true,++b>500值为false,同时b自增1,结果为true
        System.out.println("b="+b);//输出b的值,为201
        System.out.println("使用短路或运算:");
        System.out.println("计算(a>20)||(++b>500):"+((a>20)||(++b>500)));//a>20值为true,此时已经可以确定最终结果,++b>500没有执行
        System.out.println("b="+b);//输出b的值,为201
        System.out.println("计算(a<20)||(++b>500):"+((a<20)||(++b>500)));//a<20值为false,此时不能确定最终结果,++b>500需要执行
        System.out.println("b="+b);//输出b的值,为202
    }
}

运行结果为:

逻辑或:true
逻辑与:false
逻辑异或:true
逻辑非:false
使用普通或运算:
true
b=201
使用短路或运算:
计算(a>20)||(++b>500):true
b=201
计算(a<20)||(++b>500):false
b=202

其它运算大家可以自己写程序进行验证和练习。

位运算

位运算只能用于整型数据,而且只能在二进制层面进行运算。整型数据在计算机中是以二进制形式存储,位运算也是针对二进制数据进行的运算。主要包括:

运算符说明示例结果
&按位与a&b参与运算的两位都是1,结果为1,其余为0
|按位或a|b参与运算的两位都是0,结果为0,其余为1
~取反~a1变为0,0变为1
^异或a^b参与运算的两位相同为0,不同为1
<<左移a<<2二进制数据向左移动2位,右端补0
>>右移a>>2二进制数据向右移动2位,正数左端补0,负数补1
>>>无符号右移a>>>2二进制数据向右移动2位,无论正负均补0

在与、或、异或的位运算中,参与运算的两个数必须是二进制形式,右对齐,左边不足补0,从右向左进行计算。例如:

  10011001
& 00001101
----------
  00001001

取反时,将二进制的1转换为0,0转换为1。需要注意的是,由于正整数和负整数在内存中的表示方法不同,对十进制的整数1进行取反操作,结果是-2,而不是0。
左移时,将最左边的数据移出变量的存储空间,右侧补0。如果左移时,没有1被移出存储空间,每左移一位,就相当于乘以一次2。
右移时,将最右边的数据移出变量的存储空间,但由于最左边那一位是符号位,左边补0还是1,产生两种处理方式:一是正数补0,负数补1,即>>;二是无论正负,一律补0,即>>>
大家可以编写并运行以下程序,思考一下具体执行过程:

public class BitOperate {
    public static void main(String[] args) {
        int a=1;//二进制形式为01,省略了前面30字位的0
        int b=3;//二进制形式为11,省略了前面30字位的0
        System.out.println("a&b="+(a&b));//01&11=01,十进制的1
        System.out.println("a|b="+(a|b));//01|11=11,十进制的3
        System.out.println("a^b="+(a^b));//01^11=10,十进制的2
        System.out.println("~a="+(~a));//~01=10,前面30字位的0也要取反为1,所以实际答案是11111111111111111111111111111110,-2
        System.out.println("a<<2="+(a<<2));//a左移两位,为4
        System.out.println("-a<<2="+((-a)<<2));//-a,即-1左移两位,为-4
        System.out.println("b>>1="+(b>>1));//b右移1位,为1
        System.out.println("-b>>1="+((-b)>>1));//-b右移1位,为-2
        System.out.println("b>>>1="+(b>>>1));//b无符号右移1位,为1
        System.out.println("-b>>>1="+((-b)>>>1));//-b无符号右移1位,为2147483646
    }
}

条件运算

Java中还有一个条件运算,也是Java唯一一个三目运算符(这个运算涉及到三个参数)。它的格式是:表达式1?表达式2:表达式3
表达式1必须是逻辑表达式——其自身或者运算结果必须是个逻辑值,true或者false。如果表达式1的值是true,整个运算的结果就是表达式2的值;如果表达式1的值是false,整个运算的结果就是表达式3的值。也就是说,条件运算可以根据条件的不同(表达式1的值),来产生不同的结果(表达式2和表达式3的值)。
我们来看这个程序:

public class SelectiveOperation {
    public static void main(String[] args) {
        int a=300;
        int b=500;
        byte score=90;
        System.out.println("a和b中:"+(a>b?"a比较大":"b比较大"));
        System.out.println("你的考试成绩:"+(score>=60?"及格":"不及格"));
    }
}

02

 

数据类型转换

之前我们提到,9/4=2,这是由于计算机中不同数据类型的保存和处理方法是不同的。这就带来一个问题,当不同类型的数据放到一起进行运算时,该如何处理?
答案是通过数据类型转换,把不同类型的数据转换为相同的数据类型,再进行运算。
具体转换方法这里不进行深入探讨,我们主要学习在什么情况下使用哪种转换方式。
在Java中,有两种数据类型转换方式:自动类型转换和强制类型转换。

自动类型转换

顾名思义,不需要我们手工干预就可以完成。一般来说,当两个不同类型的数据在一起运算时,表示范围小、精度低的数据类型会转换为表示范围大、精度高的类型。
转换规律为:
(byte,short,char)–>int–>long–>float–>double
byte,short和char三种类型都会转换为int类型——即使运算中不包含int类型时也是如此,例如两个short类型数据在一起运算。

强制类型转换

我们有时需要手工指定转换目标,例如把表示范围大、精度高的类型转换为范围小、精度低的类型。转换方法:(目标数据类型)转换对象,例如:(int)3.14;这会把3.14(double类型)强制转换为int类型,结果为3。
不过有时也需要强制把表示范围小、精度低的类型会转换为表示范围大、精度高的类型,例如在计算平均分时,我们需要用总分除以人数。人数必然是整数,分数很多时候也是分数,很容易在无意间写成两个整数相除,结果必然还是整数。我们可以把计算平均分的方法写成:

//avg方法用于计算平均分,sum表示总分,num表示人数
double avg(int sum,int num){
    return (double)sum/num;
}

在这个方法中,sum会被强制转换为double类型,那么结果自然也是double类型了。

需要注意的是:除了=之外的所有赋值运算符,都会在需要时自动进行强制类型转换。如:

    short s=50;
    int i=100;
    s+=i;

我们看这个对类型转换进行总结的程序:

public class DTConversion {
    public static void main(String[] args) {
        //整数的自动类型转换
        byte b=34;
        short s=23;
        s=(short)(s+b);//自动转换时,short数据和byte数据相加,会转换为int数据,所以不能直接赋值给short变量
        System.out.println("自动进行强制转换:"+(s+=b));//这种形式的赋值运算会自动进行强制转换
        System.out.println("不转换:"+(12/5));
        System.out.println("自动类型转换:"+(12.0/5));
        System.out.println("强制类型转换:"+((double)12/5));
        System.out.println("强制转换可能会导致精度损失:"+(int)12.5);
    }
}

运算符的优先级

Java中包含了很多运算符,当这些运算符在同一个运算式中时,必须规定执行顺序,这就是优先级。Java中运算符的优先级是这样规定的:

优先级运算符结合性
1.、()、[]、{}从左向右
2!、+、-、~、++、–从右向左
3*、/、%从左向右
4+、-(正负号)从左向右
5<<、 >>、 >>>从左向右
6<、 <=、 >、>=、instanceof从左向右
7==、!=从左向右
8&从左向右
9^从左向右
10|从左向右
11&&从左向右
12||从左向右
13?:从右向左
14=、+=、-=、*=、/=、%=、<<=、>>=、>>>=、&=、~=、^=、|=从右向左

由于小括号的优先级非常高,因此,如果暂时记不住这个表,那么可以用小括号把需要先计算的部分括起来。但仍需要通过记忆和练习,记住他们的优先级的。

02

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值