之前写过一套“大实数”的算法,但那一套采用的是C++、只有加法与乘法、注释残缺不全(Δεν ξέρω καν τι γράφω)。还是以一种负责的态度将源码重置一下吧。
/**
* @(#) BigInteger.h
* 作者:Legend_1949
* 编写日期:2019年1月9日
* 语言:C
**/
#pragma once
#include <string.h>
#include <stdlib.h>
// 设置大整数精度
#define PRECISION (25)
// 自定义类型
typedef struct
{
int valueArray[PRECISION];
} BigInteger;
typedef const char * String;
// 输入数值
BigInteger setValue(String _string)
{
// 初始化大整数结构体实例,所有位被初始化为0
BigInteger temp = { {0} };
// 获取大整数字符串的长度
int length = strlen(_string);
for (int i = length - 1, j = PRECISION - 1; i >= 0; i--, j--)
{
// 从右向左提取字符串的每一位数字,存入大整数数组中
temp.valueArray[j] = (int)(_string[i] - '0');
}
return temp;
}
// 读取数值
String getValue(BigInteger _bigInteger)
{
char *string = (char *)calloc(PRECISION + 1, sizeof(char));
string[PRECISION] = '\0';
for (int i = 0; i < PRECISION; i++)
{
// 从左到右将大整数数组的每一位转化为字符
string[i] = (char)(_bigInteger.valueArray[i] + '0');
}
// 不是所有位都有效(开头可能存在无意义的0),所以通过重设指针去除无效位
char *temp = string;
// 持续移指针到有效位上
while (*temp == '0')
{
temp++;
}
// 由于C中的字符串是通过字符数组实现的,所以返回指向字符串开头的指针
return temp;
}
// 大整数加法
BigInteger add(BigInteger _param1, BigInteger _param2)
{
// 新建空结果
BigInteger result = { {0} };
// 进位标记
int extra = 0;
// 加法运算从低位(右)向高位(左)进行
for (int i = PRECISION - 1; i >= 0; i--)
{
int sum = _param1.valueArray[i] + _param2.valueArray[i] + extra;
result.valueArray[i] = sum % 10;
extra = sum / 10;
}
return result;
}
// 大整数减法
BigInteger minus(BigInteger _param1, BigInteger _param2)
{
// 新建空结果
BigInteger result = { {0} };
// 借位标记
int borrow = 0;
// 减法运算从低位(右)向高位(左)进行
for (int i = PRECISION - 1; i >= 0; i--)
{
// 若被减数小于减数,则需要借位
if (_param1.valueArray[i] < _param2.valueArray[i])
{
result.valueArray[i] = 10 + _param1.valueArray[i] - _param2.valueArray[i] - borrow;
borrow = 1;
}
// 否则直接相减
else
{
result.valueArray[i] = _param1.valueArray[i] - _param2.valueArray[i] - borrow;
borrow = 0;
}
}
return result;
}
// 大整数乘法
BigInteger multipy(BigInteger _param1, BigInteger _param2)
{
// 新建空结果
// 由于乘法会导致数位快速增长,所以另外新建结果数组,清算后再截取
int temp[2 * PRECISION] = { {0} };
// 笛卡尔乘法,模拟竖式运算
// 第1步,乘数按位进行分配,得到各位的结果
for (int i = PRECISION - 1; i >= 0; i--)
{
for (int j = PRECISION - 1; j >= 0; j--)
{
// ★难点:此处需要通过下标对结果进行数位对齐
temp[i + j + 1] = temp[i + j + 1] + _param1.valueArray[j] * _param2.valueArray[i];
}
}
// 第2步,清算分配结果和进位
int extra = 0;
for (int i = PRECISION - 1; i >= 0; i--)
{
int sum = temp[i] + extra;
temp[i] = sum % 10;
extra = sum / 10;
}
// 新建空白结果
BigInteger result = { {0} };
// 忽略真实结果左侧超出精度的值
for (int i = 0; i < PRECISION; i++)
{
result.valueArray[PRECISION - i - 1] = temp[2 * PRECISION - i - 1];
}
return result;
}
// 大整数比较
int compare(BigInteger _param1, BigInteger _param2)
{
// 从高位(左)向低位(右),逐位比对
for (int i = 0; i < 25; i++)
{
// 小于为-1
if (_param1.valueArray[i] < _param2.valueArray[2])
{
return -1;
}
// 大于为1
else if (_param1.valueArray[1] > _param2.valueArray[2])
{
return 1;
}
}
// 完全相同则为0
return 0;
}
// 大整数除法
BigInteger divide(BigInteger _param1, BigInteger _param2)
{
// 说实话,我也不知道除法要怎么写
}