前言:java
本文主要介紹java基礎類型的二進制轉換和二進制的基本概念。算法
二進制:數組
1,二進制是以0和1爲碼,逢2進1,好比3=11=1*2+1。工具
2,在計算機當中其它進制的算法基本基於2進制,由於計算機只認識0和1,好比16進制數則意味着一位16進制碼由4位2進制碼數表示。測試
3,在Java語言中byte表明最小計量單位,byte由8位2進制數組成。編碼
Java基本數據類型與表示範圍(boolean忽略)spa
1,byte(整型):8位,short(整型):16位,char(字符型):16位,int(整型):32位,float(浮點型單精度):32位,long(整型):64位,double(浮點型雙精度):64位。code
2,直接按位作比例運算,一個short數字或char字符可有兩個byte數字表示,一個float或int數字可由4個byte數字表示,一個long或double數字可由8個byte數字表示。blog
3,以2進制數表示範圍計算獲得各整型數值表示範圍,每種數值類型的最大表示範圍能夠經過包裝類的靜態屬性取到,好比Integer.MAX_VALUE。utf-8
4,char類型是最具話題性的數據類型,它承擔着整個語言世界的符號通通轉換稱爲計算機所認識的編碼格式的重任,關於字符集和編碼包含了不少概念也帶來了不少問題。
二進制與編碼
通常對英文字符而言,一個字節表示一個字符,可是對漢字而言,因爲低位的編碼已經被使用(早期計算機並不支持中文,所以爲了擴展支持,惟一的辦法就是採用更多的字節數)只好向高位擴展。
通常字符集編碼的範圍 utf-8>gbk>iso-8859-1(latin1)>ascll。ascll編碼是美國標準信息交換碼的英文縮寫,包含了經常使用的字符,如阿拉伯數字,英文字母和一些打印符號,請注意字符和數字的區別,好比'0'字符對應的十進制數字是48。
unicode編碼包含不少種格式,utf-8是其中最經常使用的一種,utf-8名稱的來自於該編碼使用8位一個字節表示一個字符。對於一個漢字而言,它須要3個字節表示一個漢字,但大中華地區人民表示不服,搞一套gbk編碼格式,用兩個字節表示一個漢字。
亂碼問題:
亂碼問題的根源在於信息解碼和編碼時使用的格式不統一,參考IBM社區的一篇文章《深刻分析Java中文編碼問題》。
示例1--簡單&運算示例
@Test public void demo(){ // 0100&0100=0100 assertEquals(4,4&4); // 1000&0100=0000 assertEquals(0,4&8); // 字符'0'用十進制數48表示 char c = '0'; int i = c; assertEquals(48,i); // 認識 0xf, 0xff, 0xffff. f對應16進制數字15, 二進制1111 byte b = Byte.MAX_VALUE; assertEquals(127,b); assertEquals(127,b & 0xff); assertEquals(15,b & 0xf); byte b1 = -1; // 說明-1是按照默認的(byte)b1=0xff與0xff計算後轉換爲int值 = 255 assertEquals(255, (byte)b1&0xff); assertEquals(255, b1&0xff); // 255轉換爲byte 結果爲-1 assertEquals(-1, (byte)(b1&0xff)); // b1不強制轉換編譯器會報錯. 0xff超過byte表示範圍轉爲byte值獲得-1 byte bf = (byte) 0xff; assertEquals(bf, -1); // 0xf2 = 11110010 // 符號位不變取反+1 = 10001101+00000001 = 10001110 = -14 assertEquals(-14, (byte)0xf2); }
上面的代碼包含了幾個基本的運算和轉換的示例。
二進制與其它類型直接的轉換
工具類ByteUtils.java(爲方便了解進制轉換,各個方法參數都不包含index,若是要做爲工具使用,請自行修改)
package org.wit.ff.common; /** * * <pre> * 基本數據類型轉換(主要是byte和其它類型之間的互轉). * </pre> * * @author F.Fang * @version $Id: ByteUtils.java, v 0.1 2014年11月9日 下午11:23:21 F.Fang Exp $ */ public class ByteUtils { /** * * <pre> * 將4個byte數字組成的數組合併爲一個float數. * </pre> * * @param arr * @return */ public static float byte4ToFloat(byte[] arr) { if (arr == null || arr.length != 4) { throw new IllegalArgumentException("byte數組必須不爲空,而且是4位!"); } int i = byte4ToInt(arr); return Float.intBitsToFloat(i); } /** * * <pre> * 將一個float數字轉換爲4個byte數字組成的數組. * </pre> * * @param f * @return */ public static byte[] floatToByte4(float f) { int i = Float.floatToIntBits(f); return intToByte4(i); } /** * * <pre> * 將八個byte數字組成的數組轉換爲一個double數字. * </pre> * * @param arr * @return */ public static double byte8ToDouble(byte[] arr) { if (arr == null || arr.length != 8) { throw new IllegalArgumentException("byte數組必須不爲空,而且是8位!"); } long l = byte8ToLong(arr); return Double.longBitsToDouble(l); } /** * * <pre> * 將一個double數字轉換爲8個byte數字組成的數組. * </pre> * * @param i * @return */ public static byte[] doubleToByte8(double i) { long j = Double.doubleToLongBits(i); return longToByte8(j); } /** * * <pre> * 將一個char字符轉換爲兩個byte數字轉換爲的數組. * </pre> * * @param c * @return */ public static byte[] charToByte2(char c) { byte[] arr = new byte[2]; arr[0] = (byte) (c >> 8); arr[1] = (byte) (c & 0xff); return arr; } /** * * <pre> * 將2個byte數字組成的數組轉換爲一個char字符. * </pre> * * @param arr * @return */ public static char byte2ToChar(byte[] arr) { if (arr == null || arr.length != 2) { throw new IllegalArgumentException("byte數組必須不爲空,而且是2位!"); } return (char) (((char) (arr[0] << 8)) | ((char) arr[1])); } /** * * <pre> * 將一個16位的short轉換爲長度爲2的8位byte數組. * </pre> * * @param s * @return */ public static byte[] shortToByte2(Short s) { byte[] arr = new byte[2]; arr[0] = (byte) (s >> 8); arr[1] = (byte) (s & 0xff); return arr; } /** * * <pre> * 長度爲2的8位byte數組轉換爲一個16位short數字. * </pre> * * @param arr * @return */ public static short byte2ToShort(byte[] arr) { if (arr != null && arr.length != 2) { throw new IllegalArgumentException("byte數組必須不爲空,而且是2位!"); } return (short) (((short) arr[0] << 8) | ((short) arr[1] & 0xff)); } /** * * <pre> * 將short轉換爲長度爲16的byte數組. * 實際上每一個8位byte只存儲了一個0或1的數字 * 比較浪費. * </pre> * * @param s * @return */ public static byte[] shortToByte16(short s) { byte[] arr = new byte[16]; for (int i = 15; i >= 0; i--) { arr[i] = (byte) (s & 1); s >>= 1; } return arr; } public static short byte16ToShort(byte[] arr) { if (arr == null || arr.length != 16) { throw new IllegalArgumentException("byte數組必須不爲空,而且長度爲16!"); } short sum = 0; for (int i = 0; i < 16; ++i) { sum |= (arr[i] << (15 - i)); } return sum; } /** * * <pre> * 將32位int轉換爲由四個8位byte數字. * </pre> * * @param sum * @return */ public static byte[] intToByte4(int sum) { byte[] arr = new byte[4]; arr[0] = (byte) (sum >> 24); arr[1] = (byte) (sum >> 16); arr[2] = (byte) (sum >> 8); arr[3] = (byte) (sum & 0xff); return arr; } /** * <pre> * 將長度爲4的8位byte數組轉換爲32位int. * </pre> * * @param arr * @return */ public static int byte4ToInt(byte[] arr) { if (arr == null || arr.length != 4) { throw new IllegalArgumentException("byte數組必須不爲空,而且是4位!"); } return (int) (((arr[0] & 0xff) << 24) | ((arr[1] & 0xff) << 16) | ((arr[2] & 0xff) << 8) | ((arr[3] & 0xff))); } /** * * <pre> * 將長度爲8的8位byte數組轉換爲64位long. * </pre> * * 0xff對應16進制,f表明1111,0xff恰好是8位 byte[] * arr,byte[i]&0xff恰好知足一位byte計算,不會致使數據丟失. 若是是int計算. int[] arr,arr[i]&0xffff * * @param arr * @return */ public static long byte8ToLong(byte[] arr) { if (arr == null || arr.length != 8) { throw new IllegalArgumentException("byte數組必須不爲空,而且是8位!"); } return (long) (((long) (arr[0] & 0xff) << 56) | ((long) (arr[1] & 0xff) << 48) | ((long) (arr[2] & 0xff) << 40) | ((long) (arr[3] & 0xff) << 32) | ((long) (arr[4] & 0xff) << 24) | ((long) (arr[5] & 0xff) << 16) | ((long) (arr[6] & 0xff) << 8) | ((long) (arr[7] & 0xff))); } /** * 將一個long數字轉換爲8個byte數組組成的數組. */ public static byte[] longToByte8(long sum) { byte[] arr = new byte[8]; arr[0] = (byte) (sum >> 56); arr[1] = (byte) (sum >> 48); arr[2] = (byte) (sum >> 40); arr[3] = (byte) (sum >> 32); arr[4] = (byte) (sum >> 24); arr[5] = (byte) (sum >> 16); arr[6] = (byte) (sum >> 8); arr[7] = (byte) (sum & 0xff); return arr; } /** * * <pre> * 將int轉換爲32位byte. * 實際上每一個8位byte只存儲了一個0或1的數字 * 比較浪費. * </pre> * * @param num * @return */ public static byte[] intToByte32(int num) { byte[] arr = new byte[32]; for (int i = 31; i >= 0; i--) { // &1 也能夠改成num&0x01,表示取最地位數字. arr[i] = (byte) (num & 1); // 右移一位. num >>= 1; } return arr; } /** * * <pre> * 將長度爲32的byte數組轉換爲一個int類型值. * 每個8位byte都只存儲了0或1的數字. * </pre> * * @param arr * @return */ public static int byte32ToInt(byte[] arr) { if (arr == null || arr.length != 32) { throw new IllegalArgumentException("byte數組必須不爲空,而且長度是32!"); } int sum = 0; for (int i = 0; i < 32; ++i) { sum |= (arr[i] << (31 - i)); } return sum; } /** * * <pre> * 將長度爲64的byte數組轉換爲一個long類型值. * 每個8位byte都只存儲了0或1的數字. * </pre> * * @param arr * @return */ public static long byte64ToLong(byte[] arr) { if (arr == null || arr.length != 64) { throw new IllegalArgumentException("byte數組必須不爲空,而且長度是64!"); } long sum = 0L; for (int i = 0; i < 64; ++i) { sum |= ((long) arr[i] << (63 - i)); } return sum; } /** * * <pre> * 將一個long值轉換爲長度爲64的8位byte數組. * 每個8位byte都只存儲了0或1的數字. * </pre> * * @param sum * @return */ public static byte[] longToByte64(long sum) { byte[] arr = new byte[64]; for (int i = 63; i >= 0; i--) { arr[i] = (byte) (sum & 1); sum >>= 1; } return arr; } }
測試用例:
1,測試基本的移位操做符號.
@Test public void op(){ // >>> // >> // <<< int i = -1; System.out.println(Arrays.toString(ByteUtils.intToByte32(i))); // 有符號右移,符號位依然存在,右移一位後最左邊的最高位補1, -1 System.out.println(i >> 1); // 無符號右移,忽略符號位,右移一位後最左邊的最高位補0,2147483647 Integer.MAX_VALUE System.out.println(i >>> 1); // 有符號左移,符號位依然存在,左移一位最低位補0. -2 System.out.println(i << 1); // <<<無此符號,由於左移符號位不會丟失,沒有必要再增長此操做. }
2,查詢最大值最小值.
@Test public void showMaxValAndminVal() { // 127 System.out.println(Byte.MAX_VALUE); // -128 System.out.println(Byte.MIN_VALUE); // 32767 System.out.println(Short.MAX_VALUE); // -32768 System.out.println(Short.MIN_VALUE); // 65535 2的16次方-1 System.out.println((int) Character.MAX_VALUE); // 0 System.out.println((int) Character.MIN_VALUE); // 2147483647 System.out.println(Integer.MAX_VALUE); // -2147483648 System.out.println(Integer.MIN_VALUE); // 科學計數法. // 3.4028235E38 System.out.println(Float.MAX_VALUE); // 1.4E-45 System.out.println(Float.MIN_VALUE); // 9223372036854775807 System.out.println(Long.MAX_VALUE); // -9223372036854775808 System.out.println(Long.MIN_VALUE); // 科學計數法. // 1.7976931348623157E308 System.out.println(Double.MAX_VALUE); // 4.9E-324 System.out.println(Double.MIN_VALUE); }
3,轉換測試:
@Test public void transByte() { char c = 'z'; byte[] charToByte2Arr = ByteUtils.charToByte2(c); assertEquals("[0, 122]", Arrays.toString(charToByte2Arr)); assertEquals('z', ByteUtils.byte2ToChar(charToByte2Arr)); short s = Short.MAX_VALUE; // System.out.println("Short.MAX_VALUE:" + s); byte[] shortToByte2Arr = ByteUtils.shortToByte2(s); assertEquals("[127, -1]", Arrays.toString(shortToByte2Arr)); assertEquals(s, ByteUtils.byte2ToShort(shortToByte2Arr)); byte[] shortToByte16 = ByteUtils.shortToByte16(s); System.out.println(Arrays.toString(shortToByte16)); System.out.println(ByteUtils.byte16ToShort(shortToByte16)); int i = Integer.MAX_VALUE; // System.out.println("Integer.MAX_VALUE:" + i); byte[] intToByte4Arr = ByteUtils.intToByte4(i); assertEquals("[127, -1, -1, -1]", Arrays.toString(intToByte4Arr)); assertEquals(i, ByteUtils.byte4ToInt(intToByte4Arr)); byte[] intToByte32Arr = ByteUtils.intToByte32(i); System.out.println(Arrays.toString(intToByte32Arr)); System.out.println(ByteUtils.byte32ToInt(intToByte32Arr)); long j = Long.MAX_VALUE; // System.out.println("Long.MAX_VALUE:" + j); byte[] longToByte8Arr = ByteUtils.longToByte8(j); assertEquals("[127, -1, -1, -1, -1, -1, -1, -1]", Arrays.toString(longToByte8Arr)); assertEquals(j, ByteUtils.byte8ToLong(longToByte8Arr)); byte[] longToByte64Arr = ByteUtils.longToByte64(j); System.out.println(Arrays.toString(longToByte64Arr)); System.out.println(ByteUtils.byte64ToLong(longToByte64Arr)); double d = 2.34; byte[] doubleToByte8Arr = ByteUtils.doubleToByte8(d); assertEquals("[64, 2, -72, 81, -21, -123, 30, -72]", Arrays.toString(doubleToByte8Arr)); // double類型不能直接作等值比較,只能在精度範圍作差值比較. assertEquals(d + "", ByteUtils.byte8ToDouble(doubleToByte8Arr) + ""); float f = 1.2f; byte[] floatToByte4Arr = ByteUtils.floatToByte4(f); assertEquals("[63, -103, -103, -102]", Arrays.toString(floatToByte4Arr)); assertEquals(f + "", ByteUtils.byte4ToFloat(floatToByte4Arr) + ""); }