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]。

数据类型

JAVA基础复习-运算

 

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

位运算符^的特点:一个数据对另一个数据位异或两次,该数本身不变。

JAVA基础复习-运算