吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 872|回复: 3
收起左侧

[C&C++ 原创] <ver0.3>大数计算加减乘除的字符实现

[复制链接]
wangarc 发表于 2026-2-22 16:11
加减乘除全部采用搬运字符的方法实现,即'1' + '2' 得'3',不是转换成数字后计算。
相比上一版,几乎是重写,主要是函数短了,程序结构清楚了。

一共就2个文件,一个头文件.h,和一个实现文件.c:
bigint_string.h
bigint_string.c
还有一个测试使用示例:
main_for_example.c

用基本的C代码,不依赖任何库,gcc和g++都可以编译(测试用main文件除外)

效果图片:
screenshot.png

主要实现文件bigint_string.c:
[C] 纯文本查看 复制代码
#include "bigint_string.h"

int bigInt_chAdd(char * ch, const char * c2, char * carry)
{	//return 0 = no error, return 1, 2, 3 = error!
	switch (*carry)
	{
		case '0': switch (*c2)
				  {
					  case '0': return bigInt_chAdd0(ch, carry);
					  case '1': return bigInt_chAdd1(ch, carry);
					  case '2': return bigInt_chAdd2(ch, carry);
					  case '3': return bigInt_chAdd3(ch, carry);
					  case '4': return bigInt_chAdd4(ch, carry);
					  case '5': return bigInt_chAdd5(ch, carry);
					  case '6': return bigInt_chAdd6(ch, carry);
					  case '7': return bigInt_chAdd7(ch, carry);
					  case '8': return bigInt_chAdd8(ch, carry);
					  case '9': return bigInt_chAdd9(ch, carry);
					  default: return 2; //Error: c2 out of range
				  }
		case '1': switch (*c2)
				  {
					  case '0': return bigInt_chAdd1(ch, carry);
					  case '1': return bigInt_chAdd2(ch, carry);
					  case '2': return bigInt_chAdd3(ch, carry);
					  case '3': return bigInt_chAdd4(ch, carry);
					  case '4': return bigInt_chAdd5(ch, carry);
					  case '5': return bigInt_chAdd6(ch, carry);
					  case '6': return bigInt_chAdd7(ch, carry);
					  case '7': return bigInt_chAdd8(ch, carry);
					  case '8': return bigInt_chAdd9(ch, carry);
					  case '9': return bigInt_chAdd10(ch, carry);
					  default: return 2; //Error: c2 out of range
				  }
		default: return 3; //Error: *carry out of range
	}
}

int bigInt_chAdd0(char * ch, char * carry)
{	//return 0 = no error, return 1 = error!
	switch (*ch)
	{
		case '0': *carry = '0'; *ch = '0'; return 0;
		case '1': *carry = '0'; *ch = '1'; return 0;
		case '2': *carry = '0'; *ch = '2'; return 0;
		case '3': *carry = '0'; *ch = '3'; return 0;
		case '4': *carry = '0'; *ch = '4'; return 0;
		case '5': *carry = '0'; *ch = '5'; return 0;
		case '6': *carry = '0'; *ch = '6'; return 0;
		case '7': *carry = '0'; *ch = '7'; return 0;
		case '8': *carry = '0'; *ch = '8'; return 0;
		case '9': *carry = '0'; *ch = '9'; return 0;
		default: return 1; //Error: *ch out of range
	}
}

int bigInt_chAdd1(char * ch, char * carry)
{	//return 0 = no error, return 1 = error!
	switch (*ch)
	{
		case '0': *carry = '0'; *ch = '1'; return 0;
		case '1': *carry = '0'; *ch = '2'; return 0;
		case '2': *carry = '0'; *ch = '3'; return 0;
		case '3': *carry = '0'; *ch = '4'; return 0;
		case '4': *carry = '0'; *ch = '5'; return 0;
		case '5': *carry = '0'; *ch = '6'; return 0;
		case '6': *carry = '0'; *ch = '7'; return 0;
		case '7': *carry = '0'; *ch = '8'; return 0;
		case '8': *carry = '0'; *ch = '9'; return 0;
		case '9': *carry = '1'; *ch = '0'; return 0;
		default: return 1; //Error: *ch out of range
	}
}

int bigInt_chAdd2(char * ch, char * carry)
{	//return 0 = no error, return 1 = error!
	switch (*ch)
	{
		case '0': *carry = '0'; *ch = '2'; return 0;
		case '1': *carry = '0'; *ch = '3'; return 0;
		case '2': *carry = '0'; *ch = '4'; return 0;
		case '3': *carry = '0'; *ch = '5'; return 0;
		case '4': *carry = '0'; *ch = '6'; return 0;
		case '5': *carry = '0'; *ch = '7'; return 0;
		case '6': *carry = '0'; *ch = '8'; return 0;
		case '7': *carry = '0'; *ch = '9'; return 0;
		case '8': *carry = '1'; *ch = '0'; return 0;
		case '9': *carry = '1'; *ch = '1'; return 0;
		default: return 1; //Error: *ch out of range
	}
}

int bigInt_chAdd3(char * ch, char * carry)
{	//return 0 = no error, return 1 = error!
	switch (*ch)
	{
		case '0': *carry = '0'; *ch = '3'; return 0;
		case '1': *carry = '0'; *ch = '4'; return 0;
		case '2': *carry = '0'; *ch = '5'; return 0;
		case '3': *carry = '0'; *ch = '6'; return 0;
		case '4': *carry = '0'; *ch = '7'; return 0;
		case '5': *carry = '0'; *ch = '8'; return 0;
		case '6': *carry = '0'; *ch = '9'; return 0;
		case '7': *carry = '1'; *ch = '0'; return 0;
		case '8': *carry = '1'; *ch = '1'; return 0;
		case '9': *carry = '1'; *ch = '2'; return 0;
		default: return 1; //Error: *ch out of range
	}
}

int bigInt_chAdd4(char * ch, char * carry)
{	//return 0 = no error, return 1 = error!
	switch (*ch)
	{
		case '0': *carry = '0'; *ch = '4'; return 0;
		case '1': *carry = '0'; *ch = '5'; return 0;
		case '2': *carry = '0'; *ch = '6'; return 0;
		case '3': *carry = '0'; *ch = '7'; return 0;
		case '4': *carry = '0'; *ch = '8'; return 0;
		case '5': *carry = '0'; *ch = '9'; return 0;
		case '6': *carry = '1'; *ch = '0'; return 0;
		case '7': *carry = '1'; *ch = '1'; return 0;
		case '8': *carry = '1'; *ch = '2'; return 0;
		case '9': *carry = '1'; *ch = '3'; return 0;
		default: return 1; //Error: *ch out of range
	}
}

int bigInt_chAdd5(char * ch, char * carry)
{	//return 0 = no error, return 1 = error!
	switch (*ch)
	{
		case '0': *carry = '0'; *ch = '5'; return 0;
		case '1': *carry = '0'; *ch = '6'; return 0;
		case '2': *carry = '0'; *ch = '7'; return 0;
		case '3': *carry = '0'; *ch = '8'; return 0;
		case '4': *carry = '0'; *ch = '9'; return 0;
		case '5': *carry = '1'; *ch = '0'; return 0;
		case '6': *carry = '1'; *ch = '1'; return 0;
		case '7': *carry = '1'; *ch = '2'; return 0;
		case '8': *carry = '1'; *ch = '3'; return 0;
		case '9': *carry = '1'; *ch = '4'; return 0;
		default: return 1; //Error: *ch out of range
	}
}

int bigInt_chAdd6(char * ch, char * carry)
{	//return 0 = no error, return 1 = error!
	switch (*ch)
	{
		case '0': *carry = '0'; *ch = '6'; return 0;
		case '1': *carry = '0'; *ch = '7'; return 0;
		case '2': *carry = '0'; *ch = '8'; return 0;
		case '3': *carry = '0'; *ch = '9'; return 0;
		case '4': *carry = '1'; *ch = '0'; return 0;
		case '5': *carry = '1'; *ch = '1'; return 0;
		case '6': *carry = '1'; *ch = '2'; return 0;
		case '7': *carry = '1'; *ch = '3'; return 0;
		case '8': *carry = '1'; *ch = '4'; return 0;
		case '9': *carry = '1'; *ch = '5'; return 0;
		default: return 1; //Error: *ch out of range
	}
}

int bigInt_chAdd7(char * ch, char * carry)
{	//return 0 = no error, return 1 = error!
	switch (*ch)
	{
		case '0': *carry = '0'; *ch = '7'; return 0;
		case '1': *carry = '0'; *ch = '8'; return 0;
		case '2': *carry = '0'; *ch = '9'; return 0;
		case '3': *carry = '1'; *ch = '0'; return 0;
		case '4': *carry = '1'; *ch = '1'; return 0;
		case '5': *carry = '1'; *ch = '2'; return 0;
		case '6': *carry = '1'; *ch = '3'; return 0;
		case '7': *carry = '1'; *ch = '4'; return 0;
		case '8': *carry = '1'; *ch = '5'; return 0;
		case '9': *carry = '1'; *ch = '6'; return 0;
		default: return 1; //Error: *ch out of range
	}
}

int bigInt_chAdd8(char * ch, char * carry)
{	//return 0 = no error, return 1 = error!
	switch (*ch)
	{
		case '0': *carry = '0'; *ch = '8'; return 0;
		case '1': *carry = '0'; *ch = '9'; return 0;
		case '2': *carry = '1'; *ch = '0'; return 0;
		case '3': *carry = '1'; *ch = '1'; return 0;
		case '4': *carry = '1'; *ch = '2'; return 0;
		case '5': *carry = '1'; *ch = '3'; return 0;
		case '6': *carry = '1'; *ch = '4'; return 0;
		case '7': *carry = '1'; *ch = '5'; return 0;
		case '8': *carry = '1'; *ch = '6'; return 0;
		case '9': *carry = '1'; *ch = '7'; return 0;
		default: return 1; //Error: *ch out of range
	}
}

int bigInt_chAdd9(char * ch, char * carry)
{	//return 0 = no error, return 1 = error!
	switch (*ch)
	{
		case '0': *carry = '0'; *ch = '9'; return 0;
		case '1': *carry = '1'; *ch = '0'; return 0;
		case '2': *carry = '1'; *ch = '1'; return 0;
		case '3': *carry = '1'; *ch = '2'; return 0;
		case '4': *carry = '1'; *ch = '3'; return 0;
		case '5': *carry = '1'; *ch = '4'; return 0;
		case '6': *carry = '1'; *ch = '5'; return 0;
		case '7': *carry = '1'; *ch = '6'; return 0;
		case '8': *carry = '1'; *ch = '7'; return 0;
		case '9': *carry = '1'; *ch = '8'; return 0;
		default: return 1; //Error: *ch out of range
	}
}

int bigInt_chAdd10(char * ch, char * carry)
{	//return 0 = no error, return 1 = error!
	switch (*ch)
	{
		case '0': *carry = '1'; *ch = '0'; return 0;
		case '1': *carry = '1'; *ch = '1'; return 0;
		case '2': *carry = '1'; *ch = '2'; return 0;
		case '3': *carry = '1'; *ch = '3'; return 0;
		case '4': *carry = '1'; *ch = '4'; return 0;
		case '5': *carry = '1'; *ch = '5'; return 0;
		case '6': *carry = '1'; *ch = '6'; return 0;
		case '7': *carry = '1'; *ch = '7'; return 0;
		case '8': *carry = '1'; *ch = '8'; return 0;
		case '9': *carry = '1'; *ch = '9'; return 0;
		default: return 1; //Error: *ch out of range
	}
}

int bigInt_chSub(char * ch, const char * c2, char * borrow)
{	//return 0 = no error, return 4, 5, 6 = error!
	switch (*borrow)
	{
		case '0': switch (*c2)
				  {
					  case '0': return bigInt_chSub0(ch, borrow);
					  case '1': return bigInt_chSub1(ch, borrow);
					  case '2': return bigInt_chSub2(ch, borrow);
					  case '3': return bigInt_chSub3(ch, borrow);
					  case '4': return bigInt_chSub4(ch, borrow);
					  case '5': return bigInt_chSub5(ch, borrow);
					  case '6': return bigInt_chSub6(ch, borrow);
					  case '7': return bigInt_chSub7(ch, borrow);
					  case '8': return bigInt_chSub8(ch, borrow);
					  case '9': return bigInt_chSub9(ch, borrow);
					  default: return 5; //Error: c2 out of range
				  }
		case '1': switch (*c2)
				  {
					  case '0': return bigInt_chSub1(ch, borrow);
					  case '1': return bigInt_chSub2(ch, borrow);
					  case '2': return bigInt_chSub3(ch, borrow);
					  case '3': return bigInt_chSub4(ch, borrow);
					  case '4': return bigInt_chSub5(ch, borrow);
					  case '5': return bigInt_chSub6(ch, borrow);
					  case '6': return bigInt_chSub7(ch, borrow);
					  case '7': return bigInt_chSub8(ch, borrow);
					  case '8': return bigInt_chSub9(ch, borrow);
					  case '9': return bigInt_chSub10(ch, borrow);
					  default: return 5; //Error: c2 out of range
				  }
		default: return 6; //Error: *borrow out of range
	}
}

int bigInt_chSub0(char * ch, char * borrow)
{	//return 0 = no error, return 4 = error!
	switch (*ch)
	{
		case '0': *borrow = '0'; *ch = '0'; return 0;
		case '1': *borrow = '0'; *ch = '1'; return 0;
		case '2': *borrow = '0'; *ch = '2'; return 0;
		case '3': *borrow = '0'; *ch = '3'; return 0;
		case '4': *borrow = '0'; *ch = '4'; return 0;
		case '5': *borrow = '0'; *ch = '5'; return 0;
		case '6': *borrow = '0'; *ch = '6'; return 0;
		case '7': *borrow = '0'; *ch = '7'; return 0;
		case '8': *borrow = '0'; *ch = '8'; return 0;
		case '9': *borrow = '0'; *ch = '9'; return 0;
		default: return 4; //Error: *ch out of range
	}
}

int bigInt_chSub1(char * ch, char * borrow)
{	//return 0 = no error, return 4 = error!
	switch (*ch)
	{
		case '0': *borrow = '1'; *ch = '9'; return 0;
		case '1': *borrow = '0'; *ch = '0'; return 0;
		case '2': *borrow = '0'; *ch = '1'; return 0;
		case '3': *borrow = '0'; *ch = '2'; return 0;
		case '4': *borrow = '0'; *ch = '3'; return 0;
		case '5': *borrow = '0'; *ch = '4'; return 0;
		case '6': *borrow = '0'; *ch = '5'; return 0;
		case '7': *borrow = '0'; *ch = '6'; return 0;
		case '8': *borrow = '0'; *ch = '7'; return 0;
		case '9': *borrow = '0'; *ch = '8'; return 0;
		default: return 4; //Error: *ch out of range
	}
}

int bigInt_chSub2(char * ch, char * borrow)
{	//return 0 = no error, return 4 = error!
	switch (*ch)
	{
		case '0': *borrow = '1'; *ch = '8'; return 0;
		case '1': *borrow = '1'; *ch = '9'; return 0;
		case '2': *borrow = '0'; *ch = '0'; return 0;
		case '3': *borrow = '0'; *ch = '1'; return 0;
		case '4': *borrow = '0'; *ch = '2'; return 0;
		case '5': *borrow = '0'; *ch = '3'; return 0;
		case '6': *borrow = '0'; *ch = '4'; return 0;
		case '7': *borrow = '0'; *ch = '5'; return 0;
		case '8': *borrow = '0'; *ch = '6'; return 0;
		case '9': *borrow = '0'; *ch = '7'; return 0;
		default: return 4; //Error: *ch out of range
	}
}

int bigInt_chSub3(char * ch, char * borrow)
{	//return 0 = no error, return 4 = error!
	switch (*ch)
	{
		case '0': *borrow = '1'; *ch = '7'; return 0;
		case '1': *borrow = '1'; *ch = '8'; return 0;
		case '2': *borrow = '1'; *ch = '9'; return 0;
		case '3': *borrow = '0'; *ch = '0'; return 0;
		case '4': *borrow = '0'; *ch = '1'; return 0;
		case '5': *borrow = '0'; *ch = '2'; return 0;
		case '6': *borrow = '0'; *ch = '3'; return 0;
		case '7': *borrow = '0'; *ch = '4'; return 0;
		case '8': *borrow = '0'; *ch = '5'; return 0;
		case '9': *borrow = '0'; *ch = '6'; return 0;
		default: return 4; //Error: *ch out of range
	}
}

int bigInt_chSub4(char * ch, char * borrow)
{	//return 0 = no error, return 4 = error!
	switch (*ch)
	{
		case '0': *borrow = '1'; *ch = '6'; return 0;
		case '1': *borrow = '1'; *ch = '7'; return 0;
		case '2': *borrow = '1'; *ch = '8'; return 0;
		case '3': *borrow = '1'; *ch = '9'; return 0;
		case '4': *borrow = '0'; *ch = '0'; return 0;
		case '5': *borrow = '0'; *ch = '1'; return 0;
		case '6': *borrow = '0'; *ch = '2'; return 0;
		case '7': *borrow = '0'; *ch = '3'; return 0;
		case '8': *borrow = '0'; *ch = '4'; return 0;
		case '9': *borrow = '0'; *ch = '5'; return 0;
		default: return 4; //Error: *ch out of range
	}
}

int bigInt_chSub5(char * ch, char * borrow)
{	//return 0 = no error, return 4 = error!
	switch (*ch)
	{
		case '0': *borrow = '1'; *ch = '5'; return 0;
		case '1': *borrow = '1'; *ch = '6'; return 0;
		case '2': *borrow = '1'; *ch = '7'; return 0;
		case '3': *borrow = '1'; *ch = '8'; return 0;
		case '4': *borrow = '1'; *ch = '9'; return 0;
		case '5': *borrow = '0'; *ch = '0'; return 0;
		case '6': *borrow = '0'; *ch = '1'; return 0;
		case '7': *borrow = '0'; *ch = '2'; return 0;
		case '8': *borrow = '0'; *ch = '3'; return 0;
		case '9': *borrow = '0'; *ch = '4'; return 0;
		default: return 4; //Error: *ch out of range
	}
}

int bigInt_chSub6(char * ch, char * borrow)
{	//return 0 = no error, return 4 = error!
	switch (*ch)
	{
		case '0': *borrow = '1'; *ch = '4'; return 0;
		case '1': *borrow = '1'; *ch = '5'; return 0;
		case '2': *borrow = '1'; *ch = '6'; return 0;
		case '3': *borrow = '1'; *ch = '7'; return 0;
		case '4': *borrow = '1'; *ch = '8'; return 0;
		case '5': *borrow = '1'; *ch = '9'; return 0;
		case '6': *borrow = '0'; *ch = '0'; return 0;
		case '7': *borrow = '0'; *ch = '1'; return 0;
		case '8': *borrow = '0'; *ch = '2'; return 0;
		case '9': *borrow = '0'; *ch = '3'; return 0;
		default: return 4; //Error: *ch out of range
	}
}

int bigInt_chSub7(char * ch, char * borrow)
{	//return 0 = no error, return 4 = error!
	switch (*ch)
	{
		case '0': *borrow = '1'; *ch = '3'; return 0;
		case '1': *borrow = '1'; *ch = '4'; return 0;
		case '2': *borrow = '1'; *ch = '5'; return 0;
		case '3': *borrow = '1'; *ch = '6'; return 0;
		case '4': *borrow = '1'; *ch = '7'; return 0;
		case '5': *borrow = '1'; *ch = '8'; return 0;
		case '6': *borrow = '1'; *ch = '9'; return 0;
		case '7': *borrow = '0'; *ch = '0'; return 0;
		case '8': *borrow = '0'; *ch = '1'; return 0;
		case '9': *borrow = '0'; *ch = '2'; return 0;
		default: return 4; //Error: *ch out of range
	}
}

int bigInt_chSub8(char * ch, char * borrow)
{	//return 0 = no error, return 4 = error!
	switch (*ch)
	{
		case '0': *borrow = '1'; *ch = '2'; return 0;
		case '1': *borrow = '1'; *ch = '3'; return 0;
		case '2': *borrow = '1'; *ch = '4'; return 0;
		case '3': *borrow = '1'; *ch = '5'; return 0;
		case '4': *borrow = '1'; *ch = '6'; return 0;
		case '5': *borrow = '1'; *ch = '7'; return 0;
		case '6': *borrow = '1'; *ch = '8'; return 0;
		case '7': *borrow = '1'; *ch = '9'; return 0;
		case '8': *borrow = '0'; *ch = '0'; return 0;
		case '9': *borrow = '0'; *ch = '1'; return 0;
		default: return 4; //Error: *ch out of range
	}
}

int bigInt_chSub9(char * ch, char * borrow)
{	//return 0 = no error, return 4 = error!
	switch (*ch)
	{
		case '0': *borrow = '1'; *ch = '1'; return 0;
		case '1': *borrow = '1'; *ch = '2'; return 0;
		case '2': *borrow = '1'; *ch = '3'; return 0;
		case '3': *borrow = '1'; *ch = '4'; return 0;
		case '4': *borrow = '1'; *ch = '5'; return 0;
		case '5': *borrow = '1'; *ch = '6'; return 0;
		case '6': *borrow = '1'; *ch = '7'; return 0;
		case '7': *borrow = '1'; *ch = '8'; return 0;
		case '8': *borrow = '1'; *ch = '9'; return 0;
		case '9': *borrow = '0'; *ch = '0'; return 0;
		default: return 4; //Error: *ch out of range
	}
}

int bigInt_chSub10(char * ch, char * borrow)
{	//return 0 = no error, return 4 = error!
	switch (*ch)
	{
		case '0': *borrow = '1'; *ch = '0'; return 0;
		case '1': *borrow = '1'; *ch = '1'; return 0;
		case '2': *borrow = '1'; *ch = '2'; return 0;
		case '3': *borrow = '1'; *ch = '3'; return 0;
		case '4': *borrow = '1'; *ch = '4'; return 0;
		case '5': *borrow = '1'; *ch = '5'; return 0;
		case '6': *borrow = '1'; *ch = '6'; return 0;
		case '7': *borrow = '1'; *ch = '7'; return 0;
		case '8': *borrow = '1'; *ch = '8'; return 0;
		case '9': *borrow = '1'; *ch = '9'; return 0;
		default: return 4; //Error: *ch out of range
	}
}

int bigInt_parse(const char * str, int * p_or_n, int * i_qty, int * d_qty, int * dot_pos)
{	//return 0 = no error, str is a bigint string, return 99, 7, 8, 9 = error!
	if (0 == str)
		return 99; //Error: nullptr is not allowed.
	int index = 0;		 //index of str.
	switch (str[index])
	{
	case '-': *p_or_n = -1; index++; break;	//negative number and bypass the '-'
	case '+': index++;						//bypass the '+'
	default: *p_or_n = 1;				//positive number
	}
	*i_qty = 0;	//integer part char qty
	*d_qty = 0; //decimal part char qty
	*dot_pos = -1;	//initialized as a not possible value.
	int dot_found = 0; //'.' found in the str
	while (str[index] != '\0')
	{
		switch (str[index])
		{
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':	dot_found ? ++(*d_qty) : ++(*i_qty);
				break;
			case '.':	if (++dot_found > 1)
							return 7;	//Error: too many '.'
						*dot_pos = index;
						break;
			default: return 8;	//Error: unexpected char found
		}
		index++;
	}
	if (*i_qty == 0 && *d_qty == 0)
		return 9;		//Error: no valid number found
	if (*dot_pos == -1)	//there is no '.' in the str, str is an integer
		*dot_pos = index;	//dot_pos set at '\0'(str end) for "no dot" integer
	////ignore excessive '0' in the end of decimal part
	//if (*i_qty > 0)
	//	while (*d_qty > 0 && str[*dot_pos + *d_qty] == '0')
	//		--(*d_qty);
	//else
	//	while (*d_qty > 1 && str[*dot_pos + *d_qty] == '0')
	//		--(*d_qty);	//leave 1 char at least
	////ignore excessive '0' in the begining of integeral part
	//if (*d_qty > 0)
	//	while (*i_qty > 0 && str[*dot_pos - *i_qty] == '0')
	//		--(*i_qty);
	//else
	//	while (*i_qty > 1 && str[*dot_pos - *i_qty] == '0')
	//		--(*i_qty);	//leave 1 char at least
	return 0;
}

int bigInt_chInc(char * ch)
{	//return 0 = no error, return 10 = error! return 11 = Carry discarded!
	switch (*ch)
	{
		case '0': *ch = '1'; return 0;
		case '1': *ch = '2'; return 0;
		case '2': *ch = '3'; return 0;
		case '3': *ch = '4'; return 0;
		case '4': *ch = '5'; return 0;
		case '5': *ch = '6'; return 0;
		case '6': *ch = '7'; return 0;
		case '7': *ch = '8'; return 0;
		case '8': *ch = '9'; return 0;
		case '9': *ch = '0'; return 11; //Error: Carry discarded
		default: return 10; //Error: *ch out of range
	}
}

int bigInt_chDec(char * ch)
{	//return 0 = no error, return 12 = error! return 13 = borrow discarded!
	switch (*ch)
	{
		case '0': *ch = '9'; return 13; //Error: borrow discarded
		case '1': *ch = '0'; return 0;
		case '2': *ch = '1'; return 0;
		case '3': *ch = '2'; return 0;
		case '4': *ch = '3'; return 0;
		case '5': *ch = '4'; return 0;
		case '6': *ch = '5'; return 0;
		case '7': *ch = '6'; return 0;
		case '8': *ch = '7'; return 0;
		case '9': *ch = '8'; return 0;
		default: return 12; //Error: *ch out of range
	}
}

int bigInt_strTailAlignedAdd(char * s1, const int * h1, const int * t1,
							 const char * s2, const int * h2, const int * t2,
							 char * carry)
{	//return 0 = no error, return 19 = error!
	int tempRetVal;
	if (tempRetVal = bigInt_headTailValidate(*h1, *t1))
		return tempRetVal; //Error: wrong parameter.
	if (tempRetVal = bigInt_headTailValidate(*h2, *t2))
		return tempRetVal; //Error: wrong parameter.
	if (*t1 - *h1 < *t2 - *h2)
		return 19; //Error: not allowed: *t1 - *h1 < *t2 - *h2
	const int s2CharQty = *t2 - *h2 + 1;
	for (int i = 0; i < s2CharQty; ++i)
		if (tempRetVal = bigInt_chAdd(&s1[*t1 - i], &s2[*t2 - i], carry))
			return tempRetVal; //Error: bigInt_chAdd() returned error!
	const char c2 = '0';
	for (int temp_t1 = *t1 - s2CharQty; *carry == '1' && temp_t1 >= *h1; --temp_t1)
		if (tempRetVal = bigInt_chAdd(&s1[temp_t1], &c2, carry))
			return tempRetVal; //Error: bigInt_chAdd() returned error!
	return 0;
}

int bigInt_strTailAlignedSub(char * s1, const int * h1, const int * t1,
							 const char * s2, const int * h2, const int * t2,
							 char * borrow)
{	//return 0 = no error, return 20 = error!
	int tempRetVal;
	if (tempRetVal = bigInt_headTailValidate(*h1, *t1))
		return tempRetVal; //Error: wrong parameter.
	if (tempRetVal = bigInt_headTailValidate(*h2, *t2))
		return tempRetVal; //Error: wrong parameter.
	if (*t1 - *h1 < *t2 - *h2)
		return 20; //Error: not allowed: *t1 - *h1 < *t2 - *h2
	const int s2CharQty = *t2 - *h2 + 1;
	for (int i = 0; i < s2CharQty; ++i)
		if (tempRetVal = bigInt_chSub(&s1[*t1 - i], &s2[*t2 - i], borrow))
			return tempRetVal; //Error: bigInt_chSub() returned error!
	const char c2 = '0';
	for (int temp_t1 = *t1 - s2CharQty; *borrow == '1' && temp_t1 >= *h1; --temp_t1)
		if (tempRetVal = bigInt_chSub(&s1[temp_t1], &c2, borrow))
			return tempRetVal; //Error: bigInt_chSub() returned error!
	return 0;
}

int bigInt_strTailAlignedSubTry(const char * s1, const int * h1, const int * t1,
								const char * s2, const int * h2, const int * t2,
								char * borrow)
{	//return 0 = no error, return 21 = error!
	int tempRetVal;
	if (tempRetVal = bigInt_headTailValidate(*h1, *t1))
		return tempRetVal; //Error: wrong parameter.
	if (tempRetVal = bigInt_headTailValidate(*h2, *t2))
		return tempRetVal; //Error: wrong parameter.
	if (*t1 - *h1 < *t2 - *h2)
		return 21; //Error: not allowed: *t1 - *h1 < *t2 - *h2
	const int s2CharQty = *t2 - *h2 + 1;
	char tempChar;
	for (int i = 0; i < s2CharQty; ++i)
	{
		tempChar = s1[*t1 - i];
		if (tempRetVal = bigInt_chSub(&tempChar, &s2[*t2 - i], borrow))
			return tempRetVal; //Error: bigInt_chSub() returned error!
	}
	const char c2 = '0';
	for (int temp_t1 = *t1 - s2CharQty; *borrow == '1' && temp_t1 >= *h1; --temp_t1)
	{
		tempChar = s1[temp_t1];
		if (tempRetVal = bigInt_chSub(&tempChar, &c2, borrow))
			return tempRetVal; //Error: bigInt_chSub() returned error!
	}
	return 0;
}

int bigInt_chSet(char * s1, const int * h1, const int * t1, char ch)
{	//return 0 = no error.
	int tempRetVal;
	if (tempRetVal = bigInt_headTailValidate(*h1, *t1))
		return tempRetVal; //Error: wrong parameter.
	if (tempRetVal = bigInt_chValidate(ch))
		return tempRetVal; //Error: wrong ch.
	for (int i = *h1; i <= *t1; ++i)
		s1[i] = ch;
	return 0;
}

int bigInt_chSetAtPosition(char * s1, int * h1, int * t1, const int * s1Size, 
						   const int * position, char ch)
{	//return 0 = no error, return 22 = error!
	int tempRetVal;
	if (tempRetVal = bigInt_headTailValidate(*h1, *t1))
		return tempRetVal; //Error: wrong parameter.
	if (tempRetVal = bigInt_chValidate(ch))
		return tempRetVal; //Error: wrong ch.
	if (*position < 0 || *position < *h1 - 1 || *position > *t1 + 1 || *position >= *s1Size)
		return 22; //Error: not a reasonable position.
	if (*position == *h1 - 1)
		--(*h1);
	if (*position == *t1 + 1)
		++(*t1);
	s1[*position] = ch;
	return 0;
}

int bigInt_chSetBeforeHead(char * s1, int * h1, int * t1, const int * s1Size, char ch)
{	//return 0 = no error
	int tempRetVal;
	int position = *h1 - 1;
	if (tempRetVal = bigInt_chSetAtPosition(s1, h1, t1, s1Size, &position, ch))
		return tempRetVal;
	return 0;
}

int bigInt_chSetAfterTail(char * s1, int * h1, int * t1, const int * s1Size, char ch)
{	//return 0 = no error
	int tempRetVal;
	int position = *t1 + 1;
	if (tempRetVal = bigInt_chSetAtPosition(s1, h1, t1, s1Size, &position, ch))
		return tempRetVal;
	return 0;
}

int bigInt_chSequentialSetting(char * s1, int * h1, int * t1, const int * s1Size, 
							   int * setPosition, char ch)
{	//return 0 = no error.
	int tempRetVal;
	if (tempRetVal = bigInt_chSetAtPosition(s1, h1, t1, s1Size, setPosition, ch))
		return tempRetVal;
	++(*setPosition);
	return 0;
}

int bigInt_chValidate(char ch)
{	//return 0 = no error, return 23 = error!
	switch (ch)
	{
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
		case '.':
		case '-':
		case '+':
		case '\0': return 0;
		default: return 23; //Error: wrong ch.
	}
}

int bigInt_headTailValidate(int head, int tail)
{	//return 0 = no error, return 24 = error!
	if (head < 0 || tail < 0 || tail - head < 0)
		return 24; //Error: wrong parameter.
	return 0;
}

int bigInt_strCopy(char * s1, const int * h1, const int * t1,
				   const char * s2, const int * h2, const int * t2)
{	//return 0 = no error, return 25 = error!
	int tempRetVal;
	if (tempRetVal = bigInt_headTailValidate(*h1, *t1))
		return tempRetVal; //Error: wrong parameter.
	if (tempRetVal = bigInt_headTailValidate(*h2, *t2))
		return tempRetVal; //Error: wrong parameter.
	if (*t1 - *h1 != *t2 - *h2)
		return 25; //Error: not allowed: *t1 - *h1 != *t2 - *h2
	if (s1 + *h1 < s2 + *h2) //move start from head to tail
		for (int i = *h1, j = *h2; i <= *t1 && j <= *t2; ++i, ++j)
			s1[i] = s2[j];
	else if (s1 + *h1 > s2 + *h2) //move start from tail to head
		for (int i = *t1, j = *t2; i >= *h1 && j >= *h2; --i, --j)
			s1[i] = s2[j];
	else
		; // desti == source ? do nothing!
	return 0;
}

int bigInt_findNewHead(const char * s1, int * h1, const int * t1)
{	//return 0 = no error
	int tempRetVal;
	if (tempRetVal = bigInt_headTailValidate(*h1, *t1))
		return tempRetVal; //Error: wrong parameter.
	while (s1[*h1] == '0' && *h1 < *t1)
		++(*h1);
	return 0;
}

int bigInt_findNewTail(const char * s1, const int * h1, int * t1)
{	//return 0 = no error
	int tempRetVal;
	if (tempRetVal = bigInt_headTailValidate(*h1, *t1))
		return tempRetVal; //Error: wrong parameter.
	while (s1[*t1] == '0' && *t1 > *h1)
		--(*t1);
	return 0;
}

int bigInt_findDotPosition(const char * s1, const int * h1, const int * t1, 
						   int * dotPosition)
{	//return 0 = no error, return 26 = error!
	int tempRetVal;
	if (tempRetVal = bigInt_headTailValidate(*h1, *t1))
		return tempRetVal; //Error: wrong parameter.
	*dotPosition = -1;
	int dotCount = 0;
	for (int i = *h1; i <= *t1; ++i)
	{
		if (s1[i] == '.')
		{
			*dotPosition = i;
			++dotCount;
		}
	}
	if (dotCount > 1)
		return 26; //Error: too many dot
	return 0;
}

int bigInt_isZero(const char * s1, const int * h1, const int * t1, 
				  char * isZero)
{	//return 0 = no error
	int tempRetVal;
	if (tempRetVal = bigInt_headTailValidate(*h1, *t1))
		return tempRetVal; //Error: wrong parameter.
	*isZero = 'T';
	for (int i = *h1; i <= *t1; ++i)
	{
		switch (s1[i])
		{
			case '0':
			case '.':
			case '+':
			case '-':
			case '\0': continue;
			default: *isZero = 'F'; break;
		}
	}
	return 0;
}

int bigInt_copyToBufferPosition(const char * str, int i_qty, int d_qty, int dot_pos, 
		int aligned_i_size, int aligned_d_size, int safeSpaceBeforeHead, int safeSpaceAfterTail,
		char * buffer, int bufferSize, int * head, int * tail, const char * position)
{	//return 0 = no error, return 34, 35, 36 = error!
	if (i_qty < 0 || d_qty < 0 || dot_pos < 0 || aligned_i_size < 0 || aligned_d_size < 0)
		return 34; //Error: wrong parameter
	if (bufferSize < safeSpaceBeforeHead + aligned_i_size + aligned_d_size + safeSpaceAfterTail)
		return 35; //Error: bufferSize is not enough
	int tempRetVal;
	int nextIndexToFill;
	if (position[0] == 's') //fill at a position close to the start of the buffer.
		nextIndexToFill = safeSpaceBeforeHead;
	else if (position[0] == 'e') //fill at a position close to the end of the buffer.
		nextIndexToFill = bufferSize - safeSpaceAfterTail - aligned_d_size - aligned_i_size;
	else
		return 36;
	//insert '0' before integer parts.
	*head = nextIndexToFill;
	if (aligned_i_size > i_qty)
	{
		int frontZeroQty = aligned_i_size - i_qty;
		int fillZeroStart = nextIndexToFill;
		int fillZeroEnd = fillZeroStart + frontZeroQty - 1;
		if (tempRetVal = bigInt_chSet(buffer, &fillZeroStart, &fillZeroEnd, '0'))
			return tempRetVal;
		nextIndexToFill = fillZeroEnd + 1;
	}
	//copy integer parts
	if (i_qty > 0)
	{
		int fillIntegerStart = nextIndexToFill;
		int fillIntegerEnd = fillIntegerStart + i_qty - 1;
		int integer_head = dot_pos - i_qty;
		int integer_tail = dot_pos - 1;
		if (tempRetVal = bigInt_strCopy(buffer, &fillIntegerStart, &fillIntegerEnd,
										str, &integer_head, &integer_tail))
			return tempRetVal;
		nextIndexToFill = fillIntegerEnd + 1;
	}
	//copy decimal parts
	if (d_qty > 0)
	{
		int fillDecimalStart = nextIndexToFill;
		int fillDecimalEnd = fillDecimalStart + d_qty - 1;
		int decimal_head = dot_pos + 1;
		int decimal_tail = dot_pos + d_qty;
		if (tempRetVal = bigInt_strCopy(buffer, &fillDecimalStart, &fillDecimalEnd,
										str, &decimal_head, &decimal_tail))
			return tempRetVal;
		nextIndexToFill = fillDecimalEnd + 1;
	}
	//insert '0' after decimal parts.
	if (aligned_d_size > d_qty)
	{
		int rearZeroQty = aligned_d_size - d_qty;
		int fillZeroStart = nextIndexToFill;
		int fillZeroEnd = fillZeroStart + rearZeroQty - 1;
		if (tempRetVal = bigInt_chSet(buffer, &fillZeroStart, &fillZeroEnd, '0'))
			return tempRetVal;
		nextIndexToFill = fillZeroEnd + 1;
	}
	*tail = nextIndexToFill - 1;
	if (tempRetVal = bigInt_headTailValidate(*head, *tail)) //double check only
		return tempRetVal; //Error: something wrong. 
	return 0;
}

int bigInt_chInsertFromHead(char * s1, int * h1, const int * t1, const int * s1Size,
							const int * insertBeforeThisPos, char insertCh)
{	//return 0 = no error, return 37, 38, 39 = error!
	int tempRetVal;
	if (tempRetVal = bigInt_headTailValidate(*h1, *t1))
		return tempRetVal; //Error: wrong parameter.
	if (*insertBeforeThisPos < *h1 || *insertBeforeThisPos > *t1 + 1)
		return 37; //Error: wrong insert position
	if (*t1 >= *s1Size)
		return 38; //Error: out of space
	if ((*h1 - 1) < 0)
		return 39; //Error: out of space
	//move chars to left if necessary.
	if (*insertBeforeThisPos != *h1)
	{
		int sourceHead = *h1;
		int sourceTail = *insertBeforeThisPos - 1;
		int destiHead = *h1 - 1;
		int destiTail = *insertBeforeThisPos - 2;
		if (tempRetVal = bigInt_strCopy(s1, &destiHead, &destiTail,
			s1, &sourceHead, &sourceTail))
			return tempRetVal;
	}
	int pos = *insertBeforeThisPos - 1;
	char ch = insertCh;
	if (tempRetVal = bigInt_chSet(s1, &pos, &pos, ch))
		return tempRetVal;
	--(*h1);
	return 0;
}

int bigInt_chInsertFromTail(char * s1, const int * h1, int * t1, const int * s1Size, 
							const int * insertBeforeThisPos, char insertCh)
{	//return 0 = no error, return 40, 41 = error!
	int tempRetVal;
	if (tempRetVal = bigInt_headTailValidate(*h1, *t1))
		return tempRetVal; //Error: wrong parameter.
	if (tempRetVal = bigInt_chValidate(insertCh))
		return tempRetVal; //Error: wrong ch
	if (*insertBeforeThisPos < *h1 || *insertBeforeThisPos > *t1 + 1)
		return 40; //Error: wrong insert position
	if ((*t1 + 1) >= *s1Size)
		return 41; //Error: out of space
	//move chars to right if necessary.
	if (*insertBeforeThisPos != *t1 + 1)
	{
		int sourceHead = *insertBeforeThisPos;
		int sourceTail = *t1;
		int destiHead = *insertBeforeThisPos + 1;
		int destiTail = *t1 + 1;
		if (tempRetVal = bigInt_strCopy(s1, &destiHead, &destiTail,
			s1, &sourceHead, &sourceTail))
			return tempRetVal;
	}
	int pos = *insertBeforeThisPos;
	char ch = insertCh;
	if (tempRetVal = bigInt_chSet(s1, &pos, &pos, ch))
		return tempRetVal;
	++(*t1);
	return 0;
}

int bigInt_add(const char * s1, const char * s2, int * resultInBuffer,
			   char * buffer, const int * bufferSize)
{	//return 0 = no error.
	int tempRetVal;
	if (tempRetVal = bigInt_addOrSub(s1, s2, resultInBuffer,
					buffer, bufferSize, "Add"))
		return tempRetVal;
	return 0;
}

int bigInt_sub(const char * s1, const char * s2, int * resultInBuffer,
			   char * buffer, const int * bufferSize)
{	//return 0 = no error.
	int tempRetVal;
	if (tempRetVal = bigInt_addOrSub(s1, s2, resultInBuffer,
					buffer, bufferSize, "Sub"))
		return tempRetVal;
	return 0;
}

int bigInt_addOrSub(const char * str1, const char * str2, int * resultInBuffer,
					char * buffer, const int * bufferSize,
					const char * toDo)
{	//return 0 = no error, return 45, 46, 47, 48, 49, 50, 51, 52 = error!
	int tempRetVal;
	int pn1, iq1, dq1, dp1;
	if (tempRetVal = bigInt_parse(str1, &pn1, &iq1, &dq1, &dp1))
		return tempRetVal;
	int pn2, iq2, dq2, dp2;
	if (tempRetVal = bigInt_parse(str2, &pn2, &iq2, &dq2, &dp2))
		return tempRetVal;
	//consider toDo
	switch (toDo[0])
	{
		case 'S': pn2 = -pn2;	//change s1 - s2 to s1 + (-s2)
		case 'A': break;		//Add is default operation
		default: return 45; //Error: wrong parameter!
	}
	//align the size of str1 and str2
	int aligned_i_size = (iq1 > iq2) ? iq1 : iq2;
	int aligned_d_size = (dq1 > dq2) ? dq1 : dq2;
	const int safeSpaceBeforeHead = 4; 
		//extraSpaceInFront is required when you inserting 'carry', '.' or '-'
	const int safeSpaceAfterTail = 4;
		//extraSpaceAtRear is required when you inserting '.' or '\0'
	//copy str1 to a position close to the end of the buffer, 
	//digit chars only, and name as s1.
	char * s1 = buffer;
	int s1Size = *bufferSize;
	int h1, t1;
	const char * s1Position = "end of the buffer";
	if (tempRetVal = bigInt_copyToBufferPosition(str1, iq1, dq1, dp1, 
			aligned_i_size, aligned_d_size, safeSpaceBeforeHead, safeSpaceAfterTail,
			s1, s1Size, &h1, &t1, s1Position))
		return tempRetVal;
	//copy str2 to a position close to the start of the buffer, 
	//digit chars only, and name as s2.
	char * s2 = buffer;
	int s2Size = *bufferSize;
	int h2, t2;
	const char * s2Position = "start of the buffer";
	if (tempRetVal = bigInt_copyToBufferPosition(str2, iq2, dq2, dp2, 
			aligned_i_size, aligned_d_size, safeSpaceBeforeHead, safeSpaceAfterTail,
			s2, s2Size, &h2, &t2, s2Position))
		return tempRetVal;
	//check free space in buffer
	int freeSpaceInBuffer = *bufferSize - (t1 - h1 + 1) - (t2 - h2 + 1)
							- safeSpaceBeforeHead * 2 - safeSpaceAfterTail * 2;
	if (freeSpaceInBuffer < 0)
		return 46; //Error: not enough bufferSize
	//add or sub decided by pn1 and pn2
	//to save bufferSize, s1 or s2 may destroyed during add or sub.
	char * s3 = buffer;
	int s3Size = *bufferSize;
	int h3, t3, pn3;
	if (pn1 * pn2 == 1)
	{	
		if (tempRetVal = bigInt_addWithSameSign(s1, &s1Size, &h1, &t1, &pn1, 
					s2, &s2Size, &h2, &t2, &pn2, s3, &s3Size, &h3, &t3, &pn3))
			return tempRetVal;
	}
	else if (pn1 * pn2 == -1)
	{
		if (tempRetVal = bigInt_addWithOppositeSigns(s1, &s1Size, &h1, &t1, &pn1, 
					s2, &s2Size, &h2, &t2, &pn2, s3, &s3Size, &h3, &t3, &pn3))
			return tempRetVal;
	}
	else
	{
		return 47; // impossible, something wrong.
	}
	//make a readable s3, read friendly for human.
	int dq3 = aligned_d_size;
	if (tempRetVal = bigInt_makeFinishStr(s3, &s3Size, 
										  &h3, &t3, &dq3, &pn3))
		return tempRetVal;

	//calc result index in buffer
	*resultInBuffer = (int)(s3 - buffer + h3);
	return 0;
}

int bigInt_addWithSameSign(
	char * s1, const int * s1Size, int * h1, int * t1, int * pn1, 
	char * s2, const int * s2Size, int * h2, int * t2, int * pn2, 
	char * s3, const int * s3Size, int * h3, int * t3, int * pn3)
{	//return 0 = no error, return 54 = error!
	int tempRetVal;
	char carry = '0';
	if (tempRetVal = bigInt_strTailAlignedAdd(s1, h1, t1,
											  s2, h2, t2, &carry))
		return tempRetVal;
	//write '1' ahead of h1 if carry == '1'
	if (carry == '1')
	{
		if (tempRetVal = bigInt_chSetBeforeHead(s1, h1, t1, s1Size, carry))
			return tempRetVal;
		carry = '0';
	}
	*h3 = (int)(s1 - s3 + *h1);
	*t3 = (int)(s1 - s3 + *t1);
	if (*pn1 == 1 && *pn2 == 1)
		*pn3 = 1;
	else if (*pn1 == -1 && *pn2 == -1)
		*pn3 = -1;
	else
		return 54;	// Error: not alloweded in this function.
	return 0;
}

int bigInt_addWithOppositeSigns(
	char * s1, const int * s1Size, int * h1, int * t1, int * pn1, 
	char * s2, const int * s2Size, int * h2, int * t2, int * pn2, 
	char * s3, const int * s3Size, int * h3, int * t3, int * pn3)
{	//return 0 = no error, return 55, 56, 57, 58 = error!
	int tempRetVal;
	char borrow = '0';
	if (tempRetVal = bigInt_strTailAlignedSubTry(s1, h1, t1,
												 s2, h2, t2, &borrow))
		return tempRetVal;
	if (borrow == '0')
	{	// absolute s1 >= absolute s2, do: |s1| - |s2|
		borrow = '0';
		if (tempRetVal = bigInt_strTailAlignedSub(s1, h1, t1,
												  s2, h2, t2, &borrow))
			return tempRetVal;
		*h3 = (int)(s1 - s3 + *h1);
		*t3 = (int)(s1 - s3 + *t1);
		if (*pn1 == 1 && *pn2 == -1)
			*pn3 = 1;
		else if (*pn1 == -1 && *pn2 == 1)
			*pn3 = -1;
		else
			return 55;	// Error: not alloweded in this function.
	}
	else if (borrow == '1')
	{	// absolute s1 < absolute s2, do: |s2| - |s1|
		borrow = '0';
		if (tempRetVal = bigInt_strTailAlignedSub(s2, h2, t2,
												  s1, h1, t1, &borrow))
			return tempRetVal;
		if (borrow == '1')
			return 56; // impossible, something wrong.
		*h3 = (int)(s2 - s3 + *h2);
		*t3 = (int)(s2 - s3 + *t2);
		if (*pn1 == 1 && *pn2 == -1)
			*pn3 = -1;
		else if (*pn1 == -1 && *pn2 == 1)
			*pn3 = 1;
		else
			return 57;	// Error: not alloweded in this function.
	}
	else
	{
		return 58;	// impossible, something wrong.
	}
	return 0;
}

int bigInt_makeFinishStr(char * s3, const int * s3Size, 
						 int * h3, int * t3, int * dq3, int * pn3)
{	//return 0 = no error.
	int tempRetVal;
	int insertBeforeThisPos;
	char insertCh;
	//find if there is '.' already exist in s3.
	int dotPosition = -1; // -1 means no dot
	if (tempRetVal = bigInt_findDotPosition(s3, h3, t3, &dotPosition))
		return tempRetVal;
	//insert '.' if dot not found, and there's decimal parts
	if (dotPosition == -1 && *dq3 > 0) 
	{
		int insertZeroQtyBeforeHead = *dq3 - (*t3 - *h3);
		if (insertZeroQtyBeforeHead > 0)
		{
			int tail = *h3 - 1;
			int head = tail + 1 - insertZeroQtyBeforeHead;
			char setCh = '0';
			if (tempRetVal = bigInt_chSet(s3, &head, &tail, setCh))
				return tempRetVal;
			*h3 = head;
		}
		insertBeforeThisPos = *t3 + 1 - *dq3;
		insertCh = '.';
		if (insertBeforeThisPos - *h3 > *t3 - insertBeforeThisPos)
		{
			if (tempRetVal = bigInt_chInsertFromTail(s3, h3, t3, s3Size, 
											&insertBeforeThisPos, insertCh))
				return tempRetVal;
			dotPosition = insertBeforeThisPos;
		}
		else
		{
			if (tempRetVal = bigInt_chInsertFromHead(s3, h3, t3, s3Size, 
											&insertBeforeThisPos, insertCh))
				return tempRetVal;
			dotPosition = insertBeforeThisPos - 1;
		}
	}
	// unreasonable case 1: dot at head, may occur by incoming dot exist.
	if (dotPosition == *h3)
	{	//attention: use bigInt_chInsertFromTail() to avoid change of *h3
		insertBeforeThisPos = *h3;
		insertCh = '0';
		if (tempRetVal = bigInt_chInsertFromTail(s3, h3, t3, s3Size,
										&insertBeforeThisPos, insertCh))
			return tempRetVal;
		++dotPosition;
	}
	// unreasonable case 2: dot at tail, may occur by incoming dot exist.
	if (dotPosition == *t3)
	{
		--(*t3);
		dotPosition = -1;
	}
	//find new head and tail.
	if (dotPosition == -1) // -1 means no dot
	{
		if (tempRetVal = bigInt_findNewHead(s3, h3, t3))
			return tempRetVal;
	}
	else
	{
		int tailOfIntegerPart = dotPosition - 1;
		if (tempRetVal = bigInt_findNewHead(s3, h3, &tailOfIntegerPart))
			return tempRetVal;
		int headOfDecimalPart = dotPosition + 1;
		if (tempRetVal = bigInt_findNewTail(s3, &headOfDecimalPart, t3))
			return tempRetVal;
		if (*t3 == headOfDecimalPart && s3[*t3] == '0')
			*t3 = tailOfIntegerPart;
	}
	//write '-' ahead of h3
	//only if '-' not exist and pn3 == -1 and value is not Zero.
	char isZero;
	if (tempRetVal = bigInt_isZero(s3, h3, t3, &isZero))
		return tempRetVal;
	if (s3[*h3] != '-' && * pn3 == -1 && isZero == 'F')
	{
		if (tempRetVal = bigInt_chSetBeforeHead(s3, h3, t3, s3Size, '-'))
			return tempRetVal;
	}
	//append '\0' after t3.
	if (tempRetVal = bigInt_chSetAfterTail(s3, h3, t3, s3Size, '\0'))
		return tempRetVal;

	return 0;
}

int bigInt_strTailAlignedMul(const char * s1, const int * h1, const int * t1,
							 const char * s2, const int * h2, const int * t2,
							 char * s3, int * h3, int * t3, const int * s3Size)
{	//return 0 = no error, return 60, 61 = error!
	int tempRetVal;
	if (tempRetVal = bigInt_headTailValidate(*h1, *t1))
		return tempRetVal; //Error: wrong parameter.
	if (tempRetVal = bigInt_headTailValidate(*h2, *t2))
		return tempRetVal; //Error: wrong parameter.
	*h3 = *t3 - (*t1 - *h1); //*h3 to *t3 has the same size as *h1 to *t1 in the begining.
	if (tempRetVal = bigInt_chSet(s3, h3, t3, '0'))
		return tempRetVal;
	for (int i = *t2; i >= *h2; --i)
	{
		char carry = '0';
		int tailAlign = *t3 - (*t2 - i); //tailAlign is moving according i move.
		//s3: one char longer than s1 with '0' at first, no carry will occur during calculation
		if (tempRetVal = bigInt_chSetBeforeHead(s3, h3, t3, s3Size, '0'))
			return tempRetVal;
		char multiplier = s2[i];
		while (multiplier != '0')
		{
			if (tempRetVal = bigInt_strTailAlignedAdd(s3, h3, &tailAlign, 
													  s1, h1, t1, &carry))
				return tempRetVal;
			if (carry == '1') // s3 is one char longer than s1, carry should be '0' always.
				return 61; //Error: something wrong.
			if (tempRetVal = bigInt_chDec(&multiplier))
				return tempRetVal;
		}
	}
	if (tempRetVal = bigInt_headTailValidate(*h3, *t3))//double check only.
		return tempRetVal; //Error: wrong parameter.
	return 0;
}

int bigInt_strMul(const char * str1, const char * str2, int * resultInBuffer,
				  char * buffer, const int * bufferSize)
{	//return 0 = no error, return 65 = error!
	int tempRetVal;
	int pn1, iq1, dq1, dp1;
	if (tempRetVal = bigInt_parse(str1, &pn1, &iq1, &dq1, &dp1))
		return tempRetVal;
	int pn2, iq2, dq2, dp2;
	if (tempRetVal = bigInt_parse(str2, &pn2, &iq2, &dq2, &dp2))
		return tempRetVal;
	//align the size of str1 and str2
	//int aligned_i_size = (iq1 > iq2) ? iq1 : iq2; //no need for mul operation
	//int aligned_d_size = (dq1 > dq2) ? dq1 : dq2; //no need for mul operation
	const int safeSpaceBeforeHead = 4; 
		//extraSpaceInFront is required when you inserting 'carry', '.' or '-'
	const int safeSpaceAfterTail = 4;
		//extraSpaceAtRear is required when you inserting '.' or '\0'
	//copy str1 to a position close to the end of the buffer, 
	//digit chars only, and name as s1.
	char * s1 = buffer;
	int s1Size = *bufferSize;
	int h1, t1;
	const char * s1Position = "end of the buffer";
	if (tempRetVal = bigInt_copyToBufferPosition(str1, iq1, dq1, dp1, 
			iq1, dq1, safeSpaceBeforeHead, safeSpaceAfterTail,
			s1, s1Size, &h1, &t1, s1Position))
		return tempRetVal;
	//copy str2 to a position close to the start of the buffer, 
	//digit chars only, and name as s2.
	char * s2 = buffer;
	int s2Size = *bufferSize;
	int h2, t2;
	const char * s2Position = "start of the buffer";
	if (tempRetVal = bigInt_copyToBufferPosition(str2, iq2, dq2, dp2, 
			iq2, dq2, safeSpaceBeforeHead, safeSpaceAfterTail,
			s2, s2Size, &h2, &t2, s2Position))
		return tempRetVal;
	//check free space in buffer
	int freeSpaceInBuffer = *bufferSize - (t1 - h1 + 1) - (t2 - h2 + 1)
							- safeSpaceBeforeHead * 2 - safeSpaceAfterTail * 2;
	if (freeSpaceInBuffer < (t1 - h1 + 1))
		return 46; //Error: not enough bufferSize
	//multiply them: s1 is multiplicand, s2 is multiplier, 
	//to save bufferSize, s2 may destroyed during multiplying.
	//range of s3 covered the range of s2
	char * s3 = buffer;
	int s3Size = *bufferSize;
	int h3;
	int t3 = h1 - 1 - safeSpaceBeforeHead; //t3 position is ahead of h1
	int pn3 = pn1 * pn2;
	if (tempRetVal = bigInt_strTailAlignedMul(s1, &h1, &t1, 
						s2, &h2, &t2, s3, &h3, &t3, &s3Size))
		return tempRetVal;
	//make a readable s3, read friendly for human.
	int dq3 = dq1 + dq2;
	if (tempRetVal = bigInt_makeFinishStr(s3, &s3Size, 
										  &h3, &t3, &dq3, &pn3))
		return tempRetVal;
	//calc result index in buffer
	*resultInBuffer = (int)(s3 - buffer + h3);
	return 0;
}

int bigInt_mul(const char * s1, const char * s2, int * resultInBuffer,
			   char * buffer, const int * bufferSize)
{	//return 0 = no error.
	int tempRetVal;
	if (tempRetVal = bigInt_strMul(s1, s2, resultInBuffer,
								   buffer, bufferSize))
		return tempRetVal;
	return 0;
}

int bigInt_strTailAlignedDiv(char * s1, int * h1, int * t1,
							 char * s2, int * h2, int * t2,
							 char * s3, int * h3, int * t3, const int * s3Size)
{	//return 0 = no error, return 70, 71, 72, 73 = error!
	int tempRetVal;
	if (tempRetVal = bigInt_headTailValidate(*h1, *t1))
		return tempRetVal; //Error: wrong parameter.
	if (tempRetVal = bigInt_headTailValidate(*h2, *t2))
		return tempRetVal; //Error: wrong parameter.
	if (tempRetVal = bigInt_findNewHead(s2, h2, t2))
		return tempRetVal;
	char isDivisorZero = 'F';
	if (tempRetVal = bigInt_isZero(s2, h2, t2, &isDivisorZero))
		return tempRetVal;
	if (isDivisorZero == 'T')
		return 70; //Error: it's not allowed: divisor == 0
	if (*t1 - *h1 < *t2 - *h2)
		return 72; //Error: dividend length less than divisor length is not allowed.
	int quotientWritePosition = *h3; //Quotient will write here.
	*t3 = *h3; //*t3 initialized to *h3, *t3 will increase while you write data.
	for (int t1Align = *h1 + (*t2 - *h2) + 1; t1Align <= *t1; ++t1Align)
	{	//t1Align - *h1 = *t2 - *h2 + 1, dividend is always one char longer than divisor.
		char quotient = '0';
		char borrow = '0';
		if (tempRetVal = bigInt_strTailAlignedSubTry(s1, h1, &t1Align, 
													 s2, h2, t2, &borrow))
			return tempRetVal;
		while (borrow == '0')
		{
			if (tempRetVal = bigInt_strTailAlignedSub(s1, h1, &t1Align, 
													  s2, h2, t2, &borrow))
				return tempRetVal;
			if (tempRetVal = bigInt_chInc("ient))
				return tempRetVal;
			if (tempRetVal = bigInt_strTailAlignedSubTry(s1, h1, &t1Align, 
													 s2, h2, t2, &borrow))
				return tempRetVal;
		}
		if (tempRetVal = bigInt_chSequentialSetting(s3, h3, t3, s3Size, 
									"ientWritePosition, quotient))
			return tempRetVal;
		if (s1[*h1] == '0')
			++(*h1); //s1[*h1] must be '0' now.
		else
			return 73; //Error: Something wrong
	}
	return 0;
}

int bigInt_continueDecimalDiv(char * s1, int * h1, int * t1,
							  char * s2, int * h2, int * t2,
							  char * s3, int * h3, int * t3,
							  const int * s3Size, 
							  const int * truncateForQuotient,
							  int safeSpaceBeforeHead, int safeSpaceAfterTail)
{	//return 0 = no error
	int tempRetVal;
	char isDividendZero = 'F';
	if (tempRetVal = bigInt_isZero(s1, h1, t1, &isDividendZero))
		return tempRetVal;
	char isDivisorZero = 'F';
	if (tempRetVal = bigInt_isZero(s2, h2, t2, &isDivisorZero))
		return tempRetVal;
	int spaces_between_s3_tail_and_s1_head = (int)((s1 + *h1) - (s3 + *t3) - 1);
	int move_toward_the_head = spaces_between_s3_tail_and_s1_head
							   - safeSpaceBeforeHead;
	if (*truncateForQuotient > 0 && move_toward_the_head > *truncateForQuotient)
		move_toward_the_head = *truncateForQuotient;
	if (isDividendZero == 'F' && isDivisorZero == 'F' && move_toward_the_head > 0)
	{
		//move remainder toward head in s1, then have more space to append '0' for calculate
		int moveToNewH1 = *h1 - move_toward_the_head;
		int moveToNewT1 = *t1 - move_toward_the_head;
		if (tempRetVal = bigInt_strCopy(s1, &moveToNewH1, &moveToNewT1, s1, h1, t1))
			return tempRetVal;
		*h1 = moveToNewH1; //*h1 is changed.
		//fill Zero after remainder.
		int setZeroFrom = moveToNewT1 + 1;
		if (tempRetVal = bigInt_chSet(s1, &setZeroFrom, t1, '0')) //*t1 is not changed.
			return tempRetVal;
		//place a dot in s3 before write decimal parts
		if (tempRetVal = bigInt_chSetAfterTail(s3, h3, t3, s3Size, '.'))
			return tempRetVal;
		//prepare head for quotient write in s3
		int decimal_h3 = *t3 + 1;
		// go!
		if (tempRetVal = bigInt_strTailAlignedDiv(s1, h1, t1, s2, h2, t2, 
												  s3, &decimal_h3, t3, s3Size))
			return tempRetVal;
	}
	return 0;
}

int bigInt_divWithTurncate(const char * str1, const char * str2, 
						int * quotientInBuffer, int * remainderInBuffer, 
						char * buffer, const int * bufferSize, 
						const int * truncateForQuotient)
{	//return 0 = no error, return 80 = error!
	int tempRetVal;
	int pn1, iq1, dq1, dp1;
	if (tempRetVal = bigInt_parse(str1, &pn1, &iq1, &dq1, &dp1))
		return tempRetVal;
	int pn2, iq2, dq2, dp2;
	if (tempRetVal = bigInt_parse(str2, &pn2, &iq2, &dq2, &dp2))
		return tempRetVal;
	//align the size of str1 and str2
	int aligned_i_size = (iq1 > iq2) ? iq1 : iq2;
	int aligned_d_size = (dq1 > dq2) ? dq1 : dq2;
	const int safeSpaceBeforeHead = 4; 
		//extraSpaceInFront is required when you inserting 'carry', '.' or '-'
	const int safeSpaceAfterTail = 4;
		//extraSpaceAtRear is required when you inserting '.' or '\0'
	//copy str1 to a position close to the end of the buffer, 
	//digit chars only, and name as s1.
	char * s1 = buffer;
	int s1Size = *bufferSize;
	int h1, t1;
	const char * s1Position = "end of the buffer";
	if (tempRetVal = bigInt_copyToBufferPosition(str1, iq1, dq1, dp1, 
			aligned_i_size, aligned_d_size, safeSpaceBeforeHead, safeSpaceAfterTail,
			s1, s1Size, &h1, &t1, s1Position))
		return tempRetVal;
	//copy str2 to a position close to the start of the buffer, 
	//digit chars only, and name as s2.
	char * s2 = buffer;
	int s2Size = *bufferSize;
	int h2, t2;
	const char * s2Position = "start of the buffer";
	if (tempRetVal = bigInt_copyToBufferPosition(str2, iq2, dq2, dp2, 
			aligned_i_size, aligned_d_size, safeSpaceBeforeHead, safeSpaceAfterTail,
			s2, s2Size, &h2, &t2, s2Position))
		return tempRetVal;
	//check free space in buffer
	int freeSpaceInBuffer = *bufferSize - (t1 - h1 + 1) - (t2 - h2 + 1)
							- safeSpaceBeforeHead * 2 - safeSpaceAfterTail * 2;
	if (freeSpaceInBuffer < 4)
		return 46; //Error: not enough bufferSize
	// s1 / s2 = s3 ... s1 (s3 is quotient, s1 is remainder.)
	char * s3 = buffer;
	int s3Size = *bufferSize;
	int h3 = t2 + 1 + safeSpaceAfterTail; //h3 position is after t2
	int t3;
	int pn3 = pn1 * pn2;
	if (tempRetVal = bigInt_chSetBeforeHead(s1, &h1, &t1, &s1Size, '0'))
		return tempRetVal; // insert one '0' before h1 for integer div.
	if (tempRetVal = bigInt_strTailAlignedDiv(s1, &h1, &t1, s2, &h2, &t2, 
											  s3, &h3, &t3, &s3Size))
		return tempRetVal;
	//calc decimal part defined by truncateForQuotient
	if (*truncateForQuotient != 0)
	{
		if (tempRetVal = bigInt_continueDecimalDiv(s1, &h1, &t1,
							s2, &h2, &t2, s3, &h3, &t3, &s3Size, 
							truncateForQuotient, safeSpaceBeforeHead, safeSpaceAfterTail))
			return tempRetVal;
	}
	//make a readable s1 and s3, read friendly for human.
	int dq3 = 0;
	if (tempRetVal = bigInt_makeFinishStr(s3, &s3Size, 
										  &h3, &t3, &dq3, &pn3))
		return tempRetVal;
	if (*truncateForQuotient == 0)
	{	//remainder is only usefull for integer division
		dq1 = 0;
		pn1 = 1;
		if (tempRetVal = bigInt_makeFinishStr(s1, &s1Size,
			&h1, &t1, &dq1, &pn1))
			return tempRetVal;
	}
	//calc result index in buffer
	*quotientInBuffer = (int)(s3 - buffer + h3);
	*remainderInBuffer = (int)(s1 - buffer + h1);
	return 0;
}

int bigInt_divInteger(const char * str1, const char * str2, 
					  int * quotientInBuffer, int * remainderInBuffer, 
					  char * buffer, const int * bufferSize)
{	//return 0 = no error
	int tempRetVal;
	int truncateForQuotient = 0;
	if (tempRetVal = bigInt_divWithTurncate(str1, str2, 
						quotientInBuffer, remainderInBuffer, 
						buffer, bufferSize, &truncateForQuotient))
		return tempRetVal;
	return 0;
}

int bigInt_divDecimal(const char * str1, const char * str2, 
					  int * quotientInBuffer, char * buffer, 
					  const int * bufferSize)
{	//return 0 = no error
	int tempRetVal;
	int truncateForQuotient = -1; //calc until full of buffer
	int remainderInBuffer = 0; //no used data but needed for function call.
	if (tempRetVal = bigInt_divWithTurncate(str1, str2, 
						quotientInBuffer, &remainderInBuffer, 
						buffer, bufferSize, &truncateForQuotient))
		return tempRetVal;
	return 0;
}

int bigInt_divRound(const char * str1, const char * str2, int * quotientInBuffer, 
					char * buffer, const int * bufferSize, int round_digits)
{	//return 0 = no error
	int tempRetVal;
	if (round_digits < 0)
		round_digits = 0;
	int truncateForQuotient = round_digits + 1; //calc to round_digits + 1
	int remainderInBuffer = 0; //no used data but needed for function call.
	if (tempRetVal = bigInt_divWithTurncate(str1, str2, 
						quotientInBuffer, &remainderInBuffer, 
						buffer, bufferSize, &truncateForQuotient))
		return tempRetVal;
	if (tempRetVal = bigInt_decimalRound(buffer + *quotientInBuffer, round_digits))
		return tempRetVal;
	return 0;
}

int bigInt_decimalRound(char * str, int round_digits)
{	//return 0 = no error
	int tempRetVal;
	int pn, iq, dq, dp;
	if (tempRetVal = bigInt_parse(str, &pn, &iq, &dq, &dp))
		return tempRetVal;
	if (0 <= round_digits && round_digits < dq)
{
		int i_head;
		int i_tail;
		int d_head = dp + 1;
		int d_tail = dp + round_digits + 1;
		int strSize = (dp + dq + 1) + 1; // no use but required by fuction call
		if (iq > 0)
		{
			i_head = dp - iq;
			i_tail = dp - 1;
		}
		else
		{//iq == 0
			if (dp > 0 && str[dp - 1] == '0')
			{//there's at least one '0' before dot
				i_head = dp - 1;
				i_tail = dp - 1;
			}
			else
			{//dot at very first, insert one '0' before dot
				int insertBeforeThisPos = dp;
				if (tempRetVal = bigInt_chInsertFromTail(str, &dp, &d_tail, &strSize, 
													&insertBeforeThisPos, '0'))
					return tempRetVal;
				++dp;			//notice: above function call, only d_tail updated.
				d_head = dp + 1;//notice: above function call, only d_tail updated.
				i_head = dp - 1;
				i_tail = dp - 1;
			}
		}
		// add 5 at d_tail
		char s[2] = { '5', '\0' };
		int h = 0;
		int t = 0;
		char carry = '0'; 
		if (tempRetVal = bigInt_strTailAlignedAdd(str, &d_head, &d_tail,
												  s, &h, &t, &carry))
			return tempRetVal;
		if (carry == '1')
		{//if there's carry from decimal parts, add it into integer parts
			s[0] = '0';
			if (tempRetVal = bigInt_strTailAlignedAdd(str, &i_head, &i_tail,
													  s, &h, &t, &carry))
				return tempRetVal;
		}
		if (carry == '1')
		{//if there's carry from integer parts, insert it before i_head
			int insertBeforeThisPos = i_head;
			if (tempRetVal = bigInt_chInsertFromTail(str, &i_head, &d_tail, &strSize, 
													 &insertBeforeThisPos, carry))
				return tempRetVal;
		}
		int endPosition;
		if (round_digits == 0)
			endPosition = dp;		//write '\0' at dot position;
		else
			endPosition = d_tail;	//write '\0' at d_tail
		if (tempRetVal = bigInt_chSetAtPosition(str, &i_head, &d_tail, &strSize,
												&endPosition, '\0'))
			return tempRetVal;
		//notice: if there's '0' in the end of decimal parts, '0' is kept.
	}
	return 0;
}



源码打包上传

ver03.7z

10.75 KB, 下载次数: 6, 下载积分: 吾爱币 -1 CB

源码打包

免费评分

参与人数 1威望 +1 吾爱币 +10 热心值 +1 收起 理由
苏紫方璇 + 1 + 10 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

skrets 发表于 2026-2-22 22:32
可读性是挺好的,但这样搬运字符的写法有什么好处吗
转换成数字更好写,效率也更高吧
fkcp 发表于 2026-2-23 14:28
 楼主| wangarc 发表于 2026-2-24 14:32
skrets 发表于 2026-2-22 22:32
可读性是挺好的,但这样搬运字符的写法有什么好处吗
转换成数字更好写,效率也更高吧

只是一种实现方法而已。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-7-13 17:02

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表