将十进制转换为任意基数?

我知道’strtoll’但是将任何Radix Base Number(2到36之间)转换为Decimal,我需要通过将Decimal转换为Any Radix Base Number来做相反的事情,

一个例子是十进制130基数12 = AA

下面的代码使用临时缓冲区来构建字符串,然后返回一个副本。 该字符串是通过从末尾向后工作并通过索引到另一个字符串来设置每个数字来构建的。 这应该比重复短字符串复制和附加Java版本更有效。 当你完成它们时你需要释放返回的字符串,并且如果基数可能超出范围则检查NULL返回…以避免在你可能想要调整它以使用它时始终分配新的字符串你提供的缓冲结果。

 /* return string representation of num in base rad as new string (or NULL) */ char *toBaseWhatever(int num, int rad) { char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; int i; char buf[66]; /* enough space for any 64-bit in base 2 */ /* bounds check for radix */ if (rad < 2 || rad > 62) return NULL; /* if num is zero */ if (!num) return strdup("0"); /* null terminate buf, and set i at end */ buf[65] = '\0'; i = 65; if (num > 0) { /* if positive... */ while (num) { /* until num is 0... */ /* go left 1 digit, divide by radix, and set digit to remainder */ buf[--i] = digits[num % rad]; num /= rad; } } else { /* same for negative, but negate the modulus and prefix a '-' */ while (num) { buf[--i] = digits[-(num % rad)]; num /= rad; } buf[--i] = '-'; } /* return a duplicate of the used portion of buf */ return strdup(buf + i); } 

试试这个。

 #include  #include  static void decimal_to_radix_base(char *s,int x,int base,int maxlen); static void insert_char(char *s,int c,int maxlen); static int digit(int x); void main(void) { int x,base; char s[128]; x=130; base=12; decimal_to_radix_base(s,x,base,127); printf("%d base %d = %s\n",x,base,s); } static void decimal_to_radix_base(char *s,int x,int base,int maxlen) { int sign; sign= (x<0) ? -1 : 1; if (x<0) x=-x; s[0]='\0'; if (x==0) { if (maxlen > 0) strcpy(s,"0"); return; } while (x>0) { int r; r=x%base; insert_char(s,digit(r),maxlen); x /= base; } if (sign<0) insert_char(s,'-',maxlen); } static void insert_char(char *s,int c,int maxlen) { int len; len=strlen(s); if (len>=maxlen) memmove(&s[1],s,len-1); else memmove(&s[1],s,len+1); s[0]=c; } static int digit(int x) { if (x<10) return('0'+x); return('A'+x-10); } 

如果您不需要创建自己的,’strtoll’或’strtoull’将为您进行转换:

  long long i64 = 0x8000000000000000LL; unsigned long long u64 = 0xFFFFFFFFFFFFFFFFULL; printf("Signed long long: %lld\n", i64); printf("Unsigned long long: %llu\n", u64); printf("\n"); char buffer[30]; sprintf(buffer, "%lld", i64); i64 = atoll(buffer); i64 = strtoll(buffer, NULL, 10); u64 = strtoull(buffer, NULL, 10); 

[编辑]这个编辑是对@willus关于他和@ dmitri解决方案之间的时间安排的评论的回应(纯粹是为了好玩),并在混音中添加了第三个。
在纯粹的速度方面,德米特里的产品赢得了手,但包括内存泄漏。 它以不释放内存的方式使用strdup()函数。 strdupa()是一种可以释放其分配的内存的替代方案,并且在这里是一个很好的替代品。 并且,如果根本没有使用strdup()strdupa() ,@ Dmitri的代码(由@willus指出)将运行得更快。

感谢AnyRadixConvert函数的这个实现

以下是运行整数0 – 5001的三个中的每一个的结果:
在此处输入图像描述

以下是产生这些结果的代码:( _note:存在微小的变化,例如,我没有strdup() ,但是有StrDup()

 #include "toolbox.h" //StrDup(), delete otherwise #include  #include #include #include #define MAXLEN_127 127 void delaySome(void); //test the timers... int AnyRadixConvert(const char* oldNumber, int oldRadix, char* newNumber, int newRadix); ///Willus static void willus_decimal_to_radix_base(char *s, int x,int base,int maxlen); static void insert_char(char *s,int c,int maxlen); static int digit(int x); ////Dmitri char *dmitri_toBaseWhatever(int num, int rad); int main(void) { char dataIn[66]="5001"; char dataOut[66]; int radixFrom = 10; int radixTo = 2; long long int i=0; //support willus_decimal_to_radix_base int x; //support Dmitri char demitri_result[66]; demitri_result[0]=0; int dataInNum; int maxInAll = 5001; /*Converts from base x to base y*/ //values from 2 to 36 for either parameter //time it // Delay(1); clock_t start, end; long double elapsed1, elapsedWillus, elapsedDimitri; start = clock(); //end time it for(i=0;i<=maxInAll;i++) { sprintf(dataIn, "%lld", i); AnyRadixConvert(dataIn,radixFrom,dataOut,radixTo); } //end timeit end = clock(); elapsed1 = ((double) (end - start)) / CLOCKS_PER_SEC; printf("AnyRadixConvert:\nFrom base %d: %s\nTo base %ld: %s\nElapsed time: %3.15Lf\n\n" ,radixFrom,dataIn,radixTo, dataOut, elapsed1); //willus_decimal_to_radix_base x=atol(dataIn); dataOut[0]=0; start = clock(); for(i=0;i<=maxInAll;i++) { willus_decimal_to_radix_base(dataOut,(int)i,radixTo,MAXLEN_127); } end = clock(); elapsedWillus = ((double) (end - start)) / CLOCKS_PER_SEC; printf("willus_decimal_to_radix_base:\nFrom base %d: %s\nTo base %ld: %s\nElapsed time: %3.15Lf\n\n",radixFrom,dataIn,radixTo, dataOut, elapsedWillus); //dimitri_toBaseWhatever dataInNum = atol("123123132"); start = clock(); for(i=0;i<=maxInAll;i++) { strcpy(demitri_result, dmitri_toBaseWhatever((int)i, radixTo)); } end = clock(); elapsedDimitri = ((double) (end - start)) / CLOCKS_PER_SEC; printf("dimitri_toBaseWhatever:\nFrom base %d: %s\nTo base %ld: %s\nElapsed time: %3.15Lf\n\n" ,radixFrom,dataIn,radixTo, demitri_result, elapsedDimitri); ////////////////////////// getchar(); return 0; } int AnyRadixConvert(const char* oldNumber, int oldRadix, char* newNumber, int newRadix) { long dataIn = 0L; char digit = 0; int i = 0; int size=strlen(oldNumber); char* reverseNew = NULL; /*Checks if base if within bounds*/ if((oldRadix<=1 || oldRadix>36)||(newRadix<=1 || newRadix>36)) { return 0; } /*Convert to base 10 from old base*/ for(i=0;i='0' && oldNumber[i]<='9') { dataIn+=(oldNumber[i]-'0')*pow(oldRadix,size-i-1); } else if(oldNumber[i]>='A' && oldNumber[i]<='Z') { dataIn+=(oldNumber[i]-'A' + 10)*pow(oldRadix,size-i-1); } else { return -1; } } i=0; /*Convert from base 10 to new base*/ while(dataIn>0) { digit = dataIn % newRadix; (digit<10)?(newNumber[i] = digit + '0') :(newNumber[i] = digit + 'A' -10); dataIn=dataIn/newRadix; i++; } newNumber[i]='\0'; /*Reverses newNumber*/ reverseNew = (char*)(malloc(sizeof(char)*strlen(newNumber)+1)); reverseNew[0]=0; size = strlen(newNumber); for(i=size-1; i>=0; i--) { reverseNew[i] = newNumber[size-1-i]; } reverseNew[size]='\0'; strcpy(newNumber,reverseNew); free(reverseNew); return 1; } static void willus_decimal_to_radix_base(char *s, int x,int base,int maxlen) { int sign; sign= (x<0) ? -1 : 1; if (x<0) x=-x; s[0]='\0'; if (x==0) { if (maxlen > 0) strcpy(s,"0"); return; } while (x>0) { int r; r=x%base; insert_char(s,digit(r),maxlen); x /= base; } if (sign<0) insert_char(s,'-',maxlen); } static void insert_char(char *s,int c,int maxlen) { int len; len=strlen(s); if (len>=maxlen) memmove(&s[1],s,len-1); else memmove(&s[1],s,len+1); s[0]=c; } static int digit(int x) { if (x<10) return('0'+x); return('A'+x-10); } ////Dimitri /* return string representation of num in base rad as new string (or NULL) */ char *dmitri_toBaseWhatever(int num, int rad) { char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; int i; char buf[66]; /* enough space for any 64-bit in base 2 */ buf[0]=0; /* bounds check for radix */ if (rad < 2 || rad > 62) return NULL; /* if num is zero */ if (!num) return StrDup("0"); //return strdup("0"); /* null terminate buf, and set i at end */ buf[65] = '\0'; i = 65; if (num > 0) { /* if positive... */ while (num) { /* until num is 0... */ /* go left 1 digit, divide by radix, and set digit to remainder */ buf[--i] = digits[num % rad]; num /= rad; } } else { /* same for negative, but negate the modulus and prefix a '-' */ while (num) { buf[--i] = digits[-(num % rad)]; num /= rad; } buf[--i] = '-'; } /* return a duplicate of the used portion of buf */ return StrDup(buf + i); //return strdup(buf + i); } void delaySome(void) //test the timer { time_t x = clock(); while ((clock() - x)<1000); }