Java基本数据类型(为什么byte最小值是-128,float二进制转化过程)

一、基本数据类型

image-20200721002249505

二、基本描述

bit --位:位是计算机中存储数据的最小单位,指二进制数中的一个位数,其值为“0”或“1”。
byte --字节:**字节是计算机存储容量的基本单位,一个字节由8位二进制数组成

一个byte的表现形式:

1000 0011

由8位0或1二进制码组成

其中第一位符号位表示正负数,所以1000 0010 = 0* 2^0 + 1* 2^1 = -3

image-20200722220821760

所以byte的最大值:0111 1111 ;因为111 1111再进1位1000 0000=2^7,所以111 1111为2^7-1 = 127

为什么byte的最小值是-128

正整数表示:

0000 0001 - 0111 1111 ====》1-127

负整数:

1000 0001 - 1111 1111 ====》-1-(-127)

零:

0000 0000

那还有一个数:

1000 0000 ===》 -0表示啥呢?

-127 - 127的范围表示了255个数,但是八位二进制数由256种可能。

即2的8次方

我们先来看二进制数的计算:

img

2+1 = [0000_0010]原+[0000_0001]原=[0000_0011]原 = 3

1+-1=[0000_00001]原+[1000_0001]原=[1000_0010]原=-2

显然计算的时候出现了问题,为什么?

补码的来源

从上面的原码表中可以看见左边每增加一个二进制单位对应的真数是递减的,而右边每增加一个二进制单位对应的真数是递增的,所以对于原码来说,能满足正数的加法,但无法满足负数的加法

为了满足负数对加法的需求,就必须让负数与他对应的二进制码是同步递增或者同步递减

众所周知,减去一个数相当于加上这个数的相反数,这样减法就转换成了加法。

于是就通过符号位不变,其余位取反来满足这个同步递增或者递减的要求,由于正数本来就满足它本身的加法,所以不需要做任何改变。这就是反码的定义由来。

img

从上图的反码表中可以看到在运算不跨过0的时候,正负数的加法已经能满足要求

-2+1=[1111_1101]反+[0000_0001]反=[1111_1110]反=-1

127+1=[1000_0000]反=-127=128 加法算出来是128,由于128超过最大值,余1,所以取最小值开始的第一位,也就是

最小值-127,但是这里有个不合理的地方,就是[1111_1111]和[0000_0000]都表示0,这导致在实际计算中每当跨过0一次,就有一个单位的误差

-1+2=[1111_1110]反+[0000_0010]反=[0000_0000]反=0

要解决这个问题就必须让反码中的[1111_1111]和[0000_0000]合并,由于[1111_1111]+[0000_0001]=[0000_0000],所以在负数反码的基础上+1就可以解决反码中跨0的误差问题,同时不会对负数与它对应的二进制反码的同步递增产生影响,所以在反码的基础上+1就完美的解决了符号参与预算的问题,这就是补码为什么是在负数反码的基础上+1的由来。


img

回到原来的问题0000 0000 - 1111 1111表示了在-127 - 127的范围,那么1000 0000 就可以用来表示-128

[-128~127] 刚好256个数值,即2的8次方。

其他类型的表示范围也是以此类推。

在Java中整型、实型、字符型被视为简单数据类型,这些类型由低级到高级分别为:

(byte,short,char)--int--long--float--double

整数比浮点数低级。低级到高级可以自动转换。而高级到低级需要用代码强制转换,不强转会编译错误。

三、Char字符型

1.JAVA中,char占2字节,16位。可在存放汉字

2.char赋值

char a='a'; //任意单个字符,加单引号。

char a='中';//任意单个中文字,加单引号。

char a=111;//整数。0~65535。十进制、八进制、十六进制均可。输出字符编码表中对应的字符。

注:只能放单个字符

3、char运算

在JAVA中,对char类型字符可以与ASCII表对应的数值来处理,可以做一些位运算

所以在遇到一些字符串查找字符等操作可以使用char对应一个数值的特性来提高计算速度。

算法示例:

判定字符是否唯一

实现一个算法,确定一个字符串 s 的所有字符是否全都不同。

示例 1:

输入: s = "leetcode"
输出: false
示例 2:

输入: s = "abc"
输出: true
限制:

0 <= len(s) <= 100
如果你不使用额外的数据结构,会很加分。

思路
由于ASCII码字符个数为128个,而且题目说了如果你不使用额外的数据结构,会很加分。因此可以使用两个64位的long变量来存储是否出现某个字符,二进制位1表示出现过, 0表示未出现过。具体代码如下:

    public boolean isUnique(String astr) {
        long low64 = 0;
        long high64 = 0;

        for (char c : astr.toCharArray()) {
            if (c >= 64) {
                long bitIndex = 1L << c - 64;
                if ((high64 & bitIndex) != 0) {
                    return false;
                }

                high64 |= bitIndex;
            } else {
                long bitIndex = 1L << c;
                if ((low64 & bitIndex) != 0) {
                    return false;
                }

                low64 |= bitIndex;
            }

        }

        return true;
    }


​ 作者:yuruiyin
​ 链接:https://leetcode-cn.com/problems/is-unique-lcci/solution/java-wei-yun-suan-by-npe_tle-2/
​ 来源:力扣(LeetCode)
​ 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

首先利用char字符的对应ASCII码数值特性切入,该题目涉及位运算,后面再学习补充。

四、浮点型

基础: IEEE754是现在公认的、最广泛使用的浮点数转换运算标准,所以要知道浮点型在计算机的表示方式需要知道IEEE754标准

知识点一:IEEE754单精度(32位)的二进制排列规则:符号位S(1位,0为正数,1为负数) + 阶码E(8位) + 尾数M(23位)

知识点二:单精度的偏置常数为127(固定值),阶码 = 127 + 阶

知识点三:计算公式

img

s为符号位,Exponent为指数位,Sig为尾数为部分

float单精度、32位(4个字节)

img

### double双精度、64 位(8个字节)

img

### float单精度计算转化过程

以float单精度计算转化为例:

-22.75转二进制码

float a = -22.75的二进制码式什么

1.转换整数部分:

22 = 10110

2.转换小数部分:
.75 = .5 + .25 = .11(二进制)

3.把两部分组装起来,变成标准化:
10110.11 = 1.100112^4*

4.转换指数部分:

阶码 = 127 + 阶

127 + 4 = 1000 0011(二进制)

5.结果
1 <u>1000 0011</u> <u>10011</u> 00 0000 0000 0000 0000(二进制)

二进制 1011 11101 110 0000 0000 0000 0000 0000转化为float是多少?

1. s = 1

2.Exponent = 011 11101

011 11101 = 125

125 - 127 = -2

3.Significand

img
4.Repersents:-1.75(十进制)2^(-2) = -0.4375*

float和double的一些总结:

float:32位,数据范围在3.4e-45~1.4e38,直接赋值时必须在数字后加上f或F

double:64位,数据范围在4.9e-324~1.8e308,赋值时可以加d或D也可以不加

float、double两种类型的最小值与Float.MIN_VALUE、 Double.MIN_VALUE的值并不相同,实际上Float.MIN_VALUE和Double.MIN_VALUE分别指的是 float和double类型所能表示的最小正数。也就是说存在这样一种情况,0到±Float.MIN_VALUE之间的值float类型无法表示,0 到±Double.MIN_VALUE之间的值double类型无法表示。这并没有什么好奇怪的,因为这些范围内的数值超出了它们的精度范围。

Float和Double的最小值和最大值都是以科学记数法的形式输出的,结尾的"E+数字"表示E之前的数字要乘以10的多少倍。比如3.14E3就是3.14×1000=3140,3.14E-3就是3.14/1000=0.00314。

五、引用类型

了解引用类型之前,可以先看一下Java运行时的内存分配模型

image-20200721233515255

Java把内存分成两种,一种叫做栈内存,一种叫做堆内存

  • 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用。
  • 堆内存用于存放由new创建的对象和数组。在堆中分配的内存,由java虚拟机自动垃圾回收器来管理。
  • 在堆中产生了一个数组或者对象后,还可以在栈中定义一个特殊的变量,这个变量的取值等于数组或者对象在堆内存中的首地址,在栈中的这个特殊的变量就变成了数组或者对象的引用变量

堆内存特点

  • 每一个 new 出来的东西都有地址值;
  • 每个变量都有默认值 (byte, short, int, long 的默认值为 0;float, double 的默认值为 0.0;char 的默认值为 “\u0000”;boolean 的默认值为 false;引用类型为 null);
  • 使用完毕就变成垃圾,但是并没有立即回收。会有垃圾回收器空闲的时候回收。

栈内存特点

  • 局部变量:在方法的定义中或者在方法声明上的变量称为局部变量。
  • 特点:栈内存的数据用完就释放。

所以引用变量存在两个属性:

  • 引用变量本身的值,存储在堆中
  • 引用变量的在堆内存中的地址指针变量,存储在栈中

引用的过程:

img
图片来源 Java 中的内存分配

用以下的代码来看一下引用类型存储模型与基本类型变量只存储在栈的问题

package com.java.test;

public class MainTest {
    public static void main(String[] args) {
        Student s = new Student("小明",1);
        int  a = 10;
        System.out.println("学生的信息如下: "+s.toString());
        System.out.println("变量a的值="+a);
        change(s,a);
        System.out.println("调用方法后");
        System.out.println("学生的信息如下: "+s.toString());
        System.out.println("变量a的值="+a);

    }
    static void change(Student s, int a) {
        a=a-10;
        s.setAge(1);
        s.setName("大明");
    }


}

class Student{
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

运行结果:

image-20200721235709306

Java 八大基本数据类型

关于IEEE754单精度(32位)的计算步骤(超详细)

关于计算机中补码的问题

关于IEEE754单精度(32位)的计算步骤(超详细)

JAVA中的几种基本数据类型是什么,各自占用多少字节

Java中的八种基本数据类型所占字节的求法

Java 中的内存分配

计算机原码,反码,补码

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容