/* author: Leonardone @ NEETSDKASU */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

typedef unsigned long ulong;

#define UL(v) ((ulong)(v))

typedef struct _BigNum {
	int dot;
	int size;
	char value[1];
} BigNum, *LPBigNum;

int digits(ulong value);
LPBigNum newBigNum(ulong value);
LPBigNum newBigNumDbl(double value);
LPBigNum newBigNumStr(const char *str);
void printBigNum(const BigNum *num);

int main(void) {
	LPBigNum num = NULL;

	num = newBigNum(UL(1234567890));
	printBigNum(num);
	putchar('\n');
	if (num != NULL) {
		free(num);
	}

	num = newBigNum(UL(0));
	printBigNum(num);
	putchar('\n');
	if (num != NULL) {
		free(num);
	}

	num = newBigNumStr("98765.4321");
	printBigNum(num);
	putchar('\n');
	if (num != NULL) {
		free(num);
	}
	
	num = newBigNumDbl(4.0 * atan(1.0));
	printBigNum(num);
	putchar('\n');
	if (num != NULL) {
		free(num);
	}
	
	return 0;
}

int digits(ulong value) {
	int c = 0;
	while (value > 0UL) {
		value /= 10UL;
		c++;
	}
	return c;
}

LPBigNum newBigNum(ulong value) {
	int size = digits(value);
	LPBigNum temp = (LPBigNum)malloc(sizeof(BigNum) + size);
	if (temp != NULL) {
		temp->size = size;
		temp->dot = size;
		while (value > 0UL) {
			size--;
			temp->value[size] = (char)(value % 10UL);
			value /= 10UL;
		}
	}
	return temp;
}

LPBigNum newBigNumStr(const char *str) {
	LPBigNum temp;
	int len, size, dot, i, j;
	const char *c;
	if (str == NULL) {
		return NULL;
	}
	len = strlen(str);
	c = str;
	size = 0;
	dot = -1;
	for (i = 0; i < len; i++) {
		if (*c == '0') {
			if (size > 0) {
				size++;
			}
		} else if (*c >= '1' && *c <= '9') {
			size++;
		} else if (*c == '.' && dot < 0) {
			dot = size;
		} else {
			return NULL;
		}
		c++;
	}
	if (dot < 0) {
		dot = size;
	}
	temp = (LPBigNum)malloc(sizeof(BigNum) + size);
	if (temp != NULL) {
		temp->size = size;
		temp->dot = dot;
		c = str;
		j = 0;
		for (i = 0; i < len; i++) {
			if (*c == '0') {
				if (j > 0) {
					temp->value[j] = 0;
					j++;
				}
			} else if (*c >= '1' && *c <= '9') {
				temp->value[j] = *c - '0';
				j++;
			}
			c++;
		}
	}
	return temp;
}

LPBigNum newBigNumDbl(double value) {
	char buf[100];
	sprintf(buf, "%35.34lf", value);
	return newBigNumStr(buf);
}

void printBigNum(const BigNum *num) {
	int i;
	if (num == NULL) {
		printf("null");
	} else {
		for (i = 0; i < num->size; i++) {
			if (i == num->dot) {
				putchar('0');
				break;
			}
			if (num->value[i] != 0) {
				break;
			}
		}
		if (i < num->size) {
			for (; i < num->size; i++) {
				if (i == num->dot) {
					putchar('.');
				}
				putchar('0' + num->value[i]);
			}
		} else {
			putchar('0');
		}
	}
}
