我們寫東西的時候總會遇到lua中要調用java代碼,當然這個用JNI肯定是可以做到的,但是有更加方便的辦法—LuaJavaBridge。 一、luaj 主要特征 * 可以從 Lua 調用 Java Class Static Method * 調用 Java 方法時,支持 int/float/bool ...
【問題描述】
給定n個十六進位正整數,輸出它們對應的八進位數。
輸入格式
輸入的第一行為一個正整數n (1<=n<=10)。
接下來n行,每行一個由0~9、大寫字母A~F組成的字元串,表示要轉換的十六進位正整數,每個十六進位數長度不超過100000。輸入的十六進位數不會有前導0,比如012A。
輸出格式
輸出n行,每行為輸入對應的八進位正整數。輸出的八進位數也不能有前導0。
樣例輸入
2
39
123ABC
樣例輸出
71
4435274
【編程思路1】
我們知道,二進位數與八進位數或十六進位數之間存在直接轉換關係。可以說,八或十六進位數是二進位數的縮寫形式。在電腦中,利用這一特點可把用二進位代碼表示的指令或數據寫成八或十六進位形式,以便於書寫或認讀。
(1)二進位整數與八進位整數的轉換。
由於八進位的基數為8,二進位的基數為2,兩者滿足8=23,故每位八進位數可轉換為等值的三位二進位數,反之亦然。
因此,八進位整數轉換成二進位整數,只需把每位八進位數用相應的3位二進位數代替即可。而二進位整數轉換成八進位整數,則將二進位整數從右到左分成三位一組,頭部不足三位時補0,再將每組的三位二進位數寫成一位八進位數,則得對應的八進位整數。
(2)二進位數與十六進位數的轉換。
由於十六進位的基數為16,二進位的基數為2,兩者滿足16=24,故每位十六進位數可轉換為等值的四位二進位數,反之亦然。
因此,十六進位整數轉換成二進位整數,只需把每位十六進位數用相應的4位二進位數代替即可。而二進位整數轉換成十六進位整數,則將二進位整數從右到左分成四位一組,頭部不足四位時補0,然後將每組的四位二進位數寫成一位十六進位數,則得對應的十六進位整數。
(3)八進位整數與十六進位整數的轉換。
可以用二進位數作為中間數制進行轉換。即若要將十六進位整數轉換為八進位整數,可以先將十六進位整數轉換為相應的二進位整數,然後再將二進位整數轉換為相應的八進位整數。
以樣例為例,若要轉換的十六進位整數為39,轉換為二進位整數時,每個數直接用4位二進位數來替換,寫成00111001,去掉前導0,得到相應的二進位整數 為 111001。再將該二進位整數從右到左分成兩組 111 001 ,每組分別用一個八進位數位來代替,寫成 71,即對應的八進位整數為 71。
若要轉換的十六進位整數為 123ABC,轉換為二進位整數時,每個數直接用4位二進位數來替換,寫成 0001 0010 0011 1010 1011 1100,去掉前導0,得到相應的二進位整數 為 10010001110101011 1100。再將該二進位整數從右到左分成七組 100 100 011 101 010 111 100 ,每組分別用一個八進位數位來代替,寫成 4 4 3 5 2 7 4,即對應的八進位整數為 4435274。
按上面的方法,可以編寫如下的源程式1。
【源程式1】
#include <stdio.h> #include <string.h> int main() { char hex[100001],bin[400001]; char table[16][5]={"0000","0001","0010","0011","0100","0101","0110","0111","1000","1001","1010","1011","1100","1101","1110","1111"}; int n,i,num; scanf("%d",&n); while (n--) { scanf("%s",hex); if (hex[0]=='0') { printf("0\n"); continue; } bin[0]='\0'; for (i=0;hex[i]!='\0';i++) // 將十六進位數中的每個數字用4位二進位數替換,從而將十六進位整數轉換為對應的二進位整數 { num=hex[i]-'0'; if (num>9) num=num-7; strcat(bin,table[num]); } for (i=0; bin[i]=='0';i++) ; // 去掉二進位數的前導0 strcpy(bin,&bin[i]); int len=strlen(bin); // 將二進位整數從右到左每3位為一組 if (len%3==0) // 先將頭部的一組(若為1位或2位)轉換為一個八進位數 i=0; else if (len%3==1) { i=1; printf("1"); } else { i=2; num=(bin[0]-'0')*2+(bin[1]-'0'); printf("%d",num); } for (;i<len;i+=3) // 再將後面的各組(每組均有3位),每組均轉換為一個八進位數 { num=(bin[i]-'0')*4+(bin[i+1]-'0')*2+(bin[i+2]-'0'); printf("%d",num); } printf("\n"); } return 0; }
【編程思路2】
上面的源程式1可以實現十六進位整數轉換為八進位整數,但由於採用二進位數過渡時,產生的二進位數位數太多。這樣,處理起來效率不高。在有些包含這個數制轉換問題的OJ系統中,若提交類似源程式1所示的代碼,會出現“運行超時”。因此,需要採用更高效的方法來處理。
由前面源程式1可知,一個十六進位整數的1位可以用4位二進位數來代替,而3位二進位數可以直接寫成 1位八進位數。3和4的最小公倍數為12。也就是說,十六進位整數轉換為八進位整數時,可以從右到左,將十六進位整數每3位一組,每組正好替換為12位的二進位整數,而這個12位的二進位整數轉換為八進位整數時,正好轉換為4位八進位數。因此,我們無需用二進位數作為過渡,在十六進位數轉換為八進位數時,可將十六進位整數從右到左分成三位一組,頭部不足三位時補0,然後將每組的三位十六進位數轉換為四位的八進位數,則得對應的八進位整數。在具體處理時,將這個3位十六進位數按權值展開的方式轉換為相應的十進位數,然後直接將轉換得到的十進位數按4位八進位數輸出即可。
還是以樣例為例,若要轉換的十六進位整數為 123ABC,將該十六進位數從右到左分成兩組 123 ABC,每組分別轉換為一個10進位數,再將轉換得到的每個十進位數按八進位數輸出。其中,在輸出時,頭部一組直接按實際位數輸出,而後面的各組必須按4位輸出,不足4位時用前導0填充。這樣,123 轉換為十進位數為291,按八進位數輸出為443; ABC轉換為十進位數為 2748,按4位八進位數輸出為 5274。這樣得到轉換後的八進位數為 4435274。
【源程式2】
#include <stdio.h> #include <string.h> int main() { char hex[100001]; int n; scanf("%d",&n); while (n--) { scanf("%s",hex); if (hex[0]=='0') { printf("0\n"); continue; } int i,j,len,k,num,sum; len=strlen(hex); k=len%3==0?3:len%3; // 將十六進位數從右向左每3位一組,k表示最左一組的位數 sum=0; for (i=0;i<k;i++) // 將最左一組k位十六進位數轉換為十進位數 { num=hex[i]-'0'; if (num>9) num=num-7; sum=sum*16+num; } printf("%o",sum); // 將十進位整數按八進位數輸出 for (;i<len;i+=3) // 將之後的十六進位數每3位一組轉換位十進位數,然後按4位八進位數輸出 { sum=0; for (j=0;j<3;j++) { num=hex[i+j]-'0'; if (num>9) num=num-7; sum=sum*16+num; } printf("%04o",sum); } printf("\n"); } return 0; }