JAVA 學習(一):16進位制字串自增的實現
JAVA學習系列,並不是從基礎去講java的知識,而是把我在學習或是工作中,一些思想、邏輯總結出來。
原先在工作中,因為測試的需要,經常要往資料庫中批量的插資料。而表的主鍵用的是UUID,是由16進位制字元加“-”組成的,還有裝置的mac地址是由16進位制字元加“:”組成的,那個時候,我剛學java,也不知道java裡面有方法,可以生成UUID,所以我當時的解決方案是,給定一個初始的UUID,然後讓UUID自增。當然,實現自增是需要做些處理的。UUID是由32個16進位制字元組成,如果轉換成二進位制的話,就是128位,而在java裡面,一個long型別的數字,也才64位,所以一個UUID要轉換成數字的話,需要兩個long來表示。所以,最終的處理邏輯就是:UUID先去掉分隔符“-”,再分成兩半,兩部分再轉換成long,自增以後,再轉換成16進位制字串,再拼接“-”,變成需要的字串。當然mac的自增與這個類似。後來,我就思考,這字串轉成數字,自增以後又轉換成字串,轉來轉去的,可不可以不轉換成數字就實現自增?基於這樣的思想,就開始了我的探索之路。
要實現16進位制字串的自增,先從簡單的做起,從一位數的加法做起,比如'f'+5,要怎麼實現?那麼要實現這個加法,需要解決三個問題:1. 把'f'轉換成數字,再進行運算。2.運算之後的結果,再轉換回16進位制字串。3.進位問題。解決方法就是:在方法內維護一個字元陣列,元素是0-9a-f這幾個字元,然後有了'f',那麼就查詢'f'在陣列中的下標,下標是幾,那麼這個字元就轉換成數字幾。查詢後,'f'在陣列中的下標是15,那是'f'就轉換成數字15,用15+5得到運算結果20,然後再把20轉換成16進位制,那麼把運算結果轉換成16進位制,存在兩種情況,一種是運算結果小於16,這個時候不需要進位,結果是幾就是幾,比如結果是11,不需要進位,那麼就到字元陣列中查詢下標是11的元素,結果是'b',那麼最終的結果就會顯示為“b”。那麼另外一種情況就是運算結果大於等於16了,這個時候需要進位,那麼進位時,要進幾,進位後本位是多少?進位數為運算結果除以16,進位後本位就是運算結果模以16。邏輯理清了,那麼就是程式碼的實現了
package aaa;
public class Demo {
public static void main(String[] args){
hexAdd('f', 5);
}
public static void hexAdd(char hex, int num){
char[] hexs = "0123456789abcdef".toCharArray();
int index = indexOfCharArray(hexs, hex);
if(index == -1){
System.out.println("所傳的字元引數非法!");
}else{
int sum = index+num;
if(sum<16){
System.out.println(hexs[sum]);
}else{
System.out.println(""+hexs[sum/16]+hexs[sum%16]);
}
}
}
/**
* 獲取字元在字元陣列中的下標
* 引數一:字元陣列
* 引數二:字元
* 返回值:字元在字元陣列中的下標,如果字元陣列中沒有該字元,返回-1
*/
public static int indexOfCharArray(char[] charArray, char c){
for(int i=0, len=charArray.length; i<len; ++i){
if(charArray[i]==c){
return i;
}
}
return -1;
}
}
執行之後,結果就會列印14,這就是'f'+5的結果。再接下來,就是實現多位16進位制字元的自增了
package aaa;
public class Demo {
public static char[] hexs = "0123456789abcdef".toCharArray();
public static void main(String[] args){
String result = hexAdd("abc", 256);
System.out.println(result);
}
public static String hexAdd(String hex, int num){
int len = hex.length()-1;
//是否需要進位
boolean b = true;
//參與了運算的位,運算之後的結果字串,
//由右向左運算,首先是最後一位參與運算,如果需要進位,那麼倒數第二位也要參與運算。以些類推
String change = "";
//最終運算結果,由未參與運算的位和參與了運算的位兩部分組成
String result = "";
while(b){
char c = hex.charAt(len);
int index = indexOfCharArray(hexs, c);
if(index == -1){
return "所傳的字串引數非法!";
}else{
int sum = index+num;
if(sum<16){
change = hexs[sum]+change;
result = hex.substring(0, len)+change;
b = false;
}else{
change = hexs[sum%16]+change;
num = sum/16;
}
}
--len;
}
return result;
}
/**
* 獲取字元在字元陣列中的下標
* 引數一:字元陣列
* 引數二:字元
* 返回值:字元在字元陣列中的下標,如果字元陣列中沒有該字元,返回-1
*/
public static int indexOfCharArray(char[] charArray, char c){
for(int i=0, len=charArray.length; i<len; ++i){
if(charArray[i]==c){
return i;
}
}
return -1;
}
}
這樣就簡單實現了16進位制字串的自增了,但現在還有問題,如果運算出來的結果,比原先的16進位制字串位數多的話,那麼就會出錯,下標越界。比如"ab",然後自增一個非常大的數,依次進位,最終結果大於2位的話,就會報錯,在while迴圈裡面,最後一行--len,會出現負數,然後下一次迴圈,用這個負數作下標去原字串中取字元,就下標越界了。改:
package aaa;
public class Demo {
public static char[] hexs = "0123456789abcdef".toCharArray();
public static void main(String[] args){
String result = hexAdd("c", 256);
System.out.println(result);
}
public static String hexAdd(String hex, int num){
int len = hex.length()-1;
//是否需要進位
boolean b = true;
//參與了運算的位,運算之後的結果字串,
//由右向左運算,首先是最後一位參與運算,如果需要進位,那麼倒數第二位也要參與運算。以些類推
String change = "";
//最終運算結果,由未參與運算的位和參與了運算的位兩部分組成
String result = "";
while(b && len>=0){
char c = hex.charAt(len);
int index = indexOfCharArray(hexs, c);
if(index == -1){
return "所傳的字串引數非法!";
}else{
int sum = index+num;
if(sum<16){
change = hexs[sum]+change;
result = hex.substring(0, len)+change;
b = false;
}else{
change = hexs[sum%16]+change;
num = sum/16;
}
}
--len;
}
while(b){
if(num<16){
change = hexs[num]+change;
result = change;
b= false;
}else{
change = hexs[num%16]+change;
num /= 16;
}
}
return result;
}
/**
* 獲取字元在字元陣列中的下標
* 引數一:字元陣列
* 引數二:字元
* 返回值:字元在字元陣列中的下標,如果字元陣列中沒有該字元,返回-1
*/
public static int indexOfCharArray(char[] charArray, char c){
for(int i=0, len=charArray.length; i<len; ++i){
if(charArray[i]==c){
return i;
}
}
return -1;
}
}
至此,方法就算封裝好了。新的問題又來了:字元大小寫的問題,自增的值為負數的情況,字串中存在分隔符,分隔符還不一樣的問題。有問題,得一個一個地解決,程式碼我就不貼了,我只把思路說一下,大家可以自己實現:
1. 字元大小寫的問題,好解決,方法內第一步,把傳進來的字串,先全部轉成小寫,處理完後,再根據需要轉換成大寫或是不轉。這個最好是統一返回小寫,是否轉成大寫,由方法的呼叫者決定。也想過在方法裡判斷是否是大小寫,但如果傳進來的字串中,沒有字母的情況下,就沒法判斷大小寫了。
2. 自增的值為負數或是為0的情況,為0的情況,好處理,字串原樣返回,字串為負數的話,實際上就是做減法。不過呢,做減法,比做加法要複雜那麼一丟丟,大家可以自己嘗試一下。
3. 字串中存在不一樣的分隔符的問題,我的解決方案就是把字串中0-9a-f這些字元的下標全部放到一個集合裡面,在集合中,取最後一個元素,作為下標去字串中取字元,做加法,運算之後,要進位的話,是進位到集合中倒數第二個元素作為下標的位置上,這樣就會把不是16進位制字元的所有字元都過濾掉。
其實還有一些小問題,那就是這些字串的長度都是固定的,比如,UUID不算分隔符的話,是32位,但是做加法之後,一直進位的話,不能弄出一個33位的UUID出來,那就大大的不妙了。還有傳的字串為空字串,或是為null的情況,這些是屬於異常情況,也要處理,這樣,程式的健壯性就會更好。
最後說一點,運用這個思想,還可以實現超大數字的加、減、乘、除,比如兩個long的乘法,就可以把兩個long轉成字串,再運用上面的邏輯,進行運算,然後得出一個表示數字的超長字串哦,大家有興趣,可以嘗試去實現一下。
相關文章
- Java 16進位制字串 取反Java字串
- C# 解析16進位制字串。將16進位制字串轉換成明文字串C#字串
- 16進位制字串轉位元組字串
- Java中8進位制和16進位制的表示方法Java
- 位元組流轉16進位制字串字串
- 口算 16 進位制轉換 10 進位制,但只適合兩位的 16 進位制
- 彙編實現10進位制轉16進位制並以ASCII碼輸出ASCII
- [20190819]如何快速轉換16進位制串到字串.txt字串
- java中二進位制、八進位制、十進位制、十六進位制的轉換Java
- 初學java進位制轉換方面補充學習Java
- ROP【二進位制學習】
- 負數補碼(16進位制轉10進位制的負數)
- 進位制轉化--Java自帶方法Java
- 十進位制轉換任意進位制--鏈棧實現
- printf()將10進位制數安照輸出16進位制,8進位制輸出
- C printf按8進位制、10進位制、16進位制輸出以及高位補0
- C語言中printf打出2進位制與16進位制數C語言
- oracle_16進位制與10進位制轉換小示例Oracle
- JAVA 二進位制,八進位制,十六進位制,十進位制間進行相互轉換Java
- [二進位制漏洞]PWN學習之格式化字串漏洞 Linux篇字串Linux
- C++資料格式化5 - uint轉換成十六進位制字串&二進位制的data列印成十六進位制字串C++UI字串
- 遞迴函式實現十進位制正整數轉換為二進位制,八進位制,十六進位制遞迴函式
- 在c語言中輸出8進位制數,16進位制數C語言
- 教你如何進行數倉字串、二進位制、十六進位制互轉字串
- Java實現BCD編碼與十進位制轉換Java
- 資料轉換-16進位制字元字元
- 16進位制的簡單運算(迴圈)
- PHP負數轉16進位制再轉到10進位制的正確姿勢PHP
- 二進位制,八進位制,十進位制,十六進位制的相互轉換
- 一看就懂二進位制、八進位制、十六進位制數轉換十進位制
- Go語言實現十進位制轉換成二、八、十六進位制Go
- .C++整數的N進位制字串表示C++字串
- 演算法學習之二進位制的妙用演算法
- 二進位制,八進位制,十進位制,十六進位制之間的轉換
- c++ 16進位制資料轉doubleC++
- 請問一下如何將字串轉二進位制?字串
- 進位制詳解:二進位制、八進位制和十六進位制
- C++實現進位制轉換工具C++