浮点高精度
简单封装了一下浮点加法乘法,未验证
struct BigFloat {
static const int N = 100, n = 16; //位数,保留位数
vector<int> integer;//整数部分(逆序存储)123. -->321.
vector<int> decimal;//小数部分(正序存储).456 -->.456
int integerSize;//整数长度
int decimalSize;//小数长度
BigFloat() {
init();
}
BigFloat(const string& s) {
init();
*this = s;
}
BigFloat(const double& val) {
init();
*this = val;
}
void init() {
integer.reserve(N); decimal.reserve(N);
integer.resize(N); decimal.resize(N);
integerSize = 0; decimalSize = 0;
}
BigFloat operator = (const double& value) {
(*this).init();
ostringstream oss;
oss << fixed << setprecision(n) << value;//保留精度
*this = oss.str();
return *this;
}
BigFloat operator = (const string &s) {
(*this).init();
int idx;
for (idx = 0; s[idx] != '.'; idx ++); //定位小数点下标
int len = (int)s.size();
for (int i = idx + 1 ; i < len ; i++) { //正序存储小数部分
decimal[decimalSize++] = s[i] - '0';
}
for (int j = idx - 1; j >= 0 ; j--) { //逆序存储整数部分
integer[integerSize++] = s[j] - '0';
}
return *this;
}
BigFloat operator + (const BigFloat &a) { //重载加法运算符
BigFloat ret;//保存返回结果
int qLen = decimalSize > a.decimalSize ? decimalSize : a.decimalSize;//小数长度
int carry = 0;//保存进位,以及小数到整数部分的进位
ret.decimalSize = qLen;
for (int i = qLen - 1 ; i >= 0 ; i--) { //小数部分相加
int tmp = decimal[i] + a.decimal[i] + carry;
ret.decimal[--qLen] = tmp % 10; //保存结果
carry = tmp / 10; //更新进位
}
int pLen = integerSize > a.integerSize ? integerSize : a.integerSize;//整数长度
for (int j = 0 ; j < pLen ; j++) { //整数部分相加
int tmp = integer[j] + a.integer[j] + carry;
ret.integer[ret.integerSize++] = tmp % 10; //保存结果
carry = tmp / 10; //更新进位
}
if (carry != 0) { //当前进位不为0,进位并保存下来
ret.integer[ret.integerSize++] = carry;
}
return ret;
}
BigFloat operator += (const BigFloat& a) {
*this = *this + a;
return *this;
}
BigFloat operator * (const string& num2) {
string num1 = str();
*this = mul(num1, num2);
return *this;
}
BigFloat operator * (double value) {
ostringstream num2;
num2 << fixed << setprecision(n) << value;//保留精度
string num1 = str();
*this = mul(num1, num2.str());
return *this;
}
BigFloat operator * (BigFloat num2) {
string num1 = str();
*this = mul(num1, num2.str());
return *this;
}
string str() {
string res = "";
int i = integerSize - 1;
while (integer[i] == 0 && i >= 0 )i--; //移除高位的0
if (i == -1) {
res += "0";
} else {
while (i >= 0) { //倒序输出整数部分
res += integer[i--] + '0';
}
}
int j = decimalSize - 1;
while (decimal[j] == 0 && j >= 0) j--; //移除小数部分低位0,并保存小数部分有效长度
if (j != -1) {
res += ".";
for (int k = 0; k <= j; k ++) { //输出小数部分
res += decimal[k] + '0';
}
}
return res;
}
friend ostream& operator << (ostream& out, const BigFloat& x) {
int i = x.integerSize - 1;
while (x.integer[i] == 0 && i >= 0 )i--; //移除高位的0
if (i == -1) {
out << "0";
} else {
while (i >= 0) { //倒序输出整数部分
out << x.integer[i--];
}
}
int j = x.decimalSize - 1;
while (x.decimal[j] == 0 && j >= 0) j--; //移除小数部分低位0,并保存小数部分有效长度
if (j != -1) {
out << ".";
for (int k = 0; k <= j; k ++) {
out << x.decimal[k];
}
}
return out;
}
friend istream& operator >> (istream& in, BigFloat& x) {
string s;
in >> s;
x = s;
return in;
}
// 将字符串形式的数字(带小数点)转换为倒序存储的整数数组,并记录小数点位置
pair<vector<int>, int> stringToVector(const string& num) {
vector<int> result;
int decimalPos = 0;
bool isDecimal = false;
for (int i = num.size() - 1; i >= 0; --i) {
if (num[i] == '.') {
isDecimal = true;
decimalPos = num.size() - 1 - i;
} else {
result.push_back(num[i] - '0');
}
}
if (!isDecimal) decimalPos = 0;
return {result, decimalPos};
}
// 将倒序存储的整数数组转换为字符串形式的数字,并处理小数点位置
string vectorToString(const vector<int>& num, int decimalPos) {
string result;
bool leadingZero = true;
for (int i = num.size() - 1; i >= 0; --i) {
if (leadingZero && num[i] == 0 && i >= decimalPos) continue;
leadingZero = false;
if (i == decimalPos - 1 && i != 0) {
result.push_back('.');
}
result.push_back(num[i] + '0');
}
if (leadingZero) return "0";
if (decimalPos == 0) return result;
if (result.size() <= decimalPos) result.insert(result.begin(), decimalPos - result.size(), '0');
return result;
}
// 高精度浮点数乘法
string mul(const string& num1, const string& num2) {
auto [n1, d1] = stringToVector(num1);
auto [n2, d2] = stringToVector(num2);
vector<int> result(n1.size() + n2.size(), 0);
for (size_t i = 0; i < n1.size(); ++i) {
for (size_t j = 0; j < n2.size(); ++j) {
result[i + j] += n1[i] * n2[j];
if (result[i + j] >= 10) {
result[i + j + 1] += result[i + j] / 10;
result[i + j] %= 10;
}
}
}
// 计算小数点位置
int decimalPos = d1 + d2;
// 去掉前导0
while (result.size() > 1 && result.back() == 0) {
result.pop_back();
}
return vectorToString(result, decimalPos);
}
};