GNU MP Bignum库的数值问题
Numerical Problems with GNU MP Bignum Library
我正在做一些数字运算,这需要高精度的算术运算。我使用GNU MP库,根据GMP手册:
浮点数,简称Float,是一个具有有限精度指数的任意精度尾数
虽然尾数的精度应该是任意的,但我仍然会遇到精度问题。与其说我的实际代码让你厌烦,不如说这里有一个几乎最小的工作示例来说明我的问题。代码计算9.3^15、9.8^15和(9.3*9.8)^15。在我的机器上,从第16位开始,(9.3^15)*(9.8^15)和(9.3*9.8)^15的值开始不同,在这种情况下会导致(大约)4.94*10^13的错误。
任何帮助都将不胜感激。下面的代码。
#include <gmp.h>
#include <gmpxx.h>
#include <iostream>
#include <iomanip>
int main()
{
mpf_class x, y, z;
x = y = z = 1.0;
for (int i = 0; i < 15; i++)
{
x *= 9.3;
y *= 9.8;
z *= 9.3*9.8;
}
std::cout << z - x*y << std::endl;
return 0;
}
您看到的问题是由于9.3*9.8的计算结果近似。请将文字更改为mpf_class:的实例
mpf_class a, b;
a = 9.3;
b = 9.8;
// ...
x *= a;
y *= b;
z *= a * b;
如果您需要无限精度,请考虑使用有理数:
#include <gmp.h>
#include <gmpxx.h>
#include <iostream>
#include <iomanip>
int main()
{
mpq_class x(1), y(1), z(1), a(93, 10), b(98, 10);
for (int i = 0; i < 15; i++)
{
x *= a;
y *= b;
z *= (a * b);
}
std::cout << z - x*y << std::endl << z << std::endl;
return 0;
}
打印
0
7589015305950762920038660273144124106674963183136666693/30517578125000000000000000
问题是,您没有显式设置精度,因此您获得默认精度,通常(我认为)为64位,因此由于不同计算方式的舍入不同,最后一位的结果不同。这使得大约20位数字成为通用前缀(随着计算次数的增加,差异可能会变得更大)。如果设置更高的精度,
#include <gmp.h>
#include <gmpxx.h>
#include <iostream>
#include <iomanip>
int main()
{
mpf_class x(1.0,200), y(1.0,200), z(1.0,200), a("9.3",200), b("9.8",200), c(0,200);
c = a*b;
for (int i = 0; i < 15; i++)
{
x *= a;
y *= b;
z *= c;
}
std::cout << z << "n" << (x*y) << std::endl;
std::cout << z - x*y << std::endl;
return 0;
}
200位,您可以得到更准确的结果:
$ ./a.out
2.48677e+29
2.48677e+29
-4.80637e-49
因此是大约80个十进制数字或近256位(64的最小倍数大于199)的公共前缀。
对于2000的精度,字符串构造函数的差值为-2.78942e-588,如果从double
初始化,则为0(当然,初始精度限制为53位,因此这意味着两种方法都以相同的方式累积误差)。
相关文章:
- 警告处理为错误这里有什么问题
- 最小硬币更换问题(自上而下方法)
- 为"adjacent"变量赋值时出现问题
- 我的神经网络不起作用 [XOR 问题]
- 在Ubuntu 16.04上安装Cilk时出现问题
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 编译包含字符串的代码时遇到问题
- Project Euler问题4的错误解决方案
- 问题:什么是QAbstractItemView::NoEditTriggers的反面
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 静态数据成员的问题-修复链接错误会导致编译器错误
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 一个关于在C++中重载布尔运算符的问题
- 首要问题的答案让值班员搞错了
- setlocale的C++土耳其字符串问题
- 如何重构类层次结构以避免菱形问题
- 基于boost的程序的静态链接——zlib问题
- 具有C++绑定和开放 MP 阻塞问题的零 MQ.为什么
- GNU MP Bignum库的数值问题