对于一些大学作业,我必须近似一些数字-比如用级数表示的欧拉数。因此,我必须添加非常小的数字,但我在精度方面存在问题。如果数字非常小,则不会影响结果。
real s; //sum of all previous terms
ulong k; //factorial
s += 1.0/ k;在每一步之后,k变得更小,但在第10轮之后,结果不再变化,停留在2.71828
发布于 2011-02-10 23:15:20
如果您需要一个使用本机类型运行的解决方案,您应该能够通过总是尝试添加类似大小的数字来获得合理的结果。一种方法是计算级数的前X项,然后用它们的和重复替换最小的两个数字:
auto data = real[N];
foreach(i, ref v; data) {
v = Fn(i);
}
while(data.length > 1) {
data.sort(); // IIRC .sort is deprecated but I forget what replaced it.
data[1] += data[0];
data = data[1..$];
}
return data[0];(最小堆将使这一过程更快一些。)
发布于 2011-02-09 22:58:05
固定精度浮点类型,即CPU的浮点单元(float、double、real)本身所支持的浮点类型,对于任何需要很多精度的计算都不是最优的,比如您给出的例子。
问题是,这些浮点类型的精度(实际上是二进制数字)的位数有限,这限制了这种数据类型可以表示的数字的长度。float类型的限制大约为7位小数(例如3.141593);double类型的限制为14位(例如3.1415926535898);real类型的限制类似(略高于double的限制)。
因此,将极小的数字添加到浮点值将导致这些数字丢失。当我们将以下两个浮点值相加时,看看会发生什么:
float a = 1.234567f, b = 0.0000000001234567
float c = a + b;
writefln("a = %f b = %f c = %f", a, b, c);a和b都是有效的浮点值,并且各自单独保留大约7位精度。但当添加时,只有最前面的7位数字被保留,因为它被推回到浮点数中:
1.2345670001234567 => 1.234567|0001234567 => 1.234567
^^^^^^^^^^^
sent to the bit bucket所以c最终等同于a,因为a和b相加后的精度更高的数字被去掉了。
Here's another explanation of the concept,可能比我的好多了。
这个问题的答案是任意精度的算术。不幸的是,CPU硬件中没有对任意精度算术的支持;因此,(通常)在您的编程语言中没有这种支持。但是,有许多库支持任意精度浮点类型和要对其执行的数学运算。有关建议,请参阅this question。今天,您可能找不到任何用于此目的的特定于D的库,但是有大量的C库(GMP、MPFR等)应该可以很容易地独立使用,如果您能找到其中一个的D绑定,就更容易了。
发布于 2011-02-11 01:03:09
如前所述,您需要使用一些第三方的多精度浮点算术库(我认为Tango或Phobos只有一个用于任意长度的整数运算的模块)。
dil是一个使用MPFR的D项目。您应该可以在那里找到绑定。
https://stackoverflow.com/questions/4944694
复制相似问题