求歐拉范數(shù)是一個比較簡單的算法,似乎沒有什么可說的,一般代碼如下:
/** \fn double enorm1(long n, const double* x)
* \brief 求歐拉范數(shù),簡單算法。
* \param [in] n 向量長度
* \param [in] x 向量值
* \return 歐拉范數(shù)
*/
double enorm1(long n, const double* x)
{
double ret = 0.0;
long i = 0;
for (i=0; i<n; ++i)
ret += x[i]*x[i];
return sqrt(ret);
}
然而近日在學習minpack時,發(fā)現(xiàn)它求歐拉范數(shù)的函數(shù)enorm則要復雜得多。仔細比較發(fā)現(xiàn)上面算法有不足,它沒有考慮溢出的情況,當x[i]為很小或者很大的數(shù)時,x[i]*x[i]則會下溢或者上溢,最后結果可能不準確。但x[i]*x[i]只是中間結果,最后的范數(shù)數(shù)量級應該和x[i]相同。它溢出的可能性要小得多。改進中間結果則可以改進算法。
/** \fn double enorm2(long n, const double* x)
* \brief 求歐拉范數(shù),考慮溢出的算法。
* \param [in] n 向量長度
* \param [in] x 向量值
* \return 歐拉范數(shù)
*/
double enorm2(long n, const double *x)
{
double ret = 0.0;
long i= 0;
double xmax = 0.0;
for (i=0; i<n; ++i)
{
double xabs = fabs(x[i]);
/* 這個比較方式不需要考慮xabs和xmax為0的情況 */
if (xabs < xmax)
{
ret += (xabs/xmax)*(xabs/xmax);
}
else if (xabs == xmax)
{
ret += 1;
}
else
{
ret = 1 + ret*(xmax/xabs)*(xmax/xabs);
xmax = xabs;
}
}
return sqrt(ret) * xmax;
}
將中間結果改成(x[i]/xmax)*(x[i]/xmax),降低了溢出的可能。當然該算法沒有區(qū)分可能溢出和不溢出的數(shù),計算量較大。下面的算法是仿照minpack的enorm函數(shù)編寫:
/** \fn double enorm3(long n, const double* x)
* \brief 求歐拉范數(shù),仿照minpack的enorm函數(shù)
* \param [in] n 向量長度
* \param [in] x 向量值
* \return 歐拉范數(shù)
*/
double enorm3(long n, const double *x)
{
double s1 = 0.0;
double s2 = 0.0;
double s3 = 0.0;
/* 上溢和下溢的邊界,不一定要十分精確 */
const double dwarf = 1.483e-154; /* 下溢的邊界 */
const double giant = 1.341e154 / n; /* 上溢的邊界 */
double x1max = 0.0;
double x3max = 0.0;
long i = 0;
for (i=0; i<n; ++i)
{
double xabs = fabs(x[i]);
if (xabs > dwarf && xabs < giant)
{
s2 += xabs*xabs;
}
else if (xabs <= dwarf)
{
/* 這個比較方式不需要考慮xabs和xmax為0的情況 */
if (xabs < x3max)
{
s3 += (xabs/x3max)*(xabs/x3max);
}
else if (xabs == x3max)
{
s3 += 1;
}
else
{
s3 =1 + s3*(x3max/xabs)*(x3max/xabs);
x3max = xabs;
}
}
else /* if (xabs >= giant) */
{
/* 不需要考慮xabs和xmax為0的情況 */
if (xabs <= x1max)
{
s1 += (xabs/x1max)*(xabs/x1max);
}
else if (xabs == x1max)
{
s1 += 1;
}
else
{
s1 =1 + s1*(x1max/xabs)*(x1max/xabs);
x1max = xabs;
}
}
}
if (s1 != 0.0)
{
return x1max*sqrt(s1 + s2/x1max/x1max);
}
else if (s2 != 0.0)
{
return sqrt(s2 + x3max*x3max*s3);
/* 下面為minpack中enorm的代碼,好像沒有必要
if (s2 >= x3max)
return sqrt(s2 * (1 + x3max/s2*x3max*s3));
else
return sqrt(x3max * (s2/x3max + x3max*s2));
*/
}
else
{
return x3max * sqrt(s3);
}
}
下面是測試結果:
向量
|
enorm1
|
enorm2
|
enorm3
|
{1, 2, 3}
|
3.74166
|
3.74166
|
3.74166
|
{1e200, 2e200, 3e200}
|
1.#INF
|
<td style="BORDER-RIGHT: rgb(0,0,0) 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0pt; BO
導航
|
|
26 | 27 | 28 | 29 | 30 | 31 | 1 |
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 1 | 2 | 3 | 4 | 5 |
常用鏈接
留言簿(4)
隨筆檔案
文章檔案
搜索
最新隨筆
最新評論

閱讀排行榜
評論排行榜
欧美黑人激情性久久|
久久久久久无码Av成人影院|
69久久夜色精品国产69|
99久久无码一区人妻a黑|
久久精品国产91久久麻豆自制|
国产真实乱对白精彩久久|
久久精品中文字幕一区|
精品国产一区二区三区久久久狼
|
少妇久久久久久久久久|
国产91久久精品一区二区|
欧美麻豆久久久久久中文|
久久久一本精品99久久精品66|
国产成人精品久久综合
|
亚洲AV无码成人网站久久精品大|
久久久无码一区二区三区|
伊人色综合久久|
久久天天躁狠狠躁夜夜躁2O2O
|
日韩亚洲欧美久久久www综合网|
人妻系列无码专区久久五月天|
少妇久久久久久被弄高潮|
欧美国产成人久久精品|
国产人久久人人人人爽|
波多野结衣AV无码久久一区|
精品熟女少妇aⅴ免费久久|
91久久精品91久久性色|
久久久精品人妻一区二区三区蜜桃|
99久久人人爽亚洲精品美女|
久久夜色精品国产网站|
久久久无码精品亚洲日韩京东传媒
|
欧美色综合久久久久久|
97久久精品人人澡人人爽|
99999久久久久久亚洲|
久久99精品久久久大学生|
内射无码专区久久亚洲|
精品久久久久久久久久中文字幕
|
久久这里只有精品18|
久久久久久国产精品无码下载|
精品综合久久久久久88小说|
国产精品免费久久久久久久久|
国产精品va久久久久久久|
日韩精品久久久久久|