LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1378|回复: 11

问题请教:如何实现任意大整数到16进制的转换?

[复制链接]
发表于 2005-5-9 23:08:58 | 显示全部楼层 |阅读模式
给出一个无符号大整数,如何快速的转换到一个十六进制数?

程序要求:
1、输入:无符号大整数字符串,比如"123456789098765432199999"
2、输出:相应的十六进制数,以字符串方式显示,如 "0xFFEE8899AA"
3、时间效率越高越好

谢谢达人帮忙~~


PS: 这是某公司的面试题之一,555
 楼主| 发表于 2005-5-9 23:13:43 | 显示全部楼层
继续,同样是面试题之一。

如何实现int64到十进制的转换

程序要求:
1、输入:一个int64(8字节,以int32类似方式存放)的指针
2、输出:该int64的十进制字符串表示式。
3、必须手动写出转换过程,不得借助其他库函数。
4、时间效率越高越好。
回复 支持 反对

使用道具 举报

发表于 2005-5-10 15:07:32 | 显示全部楼层
第一个好难, 思考中.
回复 支持 反对

使用道具 举报

发表于 2005-5-10 15:58:36 | 显示全部楼层
记得以前作八数码问题的时候,用64位整数表示过数组,表示起来比较方便,这个跟本贴关系不大,但我觉得是个好思路,今天看到楼主的帖子,突然想起来,所以想加到这里,供大家参考[php]一个是从数组到整数
trans()
{long   iii;
  (b)=0;
  for(iii=o;iii<max;iii++)
(b)=((b)<<4)+a[iii];

   
}
另一个是从整数到数组
rtrans()
{
    long iii;
    unit64 ttt=(a);
    for (iii=max-1;iii>=0;iii--)
  {
         b[iii]=ttt&0xf;
         ttt>>=4;
   }
}[/php]
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-6-24 17:32:52 | 显示全部楼层
Post by Lolita
继续,同样是面试题之一。

如何实现int64到十进制的转换

程序要求:
1、输入:一个int64(8字节,以int32类似方式存放)的指针
2、输出:该int64的十进制字符串表示式。
3、必须手动写出转换过程,不得借助其他库函数。
4、时间效率越高越好。
  1. #include <stdio.h>
  2. const int base=10;
  3. const int max_int64_digits=20;
  4. char hex[]="0123456789ABCDEF";
  5. char * hex2dec(char *p, long long int *np)
  6. {
  7.     long long int n=*np;
  8.     while(n){
  9.         p--;
  10.         *p=hex[n%base];
  11.         n/=base;
  12.     }
  13.     return p;
  14.    
  15. }
  16. int main()
  17. {
  18.     char dec[max_int64_digits+1];
  19.     dec[max_int64_digits]=0;
  20.     long long int test_int=998877665544332211;
  21.     char * p=hex2dec(&dec[max_int64_digits], &test_int);
  22.     printf("dec value is: %s \n", p);
  23.    
  24.     return 0;
  25. }
复制代码
~/coding/c $  gcc hex2dec.c -std=c99
~/coding/c $  ./a.out
dec value is: 998877665544332211
刚好c99支持int64运算,所以实现起来很容易。

如果题目要求改成输出 int128 、 int256的10进制字符串的话不知有什么快速的算法?
回复 支持 反对

使用道具 举报

发表于 2006-6-24 20:42:12 | 显示全部楼层
题 一:
10 进制数到 16 进制数的经典转换方法就是用长除法, 非常简单, 但依据本题的要求, 难点是如何表示任意大整数及相关运算. 代码如下
  1. #include <stdio.h>
  2. #include <string.h>
  3. int mod = 0;
  4. /* s / 16
  5. * if result is short than the original s, return 1
  6. * */
  7. int div(char s[], int n)
  8. {
  9.         int i = 0;
  10.         mod = 0;
  11.         for (i = n - 1; i >= 0; i--) {
  12.                 int t = ((mod * 10) + s[i]);
  13.                 s[i] = t >> 4;
  14.                 mod = t & 0x0F;
  15.         }
  16.         if (s[n - 1] != 0) return 0;
  17.         if (s[n - 2] != 0) return 1;
  18.         return 2;
  19. }
  20. int main(void)
  21. {
  22.         char src[1000];
  23.         char dst[1000];
  24.         int src_len = 0;
  25.         int dst_len = 0;
  26.         memset(dst, 0, sizeof(dst));
  27.         printf("input number: ");
  28.         scanf("%s", src);
  29.         src_len = strlen(src);
  30.         int i = 0;
  31.         for (i = (src_len - 1) / 2; i >= 0; i--) {
  32.                 int t = src[i] - '0';
  33.                 src[i] = src[src_len - i - 1] - '0';
  34.                 src[src_len - i - 1] = t;
  35.         }
  36.         while (src_len > 0) {
  37.                 src_len -= div(src, src_len);
  38.                 dst[dst_len++] = mod;
  39.         }
  40.         printf("result is: ");
  41.         for (i = dst_len - 1; i >= 0; i--) {
  42.                 printf("%c", dst[i] > 9 ? dst[i] - 10 + 'A' : dst[i] + '0');
  43.         }
  44.         printf("\n");
  45.         return 0;
  46. }
复制代码
运行结果
  1. rf@RemoteFish:~/tmp/t$ time ./a.out
  2. input number: 1234567890987654321234567890987654321234567890987654321
  3. result is: CE3B5A137DD015278E09864703E4FF9952FF6B62C1CB1
  4. real    0m17.300s
  5. user    0m0.000s
  6. sys     0m0.003s
复制代码
没有严格测试, 求证
回复 支持 反对

使用道具 举报

发表于 2006-6-24 20:43:32 | 显示全部楼层
  1. rf@RemoteFish:~/tmp/t$ time ./a.out
  2. input number: 123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432
  3. result is: 49E49DD122F6F55D224108B9204FD93151F7F53F23F679DC29147E0EB4AF2219EDA950D7C9B1B060E1E508F78B22C73EB238AF8670C6F1C4A205D49E050D6A1CAECB404F01BBE0D88A45DAFD493FC59A104D5B77934132CC93193E714692BAB0CC02657596755FCAEEDC993821D8AB01BD7AF63737CF53D89D9AC2462FA699E082906FD49EDA2A90191EAAFA06271299CE49BFA0480FFEF8C4616A320863129A051240936930A38A858B169ED9005CB368EC6CC4874E6614B8749B7A6FE4AE4AB9ED1E5825BA8D6E7A8A5DF74900BD9D0B8A97A6E04C7F54E70A3D8B47885B2CABBC6E3B9937DC2C07B4254A7CEC38D5BB7FF12379C78
  4. real    0m6.567s
  5. user    0m0.004s
  6. sys     0m0.002s
复制代码
这是另一组稍微大一点的数据, 看起来执行效率一般
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-6-24 21:26:28 | 显示全部楼层
嗯,DoDo的方法可行。
不过长除法效率的确偏低,题目要求之一就是要效率,这才是难点

PS:DoDo的对那个src数组进行反转那一步(for循环)好像不必要吧, div、src、dst全部统一用human阅读顺序存储也可以,即最高位字符放在 数组[0] 位置。
回复 支持 反对

使用道具 举报

发表于 2006-6-25 00:54:47 | 显示全部楼层
做除法的时候位数会越来越少. 当然这个时候把指针偏移一下也行, 不过反转这种方法是高中写高精度计算器时留下的习惯, 写也写习惯了, 想也想习惯了, 呵呵
回复 支持 反对

使用道具 举报

发表于 2006-6-25 01:16:49 | 显示全部楼层
Lolita 兄有什么好的想法吗?

我考虑过预计算 k * 10^n (k = 1 ~ 9) 的值并保存在文件中, 然后程序运行时首先载入数据, 然后只要根据用户的输入做加法即可, 这样对于 N 位十进制数只要做 N 次高精度加法即可, 而且加法的长度由 0~N 逐渐增加, 这样的效率应该比较高. 不过 预计算 是否属于合法的手段只有看题目的要求了, 而且这样也不能达到 任意精度 的要求.
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表