我在MATLAB中实现的Frobenius规范溢出问题

时间:2017-10-13 22:16:34

标签: matlab math computer-science

我在MATLAB中实现了Forbenius规范的以下定义 https://puu.sh/xXsJZ/c42a5e9eac.png

以它描述的方式(即我做了2个循环,并通过平方每个元素增加了一个总和,最后我拿了总和的平方根)。

我的问题是,有没有办法实现这个规范,这样如果我在矩阵中输入一个相当大的数字,它的方块不会溢出?在某些情况下,该函数返回“Infinity”,即使真正的Forbenius规范可能远低于机器的溢出阈值。 (回想一下,在计算结束时取平方根。)

编辑:还存在下溢问题。即使元素ai,j不是太小,其正方形也可能下溢。在MATLAB中,一个 下溢的元素设置为0.现在只要其他一些元素很大 够了,结果仍然可以接受。另一方面,如果所有元素都下溢,我的函数可能会错误地返回0。

任何帮助?

在我的机器上产生无穷大的矩阵的一个例子是

[1,9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999; 1,1]

然而,当我使用内置的Frobenius规范函数时,它可以正常工作。为什么会这样?

2 个答案:

答案 0 :(得分:1)

以下代码虽然在Java中,但与Matlab在计算Frobenius规范时所做的工作非常接近。这里的诀窍是hypot函数,而不是仅仅执行x^2 + y^2,它计算斜边以避免欠流/过流。 hypot在matlab中可用,所以不要计算sqrt(x^2 + y^2),而是使用hypot,你应该能够避免欠流/过流。

public static double normFrob(double[][] matrix) {
    double norm = 0.0;
    int rows = matrix.length;
    int cols = matrix[0].length;
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < cols; ++j) {
            norm = hypot(norm, matrix[i][j]);
        }
    }
    return norm;
}

public static double hypot(double a, double b) {
    double r;
    if (Math.abs(a) > Math.abs(b)) {
        r = b / a;
        r = Math.abs(a) * Math.sqrt(1 + r * r);
    } else if (b != 0) {
        r = a / b;
        r = Math.abs(b) * Math.sqrt(1 + r * r);
    } else {
        r = 0.0;
    }
    return r;
}

此代码片段取自Jama,这是为了向Matrix引入Matrix库,而一些开发人员是Matlab人员。

答案 1 :(得分:0)

溢出保护可以通过各种方式完成。一种可能性是正常化。这是欧几里德规范,但想法是一样的

m_sum = 0;
y=max(abs(x));
for i=1:len(x)
  m_sum = m_sum + (x(i)/y)^2;
end
mynorm = y*sqrt(m_sum);