双精度浮点数会溢出成负值吗?

3

你好,我正在使用g++编译器,并且遇到了(我认为)double类型的下溢问题,这是否可能发生,如果是,行为如何定义?

我已经上传了协方差矩阵的csv格式(51x51):http://pastebin.com/r0fx1qsx

这是我使用的计算行列式的代码(需要boost库,现已切换到long double类型,但没有影响):

int determinant_sign(const boost::numeric::ublas::permutation_matrix<std ::size_t>& pm)
{
    int pm_sign=1;
    std::size_t size = pm.size();
    for (std::size_t i = 0; i < size; ++i)
        if (i != pm(i))
            pm_sign *= -1.0; // swap_rows would swap a pair of rows here, so we change sign
    return pm_sign;
}

long double determinant( boost::numeric::ublas::matrix<long double>& m ) {
    boost::numeric::ublas::permutation_matrix<std ::size_t> pm(m.size1());
    long double det = 1.0;

    if( boost::numeric::ublas::lu_factorize(m,pm) ) {
        det = 0.0;
    } else {
        for(int i = 0; i < (int)m.size1(); i++)
            det *= m(i,i); // multiply by elements on diagonal
        det = det * determinant_sign( pm );
    }
    return det;
}

我得到的数据结果是-3.59916e-183

当我运行以下matlab代码时:

M = csvread('path/to/csv');
det(M)
the result I get is:

4.2014e-173

正如您所看到的,其中一个是(稍微)积极的,而另一个是(稍微)消极的。


1
你能展示一下代码吗? - David G
2
请展示代码,将double类型的数值加上一个值不会使其变小,所以你必须在做其他操作。 - PlasmaHH
2
那个数字太小了,可能只是由于计算误差而被简单地视为零! - Shahbaz
2
你尝试使用MPFR提供的数字类型和大精度计算它了吗?使用Eigen计算,尝试几种可用的算法?对我来说,这听起来像是一个简单的数值稳定性问题。 - Marc Glisse
@Aly 谷歌?(任意精度浮点类型) - Marc Glisse
显示剩余7条评论
1个回答

4

假设浮点单元正常运行,如果值超出有效范围,它不会溢出到负值 - 结果将是“+INF”(正无穷大)。这只会发生在有符号整数中。

当期望得到正数答案时,计算可能会产生负数的各种错误。


从技术上讲,这不应该是+HUGE_VAL吗?具体取决于目标构建环境支持的浮点标准,它可能是+INFINITY或+DBL_MAX。 - Charles L Wilcox
我一直在使用IEEE的+INF值,这是浮点数最常见的格式。但是,是的,在某些C/C++头文件中有一个常量。虽然我不完全确定这是否对答案的含义有很大影响。 - Mats Petersson
这并不意味着您永远不会从浮点计算中获得意外的负值(http://www.exploringbinary.com/the-answer-is-one-unless-you-use-floating-point/)。 - Rick Regan
是的,这就是我想说的,“在计算中出现各种错误当然是完全可能的…” [在链接中给出的例子中,这是“故意”的,但主要原因是0.1不能精确地表示为二进制数,所以乘以0.1的结果略微偏差,当你开始使用非常大的数字时,舍入效应会导致结果为负数。 - Mats Petersson
@Mats Petersson 我不知道我第一次是怎么误读那行的,但是是的,我基本上只是重复了你说的 :) - Rick Regan

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