一、基本數(shù)據(jù)類型
二、基本描述
bit --位:位是計算機中存儲數(shù)據(jù)的最小單位,指二進(jìn)制數(shù)中的一個位數(shù),其值為“0”或“1”。
byte --字節(jié):**字節(jié)是計算機存儲容量的基本單位,一個字節(jié)由8位二進(jìn)制數(shù)組成
一個byte的表現(xiàn)形式:
1000 0011
由8位0或1二進(jìn)制碼組成
其中第一位符號位表示正負(fù)數(shù),所以1000 0010 = 0* 2^0 + 1* 2^1 = -3
所以byte的最大值:0111 1111 ;因為111 1111再進(jìn)1位1000 0000=2^7,所以111 1111為2^7-1 = 127
為什么byte的最小值是-128
正整數(shù)表示:
0000 0001 - 0111 1111 ====》1-127
負(fù)整數(shù):
1000 0001 - 1111 1111 ====》-1-(-127)
零:
0000 0000
那還有一個數(shù):
1000 0000 ===》 -0表示啥呢?
-127 - 127的范圍表示了255個數(shù),但是八位二進(jìn)制數(shù)由256種可能。
即2的8次方
我們先來看二進(jìn)制數(shù)的計算:
2+1 = [0000_0010]原+[0000_0001]原=[0000_0011]原 = 3
1+-1=[0000_00001]原+[1000_0001]原=[1000_0010]原=-2
顯然計算的時候出現(xiàn)了問題,為什么?
補碼的來源
從上面的原碼表中可以看見左邊每增加一個二進(jìn)制單位對應(yīng)的真數(shù)是遞減的,而右邊每增加一個二進(jìn)制單位對應(yīng)的真數(shù)是遞增的,所以對于原碼來說,能滿足正數(shù)的加法,但無法滿足負(fù)數(shù)的加法
為了滿足負(fù)數(shù)對加法的需求,就必須讓負(fù)數(shù)與他對應(yīng)的二進(jìn)制碼是同步遞增或者同步遞減
眾所周知,減去一個數(shù)相當(dāng)于加上這個數(shù)的相反數(shù),這樣減法就轉(zhuǎn)換成了加法。
于是就通過符號位不變,其余位取反來滿足這個同步遞增或者遞減的要求,由于正數(shù)本來就滿足它本身的加法,所以不需要做任何改變。這就是反碼的定義由來。
從上圖的反碼表中可以看到在運算不跨過0的時候,正負(fù)數(shù)的加法已經(jīng)能滿足要求
-2+1=[1111_1101]反+[0000_0001]反=[1111_1110]反=-1
127+1=[1000_0000]反=-127=128 加法算出來是128,由于128超過最大值,余1,所以取最小值開始的第一位,也就是
最小值-127,但是這里有個不合理的地方,就是[1111_1111]和[0000_0000]都表示0,這導(dǎo)致在實際計算中每當(dāng)跨過0一次,就有一個單位的誤差
-1+2=[1111_1110]反+[0000_0010]反=[0000_0000]反=0
要解決這個問題就必須讓反碼中的[1111_1111]和[0000_0000]合并,由于[1111_1111]+[0000_0001]=[0000_0000],所以在負(fù)數(shù)反碼的基礎(chǔ)上+1就可以解決反碼中跨0的誤差問題,同時不會對負(fù)數(shù)與它對應(yīng)的二進(jìn)制反碼的同步遞增產(chǎn)生影響,所以在反碼的基礎(chǔ)上+1就完美的解決了符號參與預(yù)算的問題,這就是補碼為什么是在負(fù)數(shù)反碼的基礎(chǔ)上+1的由來。
回到原來的問題0000 0000 - 1111 1111表示了在-127 - 127的范圍,那么1000 0000 就可以用來表示-128
[-128~127] 剛好256個數(shù)值,即2的8次方。
其他類型的表示范圍也是以此類推。
在Java中整型、實型、字符型被視為簡單數(shù)據(jù)類型,這些類型由低級到高級分別為:
(byte,short,char)--int--long--float--double
整數(shù)比浮點數(shù)低級。低級到高級可以自動轉(zhuǎn)換。而高級到低級需要用代碼強制轉(zhuǎn)換,不強轉(zhuǎn)會編譯錯誤。
三、Char字符型
1.JAVA中,char占2字節(jié),16位。可在存放漢字
2.char賦值
char a='a'; //任意單個字符,加單引號。
char a='中';//任意單個中文字,加單引號。
char a=111;//整數(shù)。0~65535。十進(jìn)制、八進(jìn)制、十六進(jìn)制均可。輸出字符編碼表中對應(yīng)的字符。
注:只能放單個字符。
3、char運算
在JAVA中,對char類型字符可以與ASCII表對應(yīng)的數(shù)值來處理,可以做一些位運算
所以在遇到一些字符串查找字符等操作可以使用char對應(yīng)一個數(shù)值的特性來提高計算速度。
算法示例:
判定字符是否唯一
實現(xiàn)一個算法,確定一個字符串 s 的所有字符是否全都不同。
示例 1:
輸入: s = "leetcode"
輸出: false
示例 2:
輸入: s = "abc"
輸出: true
限制:
0 <= len(s) <= 100
如果你不使用額外的數(shù)據(jù)結(jié)構(gòu),會很加分。
思路
由于ASCII碼字符個數(shù)為128個,而且題目說了如果你不使用額外的數(shù)據(jù)結(jié)構(gòu),會很加分。因此可以使用兩個64位的long變量來存儲是否出現(xiàn)某個字符,二進(jìn)制位1表示出現(xiàn)過, 0表示未出現(xiàn)過。具體代碼如下:
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)
? 著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。
首先利用char字符的對應(yīng)ASCII碼數(shù)值特性切入,該題目涉及位運算,后面再學(xué)習(xí)補充。
四、浮點型
基礎(chǔ): IEEE754是現(xiàn)在公認(rèn)的、最廣泛使用的浮點數(shù)轉(zhuǎn)換運算標(biāo)準(zhǔn),所以要知道浮點型在計算機的表示方式需要知道IEEE754標(biāo)準(zhǔn)
知識點一:IEEE754單精度(32位)的二進(jìn)制排列規(guī)則:符號位S(1位,0為正數(shù),1為負(fù)數(shù)) + 階碼E(8位) + 尾數(shù)M(23位)
知識點二:單精度的偏置常數(shù)為127(固定值),階碼 = 127 + 階
知識點三:計算公式
s為符號位,Exponent為指數(shù)位,Sig為尾數(shù)為部分
float單精度、32位(4個字節(jié))
### double雙精度、64 位(8個字節(jié))
### float單精度計算轉(zhuǎn)化過程
以float單精度計算轉(zhuǎn)化為例:
-22.75轉(zhuǎn)二進(jìn)制碼
float a = -22.75的二進(jìn)制碼式什么
1.轉(zhuǎn)換整數(shù)部分:
22 = 10110
2.轉(zhuǎn)換小數(shù)部分:
.75 = .5 + .25 = .11(二進(jìn)制)
3.把兩部分組裝起來,變成標(biāo)準(zhǔn)化:
10110.11 = 1.100112^4*
4.轉(zhuǎn)換指數(shù)部分:
階碼 = 127 + 階
127 + 4 = 1000 0011(二進(jìn)制)
5.結(jié)果
1 <u>1000 0011</u> <u>10011</u> 00 0000 0000 0000 0000(二進(jìn)制)
二進(jìn)制 1011 11101 110 0000 0000 0000 0000 0000轉(zhuǎn)化為float是多少?
1. s = 1
2.Exponent = 011 11101
011 11101 = 125
125 - 127 = -2
3.Significand
float和double的一些總結(jié):
float:32位,數(shù)據(jù)范圍在3.4e-45~1.4e38,直接賦值時必須在數(shù)字后加上f或F
double:64位,數(shù)據(jù)范圍在4.9e-324~1.8e308,賦值時可以加d或D也可以不加
float、double兩種類型的最小值與Float.MIN_VALUE、 Double.MIN_VALUE的值并不相同,實際上Float.MIN_VALUE和Double.MIN_VALUE分別指的是 float和double類型所能表示的最小正數(shù)。也就是說存在這樣一種情況,0到±Float.MIN_VALUE之間的值float類型無法表示,0 到±Double.MIN_VALUE之間的值double類型無法表示。這并沒有什么好奇怪的,因為這些范圍內(nèi)的數(shù)值超出了它們的精度范圍。
Float和Double的最小值和最大值都是以科學(xué)記數(shù)法的形式輸出的,結(jié)尾的"E+數(shù)字"表示E之前的數(shù)字要乘以10的多少倍。比如3.14E3就是3.14×1000=3140,3.14E-3就是3.14/1000=0.00314。
五、引用類型
了解引用類型之前,可以先看一下Java運行時的內(nèi)存分配模型
Java把內(nèi)存分成兩種,一種叫做棧內(nèi)存,一種叫做堆內(nèi)存
- 在函數(shù)中定義的一些基本類型的變量和對象的引用變量都是在函數(shù)的棧內(nèi)存中分配。當(dāng)在一段代碼塊中定義一個變量時,java就在棧中為這個變量分配內(nèi)存空間,當(dāng)超過變量的作用域后,java會自動釋放掉為該變量分配的內(nèi)存空間,該內(nèi)存空間可以立刻被另作他用。
- 堆內(nèi)存用于存放由new創(chuàng)建的對象和數(shù)組。在堆中分配的內(nèi)存,由java虛擬機自動垃圾回收器來管理。
- 在堆中產(chǎn)生了一個數(shù)組或者對象后,還可以在棧中定義一個特殊的變量,這個變量的取值等于數(shù)組或者對象在堆內(nèi)存中的首地址,在棧中的這個特殊的變量就變成了數(shù)組或者對象的引用變量
堆內(nèi)存特點:
- 每一個 new 出來的東西都有地址值;
- 每個變量都有默認(rèn)值 (byte, short, int, long 的默認(rèn)值為 0;float, double 的默認(rèn)值為 0.0;char 的默認(rèn)值為 “\u0000”;boolean 的默認(rèn)值為 false;引用類型為 null);
- 使用完畢就變成垃圾,但是并沒有立即回收。會有垃圾回收器空閑的時候回收。
棧內(nèi)存特點:
- 局部變量:在方法的定義中或者在方法聲明上的變量稱為局部變量。
- 特點:棧內(nèi)存的數(shù)據(jù)用完就釋放。
所以引用變量存在兩個屬性:
- 引用變量本身的值,存儲在堆中
- 引用變量的在堆內(nèi)存中的地址指針變量,存儲在棧中
引用的過程:
用以下的代碼來看一下引用類型存儲模型與基本類型變量只存儲在棧的問題
package com.java.test;
public class MainTest {
public static void main(String[] args) {
Student s = new Student("小明",1);
int a = 10;
System.out.println("學(xué)生的信息如下: "+s.toString());
System.out.println("變量a的值="+a);
change(s,a);
System.out.println("調(diào)用方法后");
System.out.println("學(xué)生的信息如下: "+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;
}
}
運行結(jié)果:
關(guān)于IEEE754單精度(32位)的計算步驟(超詳細(xì))
關(guān)于IEEE754單精度(32位)的計算步驟(超詳細(xì))
JAVA中的幾種基本數(shù)據(jù)類型是什么,各自占用多少字節(jié)