関数naiseki内の変数ansの初期値が0ではないのが
計算結果に問題が出る原因です。
変数は定義しただけでは初期化されないので
手動で初期化する必要があります。
diff
1-double naiseki(double veca[], double vecb[],int n)
2+double naiseki(const double veca[], const double vecb[])
3{
4 int i;
5- double ans;
6+ double ans = 0.;
7
8- for (i=0; i<=3; i++)
9+ for (i=0; i<3; ++i)
10 {
11 ans = ans + veca[i]*vecb[i];
12 }
13 return ans;
14}
ちなみに余談ですが上記コードでは内積関数の内部の総和部分で
情報落ちで発生する誤差が蓄積されてしまう問題
への対策が行われていないので下記コードのような
状況で誤差によりおかしな結果となってしまいます。
c
1#include <stdio.h>
2
3double naiseki(const double veca[3], const double vecb[3])
4{
5 double ans = 0.;
6 for(unsigned i=0; i<3; ++i) ans += veca[i] * vecb[i];
7 return ans;
8}
9
10int main()
11{
12 double vec1[] = {10000000000000000., 1., 1.};
13 double vec2[] = {1., 1., 1.};
14
15 double result = naiseki(vec1, vec2);
16
17 printf("%lf\n", result);
18 /*--------------------------------------------
19 結果 :10000000000000000.000000
20 予想した結果 :10000000000000002.000000
21 情報落ちにより誤差が発生
22 *///------------------------------------------
23}
なのでカハンの加算アルゴリズムを用いて
誤差を抑えたコードのほうが適切かもしれません。
c
1#include <stdio.h>
2
3//
4// カハンの加算アルゴリズムを用いた内積
5//
6double naiseki_kahan(const double veca[3], const double vecb[3])
7{
8 double y, t;
9 double sum = 0.;
10 double loss = 0.;
11
12 for(unsigned i = 0; i < 3; ++i){
13 y = veca[i] * vecb[i] - loss;
14 t = sum + y;
15 loss = (t - sum) - y;
16 sum = t;
17 }
18 return sum;
19}
20
21//
22// 通常の内積
23//
24double naiseki(const double veca[3], const double vecb[3])
25{
26 double ans = 0.;
27 for(unsigned i=0; i<3; i++) ans += veca[i] * vecb[i];
28 return ans;
29}
30
31int main()
32{
33 double vec1[] = {10000000000000000., 1., 1.};
34 double vec2[] = {1., 1., 1.};
35
36 double result = naiseki(vec1, vec2);
37 double result_kahan = naiseki_kahan(vec1, vec2);
38
39 printf("use normal :%lf\n", result);
40 printf("use kahans sum :%lf\n", result_kahan);
41
42 /*--------------------------------------------
43 use normal :10000000000000000.000000
44 use kahans sum :10000000000000002.000000
45 *///------------------------------------------
46}