koneBeta

C/C++

C 사칙 연산이 없는 세계에서 사칙연산 코드

comi-soft
comi-soft
2025-06-06 12:35:29
조회 3141 · 좋아요 0


  1. + - * / 이 없을것


다만 * / 는 존재함, 참조 연산자는 [0] 로 대체하면 될일이고 주석은 그냥 지우면 될일 이기는 한데... 폰으로 하는 주제에 그정도로 매정하지는 않은편이라



// main, 단일 파일
#include <stdio.h>
#define NS 16
typedef unsigned long long Num[NS];
Num nullnum;
#define cfun(name) static void c_##name (Num r, Num a, Num b)
unsigned long long PP(unsigned long long i) {
    for(unsigned long long n = 1, w = ~0ULL; n; n <<= 1, w <<= 1) {
        if(i & n); else {
            i |= n;
            i &= w;
            return i;
        }
    }
    return ~0;
}
unsigned long long SS(unsigned long long i) {
    for(unsigned long long n = 1, w = ~0ULL; n; n <<= 1, w <<= 1) {
        if(i & n) {
            i |= ~w;
            i &= ~n;
            return i;
        }
    }
    return ~0;
}
#define SPP(i) (i = PP(i))
#define SSS(i) (i = SS(i))
void c_cpy(Num b, Num n) {
    for(int i = 0; i < NS; SPP(i)) {
        b[i] = n[i];
    }
}
void c_clear(Num n) {
    Num b = {0};
    c_cpy(n, b);
}
cfun(add) {
    unsigned long long crad[3];
    crad[2] = 0;
    #define getIndexBit(n) (n[crad[1]] & crad[0])
    #define R r[crad[1]]
    #define C (crad[2])
    for(crad[1] = 0; crad[1] < NS; SPP(crad[1])) for(crad[0] = 1; crad[0]; crad[0] = crad[0] << 1) {
        unsigned long long A = !!getIndexBit(a);
        unsigned long long B = !!getIndexBit(b);
        R &= ~crad[0];
        R |= (A^B^C ? crad[0] : 0);
        C = A&B|B&C|C&A;
    }
    #undef C
    #undef R
    #undef getIndexBit
}
cfun(sub) {
    unsigned long long crad[3];
    crad[2] = 0;
    #define getIndexBit(n) (n[crad[1]] & crad[0])
    #define R r[crad[1]]
    #define C (crad[2])
    for(crad[1] = 0; crad[1] < NS; SPP(crad[1])) for(crad[0] = 1; crad[0]; crad[0] = crad[0] << 1) {
        unsigned long long A = !!getIndexBit(a);
        unsigned long long B = !!getIndexBit(b);
        R &= ~crad[0];
        R |= (A^B^C ? crad[0] : 0);
        C = (!A)&B|B&C|C&(!A);
    }
    #undef C
    #undef R
    #undef getIndexBit
}

unsigned long long c_shift_left(Num n) {
    unsigned long long c = 0, c_b = 0;
    for(int i = 0; i < NS; SPP(i)) {
        c_b = n[i] >> 63;
        n[i] <<= 1;
        n[i] |= c;
        c = c_b;
    }
    return c;
}
unsigned long long c_shift_right(Num n) {
    unsigned long long c = 0, c_b = 0;
    for(int i = SS(NS); 0 <= i; SSS(i)) {
        c_b = n[i] & 1;
        n[i] >>= 1;
        n[i] |= (c << 63);
        c = c_b;
    }
    return c;
}
cfun(mul) {
    Num buffer;
    c_cpy(buffer, a);
    c_clear(r);
    for(int i = 0; i < NS; SPP(i)) for(unsigned long long s = 1; s; s <<= 1) {
        if(b[i] & s) c_add(r, r, buffer);
        c_shift_left(buffer);
    }
}
int c_cmp(Num a, Num b) {
    for(long long i = SS(NS); 0 <= i; i = SS(i)) {
        if(a[i] == b[i]) continue;
        if(a[i] > b[i]) return SS(0);
        if(a[i] < b[i]) return 1;
    }
    return 0;
}
static void c_div(Num r, Num a, Num b, Num m) {
    int index = 0;
    Num buffer, buf, point;
    c_cpy(buf, a); c_cpy(buffer, b);
    c_clear(r); c_clear(point); point[0] = 1;
    while( !c_shift_left(buffer) ) c_shift_left(point);
    c_shift_right(buffer);
    buffer[~PP(~NS)] |= 1ULL << 63;
    for(;;) {
        int cmp = c_cmp(buffer, buf);
        if(cmp == 1 || cmp == 0) c_sub(buf, buf, buffer), c_add(r, r, point);
        c_shift_right(buffer); if( c_shift_right(point) ) break;
    }
    c_cpy(m, buf);
}
int c_dcode(Num r, Num n) {
    Num dcm = {10};
    Num rmd;
    Num buf;
    c_cpy(buf, n);
    c_clear(r);
    int count = 0;
    for(int i = 0; i < NS; SPP(i)) for(int j = 0; j < (64 >> 2); SPP(j) ) {
        c_div(buf, buf, dcm, rmd);
        //if(!rmd[0]) break;
        r[i] |= (rmd[0] << (j << 2));
        SPP(count);
    }
    return count;
}
#define PS(p, i) (&p[i])
#define SPS(p, i) (p = PS(p, i))
#include <malloc.h>
int num_print(Num N) {
    size_t size = PP(NS * 16);
    char* buffer = (char*)malloc(size);
    if(!buffer) return SS(0);
    char* buf_p = buffer;
    Num n;
    c_dcode(n, N);
    Num t = {0x303030303030};
    for(int i = SS(NS); 0 <= i; SSS(i)) {
        //sprintf(buf_p, "%016llx", n[i]);
        char* buf_pp = buf_p;
        for(int j = SS(sizeof(unsigned long long) >> 2 << 3); 0 <= j; SSS(j)) {
            buf_pp[0] = ((n[i] >> (j<<2)) & 0xF) | '0';
            SPS(buf_pp, 1);
        }
        SPS(buf_p, 16);
    }
    SPS(buf_p, 1);
    *buf_p = '\0';
    buf_p = buffer;
    int count;
    while(*buf_p == '0') SPS(buf_p, 1);
    if(*buf_p == '\0') {
        count = printf("%s", "0");
    } else {
        count = printf("%s", buf_p);
    }
    free(buffer);
    return count;
}
#include <stdarg.h>
int system_printf(char* format, ...) {
    va_list list;
    va_start(list, format);
    size_t size = 0;
    while(format[SPP(size)]);
    char* buffer = malloc(size);
    if(!buffer) return SS(0);
    char* buf_p = buffer;
    while(*format) {
        *buf_p = *format;
        SPS(format, 1);
        SPS(buf_p, 1);
    }
    *buf_p = '\0';
    buf_p = buffer;
    char* buf_pp = buf_p;
    int count = 0;
    #define count_add(print) { \
        Num f = {count};\
        Num s = {print}; \
        c_add(f, f, s);\
        count = f[0];\
    }
    while(*buf_pp) {
        while(*buf_pp != '%') {
            SPS(buf_pp, 1);
            if(!*buf_pp) break;
        }
        if(!*buf_pp) {
            count_add( printf("%s", buf_p) );
            break;
        }
        *buf_pp = '\0';
        count_add(printf("%s", buf_p));
        *buf_pp = '%';
        switch( *(SPS(buf_pp, 1)) ) {
            case '%':
            count_add(printf("%c", '%'));
            break;
            case 'd':
            count_add(printf("%d", va_arg(list, int)));
            break;
            case 'f':
            count_add(printf("%f", va_arg(list, double)));
            break;
            case 'n':
            count_add(num_print(va_arg(list, Num)));
            break;
            case '\0':
            count_add(printf("%c", '%'));
            break;
            default:
            count_add(printf("%%%c", *buf_pp));
            break;
        }
        if(!*buf_pp) break;
        SPS(buf_pp, 1);
        buf_p = buf_pp;
    }
    va_end(list);
    free(buffer);
    return count;
}
int num_read(Num r, char* value) {
    Num dcm = {10}, buffer, point = {1}, str_0 = {'0'};
    const char* start = PS(value, SS(0));
    char* val_p = value;
    if(!*val_p) return SS(0);
    while( val_p[1] ) val_p = &val_p[1];
    c_clear(r);
    while(start != val_p) {
        Num n = {*val_p};
        if('0' <= n[0] && n[0] <= '9'); else continue;
        c_sub(n, n, str_0);
        c_mul(n, n, point);
        c_add(r, r, n);
        c_mul(point, point, dcm);
        SPS(val_p, SS(0));
    }
    return 0;
}
int main(int argc, char** argv) {
    Num a, b, c, d;
    num_read(a, "12345678901234567890");
    num_read(b, "12345678901234567890");
    num_read(c, "111101111011110111101111011110111101111011110111101111011110"); // 60자
    c_mul(d, a, b);
    c_mul(d, d, c);
    system_printf("hello %n \n", d);
    return 0;
}
// 264줄


여담:


3트째 진행 중, 이전 코드는 난해한게 크거나 << >> 연산자도 포기해서 메크로로 만드는 등 난국이라서 간결하게 만드는 걸 목표로 작성했음


설명:


add sub mul div 등등 사칙 연산 함수 구현


num_print, num_read 등등 입출력 구현


system_printf 함수는 printf에서 %n으로 해당 구조체를 출력할수가 있도록 만든 함수임


의외로 va_ 같은건 처음 써보고 다른 사람 블로그 들어갔을때처럼 평소 접할때는 머리에 버퍼링이 들어갔지만 실제로 작성하는건 쉽게 했는 것 같음


num은 unsigned long long array 형태로 구현이 되어있는 매우 큰 수임, 256B 단위로도 쓰는건 가능함


근데 256B가 속도가 한계인 느낌, 구현이 뭐랄까... print를 본다면 div 연산을 자릿수마다 하는 등등 의외로 최종버전 느낌이라 좀 느린게 한계점인것 같음




0

댓글 4

default_user_icon
0/500자

전체