java中有bigDecimal ,来进行高精度计算,现在移植到qt程序,如何进行高精度计算,并可以设置保留多少位小数
QT中没有现成的库或者类,需要自己封装一下,下面的连接中,有高精度计算的例子供参考:
在 Qt 中实现高精度计算的方法和具体实现取决于具体的需求。以下是几种常用的实现方式:
QString
类型如果精度不是非常高,可以使用 QString
类型进行计算。可以使用 QVariant
将 QString
转换为 double
或 int
,然后进行计算。例如:
#include <QVariant>
#include <QDebug>
int main()
{
QVariant a = "12345678901234567890";
QVariant b = "98765432109876543210";
qDebug() << a.toDouble() + b.toDouble(); // 高精度加法
qDebug() << a.toDouble() * b.toDouble(); // 高精度乘法
return 0;
}
Qt 中常用的第三方高精度计算库有 GMP(GNU Multiple Precision Arithmetic Library)和 MPFR(Multiple Precision Floating-Point Reliable Library)。这些库在 Ubuntu 系统中可以使用 apt-get 命令安装。在 Qt 中,可以通过链接这些库的方式来进行高精度计算。例如:
#include <gmpxx.h>
#include <QDebug>
int main()
{
mpz_class a = "12345678901234567890";
mpz_class b = "98765432109876543210";
qDebug() << a + b; // 高精度加法
qDebug() << a * b; // 高精度乘法
return 0;
}
如果对于精度要求极高,或者只需要支持加减乘除四则运算,可以手写高精度计算。这种方式的实现较为复杂,需要编写大量代码。以下是一个简单的示例:
好的,以下是一个简单的多精度计算类 MultiPrecision
的实现示例,包含详细的注释:
#include <QDebug>
// 基数,相当于十进制中的 10 的 9 次方
#define BASE 1000000000
class MultiPrecision {
public:
MultiPrecision() {}
// 通过 int 类型初始化
MultiPrecision(int n) {
while (n > 0) {
data.push_back(n % BASE);
n /= BASE;
}
}
// 通过 QString 类型初始化
MultiPrecision(QString str) {
for (int i = str.size() - 1; i >= 0; i -= 9) {
int x = 0;
// 从高位到低位取出 9 位数字
for (int j = qMax(0, i - 8); j <= i; j++) {
x = x * 10 + str[j].digitValue();
}
data.push_back(x);
}
}
// 多精度加法
MultiPrecision operator+(const MultiPrecision &other) {
MultiPrecision res;
int t = 0, k = 0;
// 对于两个多精度数的每一位进行相加
while (k < data.size() || k < other.data.size() || t > 0) {
// 如果有一方的长度已经加完,只需将另一方的数值加上,不需要再对已经加完的数值做处理
if (k < data.size()) t += data[k++];
if (k < other.data.size()) t += other.data[k++];
res.data.push_back(t % BASE);
t /= BASE;
}
return res;
}
// 多精度减法
MultiPrecision operator-(const MultiPrecision &other) {
MultiPrecision res;
int t = 0, k = 0;
// 对于两个多精度数的每一位进行相减
while (k < data.size() || k < other.data.size() || t < 0) {
if (k < data.size()) t += data[k++];
if (k < other.data.size()) t -= other.data[k++];
if (t < 0) {
res.data.push_back(t + BASE);
t = -1;
} else {
res.data.push_back(t);
t = 0;
}
}
while (res.data.size() > 1 && res.data.back() == 0) {
res.data.pop_back();
}
return res;
}
// 多精度乘法
MultiPrecision operator*(const MultiPrecision &other) {
MultiPrecision res;
res.data.resize(data.size() + other.data.size());
// 将第 i 位和第 j 位相乘,结果存入 (i+j+1) 位,进位存入 (i+j) 位
for (int i = 0; i < data.size(); i++) {
int t = 0;
for (int j = 0; j < other.data.size(); j++) {
res.data[i + j] += data[i] * other.data[j] + t;
t = res.data[i + j] / BASE;
res.data[i + j] %= BASE;
}
res.data[i + other.data.size()] += t;
}
while (res.data.size() > 1 && res.data.back() == 0) {
res.data.pop_back();
}
return res;
}
// 多精度除法,返回除数和余数,q 和 r 均为多精度数
void divide(const MultiPrecision &other, MultiPrecision &q, MultiPrecision &r) {
int len = data.size() - other.data.size() + 1;
if (len < 0) {
q.data.push_back(0);
r = *this;
return;
}
MultiPrecision d = other * BASE;
d.data.resize(d.data.size() + 1);
q.data.resize(len);
r.data.resize(other.data.size() + 1);
for (int i = len - 1; i >= 0; i--) {
r = r * BASE;
r.data[0] = data[i + other.data.size()];
int s1 = d.data.back() * (r.data.back() + 1);
int s2 = qMax(0, s1 / BASE - d.data.back+ 1);
// 判断商 q[i] 是否正确,如果大于 10 的 9 次方,需要调整,并根据余数进行调整
while (s2 * d.data[d.data.size() - 2] > s1 - s2 * BASE || s2 >= BASE) {
s2--;
s1 -= d.data[d.data.size() - 2];
}
q.data[i] = s2;
MultiPrecision tmp = d * s2;
r = r - tmp;
}
while (q.data.size() > 1 && q.data.back() == 0) {
q.data.pop_back();
}
while (r.data.size() > 1 && r.data.back() == 0) {
r.data.pop_back();
}
}
// 重载输出流运算符
friend QDebug operator<<(QDebug debug, const MultiPrecision &mp) {
for (int i = mp.data.size() - 1; i >= 0; i--) {
if (i == mp.data.size() - 1) {
debug << mp.data[i];
} else {
debug << QString("%1").arg(mp.data[i], 9, 10, QChar('0'));
}
}
return debug;
}
// 数值数组,存储多精度数每一位的值
QVector<int> data;
};
int main()
{
// 通过 int 类型初始化多精度数
MultiPrecision a(12345678);
qDebug() << a;
// 通过 QString 类型初始化多精度数
MultiPrecision b("123456789012345678901234567890");
qDebug() << b;
// 多精度加法
MultiPrecision c = a + b;
qDebug() << c;
// 多精度减法
MultiPrecision d = b - a;
qDebug() << d;
// 多精度乘法
MultiPrecision e = a * b;
qDebug() << e;
// 多精度除法
MultiPrecision f;
MultiPrecision g;
b.divide(a, f, g);
qDebug() << f << g;
return 0;
}
这个例子实现了多精度加减乘除运算,包括重载的加减运算符、乘除运算函数和输出流运算符。这个类的主要思路是将多精度数按照基数分成若干位存储,然后对于每一位进行相应的运算。由于原理比较简单,上面的代码注释比较详细,可以作为参考。当然由于实现过程比较繁琐,这种方式在实际开发中并不常见。