比double更精确的浮点数据类型?

11

在我的项目中,我需要对一个包含double元素的矩阵进行除法、乘法、减法和加法运算。问题是,当矩阵大小增加时,输出的精度会严重受到影响。

目前,我为每个元素使用 double,这种类型使用 8字节 的内存,无论小数点位置如何,它的精度都是 16位数字。即使对于大型矩阵,所有元素占用的内存也在几千字节的范围内。因此,我可以承担使用需要更多内存的 数据类型

所以我想知道哪种数据类型比 double 更精确。

我尝试在一些书籍中搜索,发现了 long double。但我不知道它的精度是多少。

如果我想要比这更高的精度怎么办?


1
请查看GMP项目。此外,还有一些方法可以最小化计算中的舍入误差。 - brian beuning
如果你需要依赖外部库,Boost 1.53有一个多精度库可以帮助你! - Hugo Corrá
1
使用一些代数方法重新排列数学计算可以帮助减少舍入误差。 - Ed Heal
1
转换为更大的类型只是延迟了数字崩溃的时间。要完全避免它,拿出一本数值分析书并阅读“稳定性”章节。 - Raymond Chen
1
数值崩溃是您正在经历的现象:舍入误差会累积并导致错误答案。 - Raymond Chen
显示剩余8条评论
4个回答

13
根据维基百科,80位“英特尔”IEEE 754 扩展精度long double是指在内存中填充为16字节的80个位,其中有64位尾数,没有隐式位,可以获得19.26个十进制数字。这已经是长期以来long double的几乎普遍标准,但最近情况开始发生变化。
新的128位四倍精度格式具有112个尾数位和一个隐式位,可以获得34个十进制数字。GCC将其实现为__float128类型,如果我没记错的话,有一个编译器选项可以将long double设置为它。

那么,在速度和精度之间存在的权衡考虑下,你会推荐使用哪个,长双精度(long double)还是__float128呢? - Cool_Coder
@Cool_Coder 我不知道你的程序特性,但既然很容易,就两个都试试吧! - Potatoswatter
好的,我会翻译并告诉您。为了确认一下,请让我知道以下代码是否正确:__float128 *nicePrecision = new __float128(); - Cool_Coder
128位浮点数并不是很新的技术。在SPARC上,它们被称为“long double”类型,已经存在了很长时间(也就是说,超过20年)。 - Pete Becker
只需要注意一点:目前GCC将double优化为MMX,将long double优化为FPU指令。这会影响性能。 - ajeh
显示剩余5条评论

7

您可能需要考虑操作的顺序,即从最小值开始按有序序列进行加法运算。这将在使用相同尾数精度的情况下增加结果的总体准确性:

1e00 + 1e-16 + ... + 1e-16 (1e16 times) = 1e00
1e-16 + ... + 1e-16 (1e16 times) + 1e00 = 2e00

重点是将小数加到大数上会使它们消失。因此,后一种方法减少了数值误差。

3

具有比double更高精度的浮点数据类型将取决于您的编译器和架构。

为了获得比double更高的精度,您可能需要依赖一些支持任意精度计算的数学库。但这些库的速度可能较慢。


这可能不够快。不够快用于什么?你是如何得出这个结论的?如果需要更高的精度,您建议采取哪些替代方案? - us2012
1
你似乎有点忽视了long double的存在。同样的问题确实存在,但影响要小得多。 - Potatoswatter
1
@us2012,我只是说可能不会很快,而不是不够快。因此,是的,它很大程度上取决于OP想要做什么。如果我知道一个数学库,我会建议使用它,但我对这种任意精度的经验仅限于其他语言。 - Telgin

0
在Intel架构中,long double的精度为80位
你想要表示什么样的值?也许使用固定精度会更好。

“long float”? 真的吗?80位精度,指数部分有多少位? - Potatoswatter
1
取决于编译器;在微软编译器中,long doubledouble 具有相同的精度。 - Pete Becker
我是指长双精度浮点数,只是出了一些小问题。 - fons

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接