![](/img/trans.png)
[英]How to convert string representation of an arbitrary length integer in a given base to decimal?
[英]How to convert an arbitrary large integer from base 10 to base 16?
該程序需要輸入一個任意大的無符號 integer,它以 10 進制表示為一個字符串。輸出是另一個以 16 進制表示 integer 的字符串。
例如輸入為“1234567890987654321234567890987654321234567890987654321”,output為“CE3B5A137DD015278E09864703E4FF9952FF6B62C1CB1”
算法越快越好。
如果輸入限制在32位或64位integer以內就很容易了; 例如,下面的代碼可以進行轉換:
#define MAX_BUFFER 16
char hex[] = "0123456789ABCDEF";
char* dec2hex(unsigned input) {
char buff[MAX_BUFFER];
int i = 0, j = 0;
char* output;
if (input == 0) {
buff[0] = hex[0];
i = 1;
} else {
while (input) {
buff[i++] = hex[input % 16];
input = input / 16;
}
}
output = malloc((i + 1) * sizeof(char));
if (!output)
return NULL;
while (i > 0) {
output[j++] = buff[--i];
}
output[j] = '\0';
return output;
}
真正具有挑戰性的部分是“任意大”的無符號integer。我已經谷歌了但大多數都在談論32位或64位內的轉換。 找不到運氣。
任何人都可以提供任何點擊或任何可以閱讀的鏈接嗎?
提前致謝。
編輯這是我最近遇到的一道面試題。 任何人都可以簡要解釋如何解決這個問題嗎? 我知道有一個 gmp 庫,我以前用過它; 但是,作為面試問題,它不需要使用外部庫。
分配整數數組,元素數等於輸入字符串的長度。 將數組初始化為全0。
該整數數組將在基數16中存儲值。
將輸入字符串中的十進制數字添加到數組的末尾。 多個現有值加10個結轉,在數組中存儲新值,新的結轉值為newvalue div 16。
carryover = digit; for (i = (nElements-1); i >= 0; i--) { newVal = array[index] * 10) + carryover; array[index] = newval % 16; carryover = newval / 16; }
打印數組,從第0個條目開始並跳過前導0。
這里有一些可行的代碼。 毫無疑問,可能會有一些優化。 但這應該是一個快速而骯臟的解決方案:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sys/types.h"
char HexChar [16] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
static int * initHexArray (char * pDecStr, int * pnElements);
static void addDecValue (int * pMyArray, int nElements, int value);
static void printHexArray (int * pHexArray, int nElements);
static void
addDecValue (int * pHexArray, int nElements, int value)
{
int carryover = value;
int tmp = 0;
int i;
/* start at the bottom of the array and work towards the top
*
* multiply the existing array value by 10, then add new value.
* carry over remainder as you work back towards the top of the array
*/
for (i = (nElements-1); (i >= 0); i--)
{
tmp = (pHexArray[i] * 10) + carryover;
pHexArray[i] = tmp % 16;
carryover = tmp / 16;
}
}
static int *
initHexArray (char * pDecStr, int * pnElements)
{
int * pArray = NULL;
int lenDecStr = strlen (pDecStr);
int i;
/* allocate an array of integer values to store intermediate results
* only need as many as the input string as going from base 10 to
* base 16 will never result in a larger number of digits, but for values
* less than "16" will use the same number
*/
pArray = (int *) calloc (lenDecStr, sizeof (int));
for (i = 0; i < lenDecStr; i++)
{
addDecValue (pArray, lenDecStr, pDecStr[i] - '0');
}
*pnElements = lenDecStr;
return (pArray);
}
static void
printHexArray (int * pHexArray, int nElements)
{
int start = 0;
int i;
/* skip all the leading 0s */
while ((pHexArray[start] == 0) && (start < (nElements-1)))
{
start++;
}
for (i = start; i < nElements; i++)
{
printf ("%c", HexChar[pHexArray[i]]);
}
printf ("\n");
}
int
main (int argc, char * argv[])
{
int i;
int * pMyArray = NULL;
int nElements;
if (argc < 2)
{
printf ("Usage: %s decimalString\n", argv[0]);
return (-1);
}
pMyArray = initHexArray (argv[1], &nElements);
printHexArray (pMyArray, nElements);
if (pMyArray != NULL)
free (pMyArray);
return (0);
}
我寫了一篇文章 ,描述了Python中的一個簡單解決方案,可用於從一系列數字轉換為任意數字基數。 我最初在C中實現了解決方案,並且我不希望依賴於外部庫。 我認為你應該能夠用C或任何你喜歡的方式重寫非常簡單的Python代碼。
這是Python代碼:
import math
import string
def incNumberByValue(digits, base, value):
# The initial overflow is the 'value' to add to the number.
overflow = value
# Traverse list of digits in reverse order.
for i in reversed(xrange(len(digits))):
# If there is no overflow we can stop overflow propagation to next higher digit(s).
if not overflow:
return
sum = digits[i] + overflow
digits[i] = sum % base
overflow = sum / base
def multNumberByValue(digits, base, value):
overflow = 0
# Traverse list of digits in reverse order.
for i in reversed(xrange(len(digits))):
tmp = (digits[i] * value) + overflow
digits[i] = tmp % base
overflow = tmp / base
def convertNumber(srcDigits, srcBase, destDigits, destBase):
for srcDigit in srcDigits:
multNumberByValue(destDigits, destBase, srcBase)
incNumberByValue(destDigits, destBase, srcDigit)
def withoutLeadingZeros(digits):
for i in xrange(len(digits)):
if digits[i] != 0:
break
return digits[i:]
def convertNumberExt(srcDigits, srcBase, destBase):
# Generate a list of zero's which is long enough to hold the destination number.
destDigits = [0] * int(math.ceil(len(srcDigits)*math.log(srcBase)/math.log(destBase)))
# Do conversion.
convertNumber(srcDigits, srcBase, destDigits, destBase)
# Return result (without leading zeros).
return withoutLeadingZeros(destDigits)
# Example: Convert base 10 to base 16
base10 = [int(c) for c in '1234567890987654321234567890987654321234567890987654321']
base16 = convertNumberExt(base10, 10, 16)
# Output list of base 16 digits as HEX string.
hexDigits = '0123456789ABCDEF'
string.join((hexDigits[n] for n in base16), '')
真正具有挑戰性的部分是“任意大”無符號整數。
您是否嘗試過使用GNU MP Bignum庫?
你可以試試這個任意長度的輸入 C99 base_convert (2 到 62 之間)function:
#include <stdlib.h>
#include <string.h>
static char *base_convert(const char * str, const int base_in, const int base_out) {
static const char *alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
size_t a, b, c = 1, d;
char *s = malloc(c + 1);
strcpy(s, "0");
for (; *str; ++str) {
for (a = (char*)memchr(alphabet, *str, base_out) - alphabet, b = c; b;) {
d = ((char *) memchr(alphabet, s[--b], base_out) - alphabet) * base_in + a;
s[b] = alphabet[d % base_out];
a = d / base_out;
}
for (; a; s = realloc(s, ++c + 1), memmove(s + 1, s, c), *s = alphabet[a % base_out], a /= base_out);
}
return s;
}
在線試用- 用法示例:
#include <stdio.h>
int main() {
char * res = base_convert("12345678909876543212345678909876"
"54321234567890987654321", 10, 16);
puts(res);
free(res);
// print CE3B5A137DD015278E09864703E4FF9952FF6B62C1CB1
}
示例 output:
'11100100100011101011001001110110001101001001100010100001111011110011000010'
from base 2 to base 58 is 'BaseConvert62'.
'NdN2mbALtnCHH' from base 60 to base 59 is 'StackOverflow'.
使用您的示例和Fibonacci(1500000)進行測試。
謝謝你。
這是一個BigInt庫:
http://www.codeproject.com/KB/cs/BigInt.aspx?msg=3038072#xx3038072xx
不知道它是否有效,但它是我在Google上找到的第一個。 它似乎具有解析和格式化大整數的函數,因此它們也可以支持不同的基數。
編輯:啊,你正在使用C,我的錯誤。 但是你可以從代碼中獲取想法,或者使用.NET的人可能有同樣的問題,所以我將把它留在這里。
Unix dc
能夠對任意大整數進行基本轉換。 這里提供Open BSD源代碼。
蟒蛇:
>>> from string import upper
>>> input = "1234567890987654321234567890987654321234567890987654321"
>>> output = upper(hex(int(input)))[2:-1]
>>> print output
CE3B5A137DD015278E09864703E4FF9952FF6B62C1CB1
以下是javascript中實現的上述算法:
function addDecValue(hexArray, value) {
let carryover = value;
for (let i = (hexArray.length - 1); i >= 0; i--) {
let rawDigit = ((hexArray[i] || 0) * 10) + carryover;
hexArray[i] = rawDigit % 16;
carryover = Math.floor(rawDigit / 16);
}
}
function toHexArray(decimalString) {
let hexArray = new Array(decimalString.length);
for (let i = 0; i < decimalString.length; i++) {
addDecValue(hexArray, Number(decimalString.charAt(i)));
}
return hexArray;
}
function toHexString(hexArray) {
const hexDigits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
let result = '';
for (let i = 0; i < hexArray.length; i++) {
if (result === '' && hexArray[i] === 0) continue;
result += hexDigits[hexArray[i]];
}
return result
}
toHexString(toHexArray('1234567890987654321234567890987654321234567890987654321'));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.