メイン svdcmp.html Last modified: Sep 01, 2009
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;CHARSET=EUC-JP">
<link rel="shortcut icon" href="../favicon.ico">
<title>JavaScript</title>
<script src="io.js">document.write("io.js ファイルが見つかりません??<br>")</script>
<script language="JavaScript">
<!--
function square(a)
{
return a == 0 ? 0 : a*a
}
function pythag(a, b)
{
var absa, absb
absa = Math.abs(a)
absb = Math.abs(b)
if (absa > absb) {
return absa * Math.sqrt(1 + square(absb / absa))
}
else if (absb == 0) {
return 0
}
else {
return absb * Math.sqrt(1 + square(absa / absb))
}
}
function sign(a, b)
{
return b >= 0 ? Math.abs(a) : -Math.abs(a)
}
// 以下のプログラム svdcmp は,
// William H. Press, Saul A. Teukolski, William T. Vetterling and Bryan P. Flannery
// Numerical Recipes in C
// Cambridge University Press 1992
// の 67-70 ページにある svdcmp を JavaScript に書き直したものである S. Aoki 2001/09/15
function svdcmp(a, n, m, w, v)
{
var flag, i, its, j, jj, k, l, nm
var anorm, c, f, g, h, s, scale, x, y, z, rv1
rv1 = makeVector(m)
g = scale = anorm = 0
for (i = 0; i < m; i++) {
l = i + 1
rv1[i] = scale * g
g = s = scale = 0
if (i < n) {
for (k = i; k < n; k++) {
scale += Math.abs(a[k][i])
}
if (scale) {
for (k = i; k < n; k++) {
a[k][i] /= scale
s += a[k][i] * a[k][i]
}
f = a[i][i]
g = -sign(Math.sqrt(s), f)
h = f * g - s
a[i][i] = f - g
for (j = l; j < m; j++) {
s = 0
for (k = i; k < n; k++) {
s += a[k][i] * a[k][j]
}
f = s / h
for (k = i; k < n; k++) {
a[k][j] += f * a[k][i]
}
}
for (k = i; k < n; k++) {
a[k][i] *= scale
}
}
}
w[i] = scale * g
g = s = scale = 0
if (i < n && i != m-1) {
for (k = l; k < m; k++) {
scale += Math.abs(a[i][k])
}
if (scale) {
for (k = l; k < m; k++) {
a[i][k] /= scale
s += a[i][k] * a[i][k]
}
f = a[i][l]
g = -sign(Math.sqrt(s), f)
h = f * g - s
a[i][l] = f - g
for (k = l; k < m; k++) {
rv1[k] = a[i][k] / h
}
for (j = l; j < n; j++) {
s = 0
for (k = l; k < m; k++) {
s += a[j][k] * a[i][k]
}
for (k = l; k < m; k++) {
a[j][k] += s * rv1[k]
}
}
for (k = l; k < m; k++) {
a[i][k] *= scale
}
}
}
anorm = Math.max(anorm, (Math.abs(w[i]) + Math.abs(rv1[i])))
}
for (i = m-1; i >= 0; i--) {
if (i < m-1) {
if (g) {
for (j = l; j < m; j++) {
v[j][i] = (a[i][j] / a[i][l]) / g
}
for (j = l; j < m; j++) {
s = 0
for ( k = l; k < m; k++) {
s += a[i][k] * v[k][j]
}
for (k = l; k < m; k++) {
v[k][j] += s * v[k][i]
}
}
}
for (j = l; j < m; j++) {
v[i][j] = v[j][i] = 0
}
}
v[i][i] = 1
g = rv1[i]
l = i
}
for (i = Math.min(n, m)-1; i >= 0; i--) {
l = i + 1
g = w[i]
for (j = l; j < m; j++) {
a[i][j] = 0
}
if (g) {
g = 1 / g
for (j = l; j < m; j++) {
s = 0
for (k = l; k < n; k++) {
s += a[k][i] * a[k][j]
}
f = (s / a[i][i]) * g
for (k = i; k < n; k++) {
a[k][j] += f * a[k][i]
}
}
for (j = i; j < n; j++) {
a[j][i] *= g
}
}
else {
for (j = i; j < n; j++) {
a[j][i] = 0
}
}
++a[i][i]
}
for (k = m-1; k >= 0; k--) {
for (its = 1; its <= 30; its++) {
flag = 1
for (l = k; l >= 0; l--) {
nm = l - 1
if (Math.abs(rv1[l]) + anorm == anorm) {
flag = 0
break
}
if (Math.abs(w[nm]) + anorm == anorm)
break
}
if (flag) {
c = 0
s = 1
for (i = l; i < k; i++) {
f = s * rv1[i]
rv1[i] = c * rv1[i]
if (Math.abs(f) + anorm == anorm) {
break
}
g = w[i]
h = pythag(f, g)
w[i] = h
h = 1 / h
c = g * h
s = -f * h
for (j = 0; j < n; j++) {
y = a[j][nm]
z = a[j][i]
a[j][nm] = y * c + z * s
a[j][i] = z * c - y * s
}
}
}
z = w[k]
if (l == k) {
if (z < 0) {
w[k] = -z
for (j = 0; j < m; j++) {
v[j][k] = -v[j][k]
}
}
break
}
if (its == 30) {
printf("no convergence in 30 svdcmp iterations\n")
}
x = w[l]
nm = k - 1
y = w[nm]
g = rv1[nm]
h = rv1[k]
f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2 * h * y)
g = pythag(f, 1)
f = ((x - z) * (x + z) + h * ((y / (f + sign(g, f))) - h)) / x
c = s = 1
for (j = l; j <= nm; j++) {
i = j + 1
g = rv1[i]
y = w[i]
h = s * g
g = c * g
z = pythag(f, h)
rv1[j] = z
c = f / z
s = h / z
f = x * c + g * s
g = g * c - x * s
h = y * s
y *= c
for (jj = 0; jj < m; jj++) {
x = v[jj][j]
z = v[jj][i]
v[jj][j] = x * c + z * s
v[jj][i] = z * c - x * s
}
z = pythag(f, h)
w[j] = z
if (z) {
z = 1 / z
c = f * z
s = h * z
}
f = c * g + s * y
x = c * y - s * g
for (jj = 0; jj < n; jj++) {
y = a[jj][j]
z = a[jj][i]
a[jj][j] = y * c + z * s
a[jj][i] = z * c - y * s
}
}
rv1[l] = 0
rv1[k] = f
w[k] = x
}
}
}
function outmat(r, n, m, str)
{
var j, k
printf("\n%s\n\n", str)
for (j = 0; j < n; j++) {
for (k = 0; k < m; k++) {
printf(" %12.6g", r[j][k])
}
printf("\n")
}
}
function sort(a, diag, v, n, m)
{
var i, j, maxi, maxv, temp
for (i = 0; i < m-1; i++) {
maxi = i
maxv = diag[i]
for (j = i+1; j < m; j++) {
if (diag[j] > maxv) {
maxi = j
maxv = diag[j]
}
}
if (maxi != i) {
diag[maxi] = diag[i]
diag[i] = maxv
for (j = 0; j < n; j++) {
temp = a[j][i]
a[j][i] = a[j][maxi]
a[j][maxi] = temp
}
for (j = 0; j < m; j++) {
temp = v[j][i]
v[j][i] = v[j][maxi]
v[j][maxi] = temp
}
}
}
}
function calc(data_string)
{
var a, n, m, diag, v
var debug = false
if ((a = getdata(data_string, 0)) != false) {
if ((n = a.length) == 0) {
printf("データが入力されていません\n")
return
}
m = a[0].length
diag = makeVector(m)
v = makeMatrix(m, m)
outmat(a, n, m, "★ 入力された行列 ★")
if (svdcmp(a, n, m, diag, v) == 1) {
printf("特異値分解ができませんでした\n")
}
else {
sort(a, diag, v, n, m)
sum = 0
for (i = 0; i < m; i++) {
sum += diag[i]
}
cum = 0
printf("\n%4s %10s %12s %12s\n\n", "番号", "固有値", "寄与率", "累積寄与率")
for (i = 0; i < m; i++) {
cum += diag[i]/sum*100
printf("%4i %10.6g %11.1f%% %11.1f%%\n", i+1, diag[i], diag[i]/sum*100, cum)
}
for (i = 0; i < n; i++) {
for (j = 0; j < m; j++) {
a[i][j] *= diag[j]
}
}
outmat(a, n, m, 'UΛ')
outmat(v, m, m, 'V')
if (debug) {
printf("\n検算\n\n")
for (i = 0; i < n; i++) {
for (j = 0; j < m; j++) {
sum = 0
for (k = 0; k < m; k++) {
sum += a[i][k]*v[j][k]
}
printf("%10.5g", sum)
}
printf("\n")
}
}
}
}
sep(40)
}
//-->
</script>
</head>
<body bgcolor="#ffffff">
<font size="+2"><b>特異値分解</b></font> <a href="src/svdcmp.html"><img src="png/src.png" width=35 height=11 alt="src" align=top></a> Last modified: Jun 01, 2006<hr noshade><p>
<font color="#ff0000" size="+2">以下のプログラムのサポートは終了しました。自己責任でお使い下さい。</font>
<form name=Result>
<script language="JavaScript">
<!--
//-->JavaScript がサポートされていないブラウザですか?
</script>
<input type="button" name="calcurate" value="計算開始" onClick="calc(this.form.data.value)">
<input type="button" name="clear" value="入力欄クリア" onClick="this.form.data.value=''">
<input type="button" name="clear" value="出力欄クリア" onClick="this.form.result.value=''">
<img src="../gra/button3.png" width=9 height=9 alt="・"> <A HREF="exa/svdcmp.html">使用法</a><p>
入力欄(データ行列を<a href="exa/kugirimoji.html">区切り文字</a>で区切って,行単位に入力)<br><textarea name="data" ROWS=10 COLS=80></textarea><p>
出力欄<br><textarea name="result" ROWS=30 COLS=80></textarea>
</form>
<p><hr noshade>
<img src="../gra/button3.png" width=9 height=9 alt="・"> <A HREF="javascript:history.go(-1)">直前のページへ戻る</A> <img src="../gra/button3.png" width=9 height=9 alt="・"> <a href="../mail.html">E-mail to Shigenobu AOKI</a>
<p><center><IMG SRC="../gra/ume5.png" width=121 height=37 ALT="Made with Macintosh"></center>
</body>
</html>
サブ io.js Last modified: Mar 25, 2004
直前のページへ戻る E-mail to Shigenobu AOKI