通过下溢趋近于零

3
请忽略此帖子,我误读了算法,所以问题不相关。但是,我无法再关闭帖子了。请投票关闭。
我一直在使用数值计算的某个算法,该算法通过下溢收敛到零:
// all types are the same floating type
sum = 0
for (i in 0,N)
   sum += abs(V[i]);

我的问题是,这是如何发生的?小正浮点数之和如何收敛到下溢/零?

是否存在某些条件,使得 0 + f = 0,f > 0

所涉及的算法是雅可比算法,http://www.mpi-hd.mpg.de/astrophysik/HEA/internal/Numerical_Recipes/f11-1.pdf,第460页。如果我误解了收敛是如何实现的,请指正我。

谢谢


也许告诉我们你正在使用哪些类型和编译器会更好。 - InsertNickHere
@Insert不重要,只要下溢设置为零即可。类型是任何IEEE浮点数,32位或64位。 - Anycorn
那么,这里需要一些大师的帮助,我无法想象每种语言都是相同的。 - InsertNickHere
1
他在询问当两个浮点数a和b都是正数时,为什么a + b == 0。 - BlueRaja - Danny Pflughoeft
3个回答

2
如果V是一个由doubles组成的数组,而sum是一个float(或single),你肯定可以有数值大于0,但当它们加到sum上时,如果它们小于float中最小的非零反规格化值,则会产生0。
你怎么知道sum实际上是零而不仅仅是非常接近零?所有的位都被设置为零吗?
编辑:在阅读实际应用程序后,归零下溢的评论可能是指重复旋转各个轴以确定矩阵的特征值和特征向量。在这种情况下,只有当您可以假设多次乘以非常小的数字将夹紧或下溢为零时,算法才能起作用。实际总和本身不会下溢。

假设sum已经包含了FLT_MIN,并且一个任意小的值被加到了它上面,那么如何才能使正确舍入的结果比sum更小呢?我之所以问这个问题是因为sum总是比0更接近于精确结果。 - Roland Illig
@Roland,他没有说sum被初始化为多少,但我假设它是0。而且double可以比FLT_MIN还要小。收敛于零和二进制为0是两码事。但是没错,sum应该单调递增。 - MSN
请转到以下网址:http://www.mpi-hd.mpg.de/astrophysik/HEA/internal/Numerical_Recipes/f11-1.pdf,第460页。所有类型都相同。 - Anycorn

1
你使用的类型是什么?如果f是浮点数,d1和d2是双精度浮点数,那么你会得到这个结果。
double d1 = std::numeric_limits<double>::min();
double d2 = std::numeric_limits<double>::min();
float f = d1 + d2;
if (f == 0.0) std::cout << "yes";
else std::cout << "no";

这将产生“是”的结果。


你们SO的成员真是太快了。像我这样的新手怎么才能获得声望呢,我们总是赶不上别人的节奏。 ;) - cape1232
1
@cape1232,我们都是这样开始的。你应该看看litb对于深奥的C++问题的回答有多快。或者说Jon Skeet一般情况下也是如此。 - MSN
@MSN litb确实非常有帮助。他为我解答了许多问题,非常感谢他。 - Anycorn

0

使用IEEE 754算术运算实现这一点我会非常惊讶。问题在于IEEE 754规定中间结果是无限精确的,然后舍入到目标数据类型。

因此,如果你有sum + V[i],那个值将始终大于或等于sum。向下舍入到下一个可表示的数字将产生sum或大于sum的数字。

当然,原始问题中没有任何阻止sum首先为负数的内容。在这种情况下,答案将是微不足道的。

在IEEE 754算术中,不存在一个数字f,使得0 + f = 0并且同时f > 0


谢谢,我在问题中添加了更多信息,包括源代码链接。 - Anycorn

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