计算机编程入门(3):变量_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > 计算机编程入门(3):变量

计算机编程入门(3):变量

 2015/5/12 18:42:31  std4453  程序员俱乐部  我要评论(0)
  • 摘要:貌似有很多人不满意呢……我写的不好请原谅,也请各位多多鼓励哈!第二章变量与运算2.1变量变量这个名字大家可能一点都不陌生,就比如说数学中的a,b,c就都是变量,可是当这个词被用于程序中时,就带上了一点点不同。再讲这个不同之前,我想先举一个例子。估计大家都知道最大公约数,也知道欧拉的辗转相除法,具体一点的算法如下所示:输入n,m0.如果n<m,则t<--m,m<--n,n<--t(交换m,n)1.r<--nmodm(n除以m的余数)2.如果r=0,结束,答案为m3
  • 标签:计算机 编程

貌似有很多人不满意呢……

我写的不好请原谅,也请各位多多鼓励哈!

?

第二章 变量与运算

?

2.1 变量

变量这个名字大家可能一点都不陌生,就比如说数学中的a,b,c就都是变量,可是当这个词被用于程序中时,就带上了一点点不同。

?

再讲这个不同之前,我想先举一个例子

估计大家都知道最大公约数,也知道欧拉的辗转相除法,具体一点的算法如下所示:

?

输入n,m

0.如果n<m,则t<--m,m<--n,n<--t(交换m,n)

1.r<--n mod m(n除以m的余数)

2.如果r=0,结束,答案为m

3.如果r不等于0,n<--m,m<--t

4.转至1.

(以上为简略写法,更标准的算法请见《计算机程序设计艺术》(The Art of Computer Programming)第一卷第一章)

?

如果你选择两个正整数带入运算,那么执行步骤的顺序可能是这样的:

0123412341234123412

很明显,执行步骤中出现了一个循环:1234

那么,当你尝试用一个算式(当然不用最大公约数的符号)来表达这个算法时,就会遇到这样一个问题:怎么把循环表达出来呢?

实际上一个算式(我指基础的加减乘除这些,什么求和,积分这些都不算)所做的操作是确定的,有限的,但是我们在生活学习中所遇到的问题并不总是确定的,有限的,就比如以上这个算法。

那么不可能说,万能的计算机程序连简单的最大公倍数都求不出来吧,那么我们用什么方法来实现这个算法呢?答案已经很明显了:变量。比如算法中写到的m,n,t,r就是变量的一些最简单的例子。

那么既然大家已经能够理解变量的基本意义了,就然我们在深入一点吧。

?

先来看一下前面求最大公约数的Java代码:

(见1.2节的说明,这段代码应该放在main函数中,还记得吗?)

class="java">int n=50;
int m=18;

int t;

if (n<m) {   //算法步骤0
    t=m;
    m=n;
    n=t;
}

int r;
while (true) {
    r=n%m;    //算法步骤1
    if (r==0)
        break;    //算法步骤2
    n=m;    //算法步骤3
    m=r;
}   //算法步骤4

System.out.println(m);

?稍微解释一下代码。

首先是n和m的输入,(这里是直接定义的,以后会学到从控制台读取的方法)然后看注释:从算法步骤0到4,根据算法对应着看,就不难理解:0不解释,1是计算余数,2是判断并(满足条件的话)退出循环,3是赋值(实际上也就是类似递归,把m,r作为输入,再次执行算法,以后会学到用递归来写这段代码),而4则是循环。

这里,变量的作用就是“应对不同输入”(指m,n)以及“作为临时存储” (指t,r)。

?

那么变量的作用大体上都有那些呢?

?

变量的作用

1.应对不同输入——一个算法总得有个输入输出,那么在程序中,告诉程序输入的值的方法就是使用变量。为了应对不确定的输入值,我们需要一个变量来储存输入的值。

2.作为临时存储——驾驶我们要交换两个变量,可是如果直接执行m=n;n=m;,由于先后问题,m和n的值并没有被正确的交换,毕竟两句语句在一起总有个先后(理论上可以有多线程,但故居没人无聊到用多线程去交换变量),因此我们需要一个临时变量:t。语句t=m;m=n;n=t;就能正确交换两个变量了。

3.减少计算量——当你想要画一个三角形并为此计算各个顶点的位置时,你将不可避免地使用根号三。但是在计算资源紧张的过去,计算一个根号3是一件开销很大的事,因此我们可能想用一个变量来代替根号三,比如:double sqrt3=Math.sqrt(3);。当然,你可能会说,可不可以直接计算出来呢?比如用1.732来代替每个根号3,不过,万一要多次计算的量是,比如说,3*m+sqrt(abs(Math.pow(exp(m),n%7)))这种东西呢?

4.扩大作用域——比如你有一个循环,你想记录循环的次数,那你可能会选择用一个定义在循环体外的变量来存储这个值。当然,用函数也可以,但这样势必会增大程序的复杂程度。

5.增强可读性——在一个长长的算式中,你可能会把自己搞糊涂,不知道算式代表的是什么意思,那么使用一些精心命名的变量可能有助于解决这个问题,比如说:

(我知道这个例子有点简单,但是我实在想不出太复杂的算式了)

n=(n&~(1<<m))|(1<<(32-m));

?能够把n的第m为值0,把n的第(32-m)位置1,但是给成这样或许会更好:

int setMTo0Mask=~(1<<m);
int set32MinusMTo1Mask=1<<(32-m);
n=(n&setMTo0Mask)|set32MinusMTo1Mask;

?

这些就是变量的基础运用,还有其他的一些运用会随着我们学习的脚步而出现,这里先列举一些:

获得引用;同一对象不同类型的表达形式;多线程间通讯;程序语言必要(比如Java的catch语句)等等。

?

变量与类型

在数学计算是可能不觉得,但是在计算机编程中类型是变量非常重要的一个属性,类型决定了变量储存了什么,可以怎么用。当然,实际的运行时,是没有类型之间的差异的,但类型对于正确地使用和管理变量是不可或缺的。比如说,要是不知道变量的类型,要怎么去知道一个变量储存了什么数据呢?要知道,计算机内部存储的永远只是二进制的1和0,具体代表了什么只有申明了他的类型才能得知。

当然,现在谈这些还为时过早,要学到了类和继承是变量的类型才真正变得重要起来。现在我们一定要了解的就是下面我要讲的内容:

?

重点!!!!

基础类型与转换

基础类型可以分为整数和实数两类,而整数中一般还分(这里都是普遍的高级语言)字节型(8位),字符型/短整型(16位),整形(32位),长整形(64位),实数分为单精度(32位)和双精度(64位)两种。当然,这些都是以Java为例,其他的语言可能有少许变化,但以现在的情况区别不大。

那么首先要讲一讲数在计算机中的储存方式。

1.整形:(注:高级内容,可跳过)

整形分有符号和无符号两种,Java中的char(字符型)是无符号的,其他都是有符号的。有符号数的格式是一位符号位,(位数-1)位数值位,而无符号数则没有符号位。有符号数在符号位为1的时候代表负数,其后的数值位是其绝对值的补码(即反码+1)。举个例子,8位的-1的二进制表示是11111111,-10是11110110,其中1110110是10(1010)的补码(0001010-->1110101-->1110110)。这种设计使得不管是有符号数还是无符号数的加法都可以简单的做二进制加法(当然会有溢出问题,我们后面再讨论)。而有符号数和无符号数之间的转换不用做任何处理(就是说,有无符号只是描述,本质一样,只是解析方法不同)。

那么不同位数的有符号数之间要怎么转换呢?如果是从位数高的向位数低的转换,就是直接截取低位数据,比如16位的1554(0000 0110 0001 0010)就会直接变成8位的18(0001 0010)。这是如果操作不当(或者有意为之),截尾后的数据就会发生变化。若是向位数高的转换,就要填充符号位。从m位的转向n位的(m<n),那么结果的第(m+1)位到第n位都用第m位的值填充。比如说,8位的-76(1001 0100)会变成16位的-76(1111 1111 1001 0100)。

(这段要认真看)

值得每一个程序员注意的整形问题有一下几种:

(1)溢出:8位的有符号数79(0100 1111)+8位有符号数65(0100 0001)=8位有符号数-112(1001 0000)。原因很简单,看下式:

? ? 0100 1111

+ ?0100 0001

-------------------

? ? 1001 0000

可是1001 0000的第一位是1,也就代表了他是一个负数,并不是我们所期望的79+65=144。(112+144=256=2^8,有兴趣的读者可以理解一下他的含义)

还有另外一种溢出方式:8位的无符号数104(0110 1000)+8位无符号数165(1010 0101)=8位无符号数13(0000 1101),而不是应得的269,原因见下式:

? ? 0110 1000 ? ? ? 104

+ ?1010 0101 ? ? ? 165

-----------------

(1)0000 1101 ? ? ? 13

头256被砍掉了,就只剩尾巴13了,于是我们就得到了269-256=13。

(2)截尾:就像我们刚刚说过的,16位的1554(0000 0110 0001 0010)向8位有符号数转换,会得到8位的18(0001 0010),数值发生了变化。在编程涉及到不同位数数据互相转换的时候,应该时刻注意数据范围,超出范围的数向低位转换时会出现我们所不期望的事。

(3)符号:8位有符号数-59(1100 0101)与无符号数197(1010 0101)数据虽然相同,但是只却截然不同。注意在同时使用有符号和无符号数,且数据值接近或大于有符号数的上限时,必须万分小心,以防出现上述情况。一个可靠的建议是使用范围更广的数据类型,比如上例用16位数据的话,有无符号就无所谓了。如果没有更大的数据类型,那我建议还是使用高精度算法(即不使用内置类型,使用数值对象)为妙。

2.浮点数

浮点数的具体存储方式较为复杂,不再详述,详见百度百科IEEE754标准。

值得注意的有那么几点:

(1)精度。举个例子,你现在有一个单精度浮点数10000000,后来你想咋它上面加上1,并且执行判断n+1==n(n和n+1是否相等) ,结果你惊奇的发现,答案竟然为真!瞎扯,n+1怎么可能等于n嘛!可惜的是,事实就是这样。实际上,单精度浮点数大悦有7位精度,超出7位精度的数值将不计算在内,因此,对于巨大的100000000来说,你小小的1就被无情地忽略掉了。唯一的解决方案就是使用更高的精度,比如双精度浮点数或者高精度算法,但是他们都有局限性。我的建议是在1也无比重要的地方使用精确值(分数,确切的算是,尽管对于超越数我们仍旧无能为力),或者使用精度足够高的高精度算法(比如1000位?应该够了)。其他地方就随他去吧,反正10^14分之一也不重要,用双精度好了。

(2)范围。实际上,虽然浮点数的最大值很高,但是还是有一个极限的。比如32位单精度的范围是1.401298E-45 到 3.4028235E+38(正数),然而1E+40他就无能为力了。当然,普通的计算中并不会碰到这么大的数字,但是一旦你的程序里会碰到大数字时,你就得小心了,浮点数的溢出是很可怕的。如果说整数溢出是可预计的(无非就是补码,截尾什么的),可浮点数的溢出是完全不可预计的,有时甚至和CPU内部的实现有关!

?

本节的最后我来说明一下Java中的变量申明与基础类型:

?申明变量:

<类型> <名称>(=<初始值>);

类型:该变量的类型

名称:该变量的名称,只能由a-z,A-Z,_,0-9这些字符组成,而且第一个字符不能是0-9

初始值:该变量初始的值,注意基础类型不一定要赋一个初始值,但是对象一定要赋一个值,对未赋值的对象进行操作会报错(编译都通不过)

?

基础类型表:

名称(Java) ? ?位数 ? ?对应的名称(C,32位) ? ?数值范围 ? ? ? ? ? ? ? ? ? ? ? ? 初始值

byte ? ? ? ? ? ? ? ? ? 8 ? ? ? ? signed byte ? ? ? ? ? ? ? ? ? ? ? -128~127 ? ? ? ? ? ? ? ? ? ? ? ?0

char ? ? ? ? ? ? ? ? ? 16 ? ? ? unsigned short ? ? ? ? ? ? ? ? ?0~65535 ? ? ? ? ? ? ? ? ? ? ? ? 0

short ? ? ? ? ? ? ? ? ?16 ? ? ? signed short ? ? ? ? ? ? ? ? ? ? ?-32768~32767 ? ? ? ? ? ? ? ?0

int ? ? ? ? ? ? ? ? ? ? ?32 ? ? ? signed int ? ? ? ? ? ? ? ? ? ? ? ? ?-2^31~2^31-1 ? ? ? ? ? ? ? ? ?0

long ? ? ? ? ? ? ? ? ? 64 ? ? ? signed long ? ? ? ? ? ? ? ? ? ? ? -2^63~2^63-1 ? ? ? ? ? ? ? ? ?0

boolean ? ? ? ? ? ? - ? ? ? ? ?bool (有的没有) ? ? ? ? ? ?true/false ? ? ? ? ? ? ? ? ? ? ? ?false

float ? ? ? ? ? ? ? ? ? 32 ? ? ? signed float ? ? ? ? ? ? ? ? ? ? ??-3.4028235E+38~3.4028235E+38,最小精度1.401298E-45 ? ? ? ? ? ? 0

double ? ? ? ? ? ? ? 64 ? ? ?signed double ? ? ? ? ? ? ? ? ? ?-1.79769313486231570E+308~1.79769313486231570E+308,最小精度-4.94065645841246544E-324 ? ? ? ? ? 0

?

习题

1.判断下列变量名是否合法:

123abcde ? ? ? ? ? ? __myJavaVariable

变量 ? ? ? ? ? ? ? ? ? ? value?integer

mMyVariable123 ?$$javaVariable

?

2.(选做)阅读IEEE 754标准,解释单、双精度浮点数最大值与最小精度的来源

?

3.写一段代码,轮换3个变量a,b,c的值。

?

4.解释辗转相除法程序中变量r的用途

发表评论
用户名: 匿名