如何在C中将128位整数转换为十进制ascii字符串?

Sil*_*ide 13 c string int ascii

我正在尝试将存储为4个无符号整数的数组的128位无符号整数转换为C中的十进制字符串表示:

unsigned int src[] = { 0x12345678, 0x90abcdef, 0xfedcba90, 0x8765421 };
printf("%s", some_func(src)); // gives "53072739890371098123344"
Run Code Online (Sandbox Code Playgroud)

(上面的输入和输出示例完全是虚构的;我不知道输入会产生什么.)

如果我要使用十六进制,二进制或八进制,这将是一个简单的掩码和位移到剥离最不重要的字符.但是,在我看来,我需要做基数为10的分裂.不幸的是,我不记得如何跨多个int执行此操作,并且我使用的系统不支持大于32位的数据类型,因此使用128位类型是不可能的.使用不同的语言也是不对的,我宁愿为这一个操作避免使用大数字库.

Ale*_*nze 8

分工没有必要:

#include <string.h>
#include <stdio.h>

typedef unsigned long uint32;

/* N[0] - contains least significant bits, N[3] - most significant */
char* Bin128ToDec(const uint32 N[4])
{
  // log10(x) = log2(x) / log2(10) ~= log2(x) / 3.322
  static char s[128 / 3 + 1 + 1];
  uint32 n[4];
  char* p = s;
  int i;

  memset(s, '0', sizeof(s) - 1);
  s[sizeof(s) - 1] = '\0';

  memcpy(n, N, sizeof(n));

  for (i = 0; i < 128; i++)
  {
    int j, carry;

    carry = (n[3] >= 0x80000000);
    // Shift n[] left, doubling it
    n[3] = ((n[3] << 1) & 0xFFFFFFFF) + (n[2] >= 0x80000000);
    n[2] = ((n[2] << 1) & 0xFFFFFFFF) + (n[1] >= 0x80000000);
    n[1] = ((n[1] << 1) & 0xFFFFFFFF) + (n[0] >= 0x80000000);
    n[0] = ((n[0] << 1) & 0xFFFFFFFF);

    // Add s[] to itself in decimal, doubling it
    for (j = sizeof(s) - 2; j >= 0; j--)
    {
      s[j] += s[j] - '0' + carry;

      carry = (s[j] > '9');

      if (carry)
      {
        s[j] -= 10;
      }
    }
  }

  while ((p[0] == '0') && (p < &s[sizeof(s) - 2]))
  {
    p++;
  }

  return p;
}

int main(void)
{
  static const uint32 testData[][4] =
  {
    { 0, 0, 0, 0 },
    { 1048576, 0, 0, 0 },
    { 0xFFFFFFFF, 0, 0, 0 },
    { 0, 1, 0, 0 },
    { 0x12345678, 0x90abcdef, 0xfedcba90, 0x8765421 }
  };
  printf("%s\n", Bin128ToDec(testData[0]));
  printf("%s\n", Bin128ToDec(testData[1]));
  printf("%s\n", Bin128ToDec(testData[2]));
  printf("%s\n", Bin128ToDec(testData[3]));
  printf("%s\n", Bin128ToDec(testData[4]));
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

0
1048576
4294967295
4294967296
11248221411398543556294285637029484152
Run Code Online (Sandbox Code Playgroud)

  • @BobbyPowers:不保证 `unsigned int` 的长度至少为 32 位。`unsigned long` 是。系统是否是64位无关紧要并且超出了C标准。 (2认同)

chi*_*ill 6

简单的除法基数 2^32,以相反的顺序打印十进制数字,使用 64 位算术,复杂性O(n)其中n是表示中的十进制位数:

#include <stdio.h>

unsigned int a [] = { 0x12345678, 0x12345678, 0x12345678, 0x12345678 };

/* 24197857161011715162171839636988778104 */

int
main ()
{
  unsigned long long d, r;

  do
    {
      r = a [0];

      d = r / 10;
      r = ((r - d * 10) << 32) + a [1];
      a [0] = d;

      d = r / 10;
      r = ((r - d * 10) << 32) + a [2];
      a [1] = d;

      d = r / 10;
      r = ((r - d * 10) << 32) + a [3];
      a [2] = d;

      d = r / 10;
      r = r - d * 10;
      a [3] = d;

      printf ("%d\n", (unsigned int) r);
    }
  while (a[0] || a[1] || a[2] || a[3]);

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

编辑:更正了循环,以便0在数组a只包含零时显示 a 。此外,数组从左到右读取,a[0] 是最重要的,a[3] 是最不重要的数字。