C 中任意碱基到任意碱基的碱基转换(最多 36 个)

问题描述 投票:0回答:2

我正在寻找c中的基数转换函数,它可以进行基数2到36的转换,包括带有字符A-Z的基数。

目前我刚刚在网络上找到了处理基数 2、十和十六进制的函数,但有一些限制。

c function radix
2个回答
1
投票

对于这个项目,了解基地的工作原理可能会有所帮助。无论如何,让我们逐步了解如何转换为 12 进制的过程。这应该是最简单的实现方法。

首先,我们有十进制数,因为这是一个很容易开始的地方。假设,我不知道,1452 是我们的号码。我们还需要一个字符数组来表示每个字符的含义,因为这比直接的 ASCII 转换要容易得多,其中数字字符和字母字符是分开的。

int dec=1452;
int toBase=12;
char outputs[36]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}

接下来,我们可能只会在另一个基数中输出结果 - 以多种方式存储它是没有意义的,并且通过仅从一个基数转换到任何其他给定基数来使您的转换过程更简单。我们可以将结果存储在字符数组中,但同样,我们已经存储了数字 - 没有意义。

对于我要描述的这个方法,我们需要一个缓冲区变量来在转换部分数字时跟踪我们的数字。

int buf=dec;

接下来,我们将开始计算我们即将要计算的基数 12 中的空格,并看看每个空格的价值。我们将继续下去,直到通过我们的号码,然后返回一个。我们还需要保存我们所在的空间,以便稍后从该空间到第一个空间的 for 循环。

int space=0;
while(Math.pow(toBase,space))<buf){
  space++;
}//Braces added for clarity
space--;

现在,这是主计算循环,我们将在其中输出结果。同样,原始数字仍然存储在“dec”中,因此我们根本不需要担心数据丢失或更改它。

int i;
for(i=space;i>=0;i--){//We have set up the for loop to check each space as we progress
  int modResult=buf%Math.pow(toBase,i);//Gets the number that goes in this space of the resulting base number
  buf-=modResult*Math.pow(toBase,i);//We have that, so take it out of the number
  printf("%c",outputs[modResult]);
}

由于我们这样做的方式,从顶部空间到底部,modResult 永远不会高于我们的基数可以输入的最高数字。这样,您的程序将输出到控制台结果数字。另外,请记住,这仅输出数字 - 出于存储和计算的目的,使用以 10 为基数的内置函数要简单得多。此外,请注意 toBase 变量永远不会超过 36。

进一步说明,我从右到左对数字(空格)进行了编号,从零开始,因为最右边的空格是 1,用基数的零次方表示。希望这有帮助。


0
投票

您可以使用依赖于

string.h
的简单 C99 函数将任何以 2 为基数的数字(以字符串形式给出)转换为 62:

// Base conversion function that converts a number from any base to any base.
// - in: Input string representing the number in base_in.
// - out: Output buffer (large enough) to store the converted number in base_out.
// - base_in: The base of the input number (2 to 62).
// - base_out: The base of the output number (2 to 62).
// Returns: The output buffer containing the converted number.

#include <string.h>

static char *base_convert(const char *in, char *out, const int base_in, const int base_out) {
    // Miraculous base converter (arbitrary length, from any base to any base).
    static const char *alpha = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    int a, b;
    size_t d, e = 1;
    char *s = out;
    const char *c = in;
    if (*c == '+' || *c == '-')
        *s++ = *c++;
    *s++ = '0';
    for (*s-- = 0; *c; ++c) {
        for (a = (int) ((char *) memchr(alpha, *c, base_in) - alpha), d = e; d;) {
            b = (int) ((char *) memchr(alpha, s[--d], base_out) - alpha), b = b * base_in + a;
            s[d] = alpha[b % base_out];
            a = b / base_out;
        }
        for (; a; memmove(s + 1, s, ++e), *s = alpha[a % base_out], a /= base_out);
    }
    return out;
}

所有数字和基数的转换结果都是一致的。

如何知道缓冲区的大小?

当您想要估算给定位数的位数时:

static size_t approx_bits_from_digits(const size_t digits, const int base) {
    static const unsigned char logs[] = {252, 200, 172, 154, 142, 133, 126, 120, 115, 111, 108, 105, 102, 100, 97, 95, 94, 92, 91, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 80, 79, 78, 77, 77, 76, 76, 75, 75, 74, 74, 73, 73, 72, 72, 72, 71, 71, 70, 70, 70, 69, 69, 69, 68, 68, 68, 67, 67, 67, 67};
    return 1 + (base == 2 ? digits : digits * 400 / logs[base - 3]);
}

当您想要近似给定位数的位数(适合

malloc
)时:

static size_t approx_digits_from_bits(const size_t bits, const int base){
    static const unsigned char logs[] = {40, 63, 80, 92, 103, 112, 120, 126, 132, 138, 143, 148, 152, 156, 160, 163, 166, 169, 172, 175, 178, 180, 183, 185, 188, 190, 192, 194, 196, 198, 200, 201, 203, 205, 206, 208, 209, 211, 212, 214, 215, 217, 218, 219, 220, 222, 223, 224, 225, 226, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238};
    return 3 + bits * 40 / logs[base - 2]; // including a byte for the sign.
}

如何使用?

例如,我们可以将 76 位数字

51494837788488733028237
从基数 10 转换为基数 59:

#include <stdio.h>

int main(void) {
    // Your parameters
    const char from[] = "51494837788488733028237";
    const int base_from = 10, base_to = 59;
    
    // The base conversion
    const int count_bits = (int) approx_bits_from_digits(strlen(from), base_from);
    const int count_digits = (int) approx_digits_from_bits(count_bits, base_to);
    char to[count_digits];
    base_convert(from, to, base_from, base_to);
    
    // Printing the result
    printf("'%s' in base %d is equal to '%s' in base %d.\n", from, base_from, to, base_to);
}

您可以对照 GMP 进行验证,演示打印的结果

StackOverflow
字符串应该是相同的。

注意:源代码位于公共领域,

base_convert
的输入字符串必须代表给定基数中的有效数字。

在线尝试使用C(gcc)编译器

© www.soinside.com 2019 - 2024. All rights reserved.