JAVA基础复习-运算
二进制
机器数
一个数在计算机中的表现形式叫做机器数,这个数有正负之分,在计算机中用一个数的最高位(符号位)用来表示它的正负,其中0表示正数,1表示负数。
例如正数7,在计算机中用一个8位的二进制数来表示,是00000111,而负数-7,则用10000111表示,这里的00000111和10000111是机器数
真数
计算机中的机器数对应的真实的值就是真数,对最高位(符号位)后面的二进制数转换成10进制,并根据最高位来确定这个数的正负。对于上面的00000111和10000111来说,对最高位后面的二进制数转换成10进制是7,在结合最高位的值,得出对应的真数分别是7和-1
原码
用第一位表示符号,其余位表示值。因为第一位是符号位,所以8位二进制数的取值范围就是:[1111_1111 , 0111_1111] 即 [-127 , 127] ,原码是容易被人脑所理解的表达方式
反码
正数的补码反码是其本身,负数的反码是符号位保持不变,其余位取反。例如正数1的原码是[0000_0001],它的反码是是其本身
[0000_0001],-1的原码是[1000_0001],其反码是[1111_1110]
补码
正数的补码是其本身,负数的补码是在其反码的基础上+1,例如正数1的原码是[0000_0001],他的补码是其本身[0000_0001],
-1的补码是[1111_1111]
那么计算机为什么要使用补码呢?
首先,根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1+(-1), 所以计算机被设计成只有加法而没有减法, 而让计算机辨别”符号位”会让计算机的基础电路设计变得十分复杂,于是就让符号位也参与运算,从而产生了反码。
用反码计算, 出现了”0”这个特殊的数值, 0带符号是没有任何意义的。 而且会有[0000 0000]和[1000 0000]两个编码表示0。于是设计了补码, 负数的补码就是反码+1,正数的补码就是正数本身,从而解决了0的符号以及两个编码的问题: 用[0000 0000]表示0,用[1000 0000]表示-128。
注意-128实际上是使用以前的-0的补码来表示的, 所以-128并没有原码和反码。使用补码, 不仅仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数。 这就是为什么8位二进制, 使用补码表示的范围为[-128, 127]。
数据类型
1、整形
整形 byte > short > int > long 表数范围依此增大
byte 1个字节 -128-127
short 2个字节 正负3w
int 4个字节 正负21亿
long 8个字节 非常大
byte a = 129; //出错,损失精度。
byte b = (byte) (100+29);//那么这是时候会出错吗?
不会,结果为-127,那么为什么会出现这个原因呢?
我们知道数据在计算机内存中是以其补码的形式存在的,并且其最高位是一个符号位。两数相加计算出来的结果是一个4字节的int类型,当我们将一个4字节int类型强转成一个1个字节的byte类型时就会对其在内存中的数据进行裁剪。int类型的130转化为其在内存中的二进制补码为
00000000 00000000 00000000 10000001
将其进行强制转换成一个字节的byte类型后变成10000001
其中最高位的1为符号位,因此它表示的是一个负数,并且这是一个结果的补码形式,现在我们将其转为它的原码形式得到11111111(最高位还是符号为),结果的十进制就是-127。
2、浮点型
float double 表数范围依此增大
float和double只能用来做科学计算或者是工程计算,在商业计算中我们要用 java.math.BigDecimal
float 4字节
double 8字节
小数字面值 默认类型 double
= 在表数范围内赋值
尽量不要使用小数做比较
BigDecimal运算
/**
* 提供精确的加法运算。
* @param v1 被加数
* @param v2 加数
* @return 两个参数的和
*/
public static double add(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
/**
* 提供精确的减法运算。
* @param v1 被减数
* @param v2 减数
* @return 两个参数的差
*/
public static double sub(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
}
/**
* 提供精确的乘法运算。
* @param v1 被乘数
* @param v2 乘数
* @return 两个参数的积
*/
public static double mul(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
* 小数点以后10位,以后的数字四舍五入。
* @param v1 被除数
* @param v2 除数
* @return 两个参数的商
*/
public static double div(double v1,double v2){
return div(v1,v2,DEF_DIV_SCALE);
}
/**
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
* 定精度,以后的数字四舍五入。
* @param v1 被除数
* @param v2 除数
* @param scale 表示表示需要精确到小数点以后几位。
* @return 两个参数的商
*/
public static double div(double v1,double v2,int scale){
if(scale<0){
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 提供精确的小数位四舍五入处理。
* @param v 需要四舍五入的数字
* @param scale 小数点后保留几位
* @return 四舍五入后的结果
*/
public static double round(double v,int scale){
if(scale<0){
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(Double.toString(v));
BigDecimal one = new BigDecimal("1");
return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
}
如果需要保证精度,最好是不要使用BigDecimal的double参数的构造函数,因为存在损失double参数精度的可能,最好是使用BigDecimal的String参数的构造函数。最好是杜绝使用BigDecimal的double参数的构造函数。
3、数据类型之 布尔 boolean
boolean 1位 1/8字节
true false
常用于表达1分为2的事情 如性别
4、字符型 char '' 双字节
字符串 String "" 多个字符,字符序列
编译期 在表数范围内
char = int类型的字面值
char ch = 'a';//unicode存储可与整数互转
char x = 97;//a
char x = 65;//A
转义字符 :用于表达键盘不方便输入的值 \+一个字母
\n:换行
\t:tab
局部变量必须存在值才能使用(报错:可能尚未初始化变量)
属性是有默认值的 byte、short、int、long-->0
float、double -->0.0
引用类型-->null
/除 :不允许整数0作为除数。
允许小数0.0作为除数。
% :取余、模
++ -- :在自身的基础上加1或减1,只能用在变量上,不能用在常量、字面值、表达式上。
= :赋值,表数范围。特例,优化。
----------------------关系运算符-----------------------------------
> < >= <= != instance of返回boolean类型
== : 基本类型 比较内容
引用类型 比较的是地址
算数运算符不能用在boolean类型上
逻辑运算符 && || !
两个操作数只能为boolean类型
短路与、或,能判断就不计算后面的。
----------------------扩展运算符----------------------------------
+= -= *= /= %=
1、、组合算数与赋值
2、优化
例如:short s = 1;
s = s + 1; //是错误的 short<--(short+int)int
s += 1; //自动优化,强转
----------------------三目运算符----------------------------------
返回boolean表达式 ? 值1 :值2
true 求值1
false 求值2
----------------------其他运算符----------------------------------
位运算符 :& | ~ ^ << >> >>>
& 普通与
| 普通或
~ 取反
^ 异或: 相同为0,不同为1。任何整数^ 自己都是0
位运算符^的特点:一个数据对另一个数据位异或两次,该数本身不变。