2017-10-15 15 views
0

임의의 정밀도 숫자 bigendian이 인코딩 된 <code>uint8_t *</code> 배열을 가지고 있는데 C에서 아스키로의 임의의 정밀도 숫자

10 진수 Ascii 표현을 원합니다. 그래서 char *을 반환하는 함수를 작성해야합니다.

내가 사용하는 환경에서는 하드웨어 제한 때문에 임의의 정밀도 라이브러리를 가져올 수 없습니다.

쉽게 구현할 수있는 정보가 있습니다.

예를 들어, 다음과 같은 16 진수 d53ceb9d32c6ca06으로 정의 된 숫자는 15365415089075571206으로 표시되어야합니다.

+0

예제를 줄 수 있습니까? 아마 심지어 [mcve]일까요? – Yunnosch

+2

본질적으로, 당신은 긴 나눗셈을 구현해야합니다. –

+0

텍스트와 숫자 사이에 필요한 변환 정도에 따라 다릅니다. '256' 대신에 기수'100'을 사용하면 텍스트 출력은 거의 없지만 bignum을 사용한 산술 계산은'&'대신'%'대신 덜 효율적인'%'를 사용해야하기 때문에 절충안이 있습니다 sums, products, etc. –

답변

-1

다음은 작동 할 방법입니다. 전달하는 bigint를 파괴적으로 변경하므로, 값을 신경 쓰면 메서드를 호출하기 전에 임시 스크래치 버퍼에 복사하십시오.

또한 가장 최적화 된 버전이 아니지만 여기에서 수행하는 방법을 묻는 경우 여기에 대해서는 아직까지 미세 최적화에 관심이 없습니다.

#include <stdint.h> 
#include <stdbool.h> 
#include <stdio.h> 
#include <stdlib.h> 

bool is_zero(uint8_t *bigi_data, int bigi_size) { 
    int i = 0; 

    while((i < bigi_size) && (bigi_data[i] == 0)) { 
     i++; 
    } 
    return (i >= bigi_size); 
} 

uint8_t bigdivmod(uint8_t *bigi_data, int bigi_size, uint8_t divisor) { 
    int i = 0; 
    uint16_t ans = 0; 

    while((i < bigi_size) && (bigi_data[i] == 0)) { 
     i++; 
    } 
    for (; i < bigi_size; i++) { 
     ans = ans*256 + bigi_data[i]; 
     bigi_data[i] = ans/divisor; 
     ans = ans % divisor; 
    } 
    return (uint8_t)ans; 
} 

static const char *digits = "abcdefghijklmnopqrstuvwxyz"; 

char *bigitoa(uint8_t *bigi_data, int bigi_size, char *out, int base) { 
    /* Assumes that "out" has enough room. DESTRUCTIVE TO BIGI, so copy */ 
    /* if you care about the value */ 
    /* Only really works for non-negative values */ 
    int i = 0; 
    uint8_t swp; 
    int j; 

    if ((base < 2) || (base > 36)) { 
     return NULL; 
    } 

    if (is_zero(bigi_data, bigi_size)) { 
     out[0] = '0'; 
     out[1] = '\0'; 
     return out; 
    } 

    while (!is_zero(bigi_data, bigi_size)) { 
     out[i++] = digits[bigdivmod(bigi_data, bigi_size, base)]; 
    } 
    out[i] = 0; 
    for (j = 0; j < i/2; j++) { 
     swp = out[i - 1 - j]; 
     out[i - 1 - j] = out[j]; 
     out[j] = swp; 
    } 

    return out; 
} 

int main(int argc, char *argv[]) { 
    uint8_t test_data[] = { 0xd5, 0x3c, 0xeb, 0x9d, 0x32, 0xc6, 0xca, 0x06 }; 
    int test_data_len = sizeof(test_data); 
    char *p; 

    /* Times 3 because we can use three digits to represent 256. If changing */ 
    /* the base below from "10", change this factor. */ 
    p = malloc(3*test_data_len + 1); 

    printf("Test data works out to %s\n", 
      bigitoa(test_data, test_data_len, p, 10)); 

    return 0; 
}