質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

3回答

1078閲覧

部分配列を仮引数に入れる方法が分かりません。

mememe0331

総合スコア55

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2020/06/18 07:58

前提・実現したいこと

まず、q:0 0 0 0 0 1 1 0 を入力します。

そして、配列Dの1行と配列qを比較すると、コサイン類似度を表示するというプログラムを作りたいです。

ほとんどのプログラムは完成しているのですが、double cosine(int D[4],int q[8])に配列Dの部分配列を代入する方法が分かりません。

コメント頂けると幸いです。

発生している問題・エラーメッセージ

問題は、計算結果が正しく表示されないことです。0または、連続する数が出ます。 double cosine(int D[4],int q[8])の部分に D[4][8]のうちの一行分の要素の部分配列を仮引数に代入したです。 しかし、どうやったら部分配列をdouble cosine(int D[4],int q[8])の中に入れられるのかが分かりません。

該当のソース

C言語

1#include <stdio.h> 2 3int main(void) 4{ 5 int D[4][8] = { 6 {0,1,1,1,0,1,0,1}, 7 {0,0,0,0,1,1,1,0}, 8 {1,0,0,0,0,0,1,0}, 9 {0,1,0,0,1,0,0,0} 10 }; 11 int q[8]; 12 double res[4]; 13 14 printf("q:"); 15 scanf("%d %d %d %d %d %d %d %d",&q[0],&q[1],&q[2],&q[3],&q[4],&q[5],&q[6],&q[7]); 16 17 printf("d1とqの類似度:%.3f\n",res[0]); 18 printf("d2とqの類似度:%.3f\n",res[1]); 19 printf("d3とqの類似度:%.3f\n",res[2]); 20 printf("d4とqの類似度:%.3f\n",res[3]); 21 22 return 0; 23} 24double cosine(int D[4],int q[8]) 25{ 26 int i,k,l; 27 double y1=0,y2=0; 28 double sum=0,sum_d=0,sum_q=0; 29 30 for(i=0;i<8;i++){ 31 sum=D[i]*q[i]; 32 } 33 for(k=0;k<8;k++){ 34 sum_d+=D[k]*D[k]; 35 } 36 for(l=0;l<8;l++){ 37 sum_q+=q[l]*q[l]; 38 } 39 y1=sqrt(sum_d); 40 y2=sqrt(sum_q); 41 42 return sum/(y1*y2); 43} 44 45void similarity(int q[8],int D[4][8],double res[4]) 46{ 47 int i; 48 49 for(i=0;i<4;i++){ 50 res[i] = cosine(D[i],q); 51 } 52 53} 54

試したこと

double cosine(int D[4],int q[8])の部分で、配列D[]、D[8]にしましたが、求めている答えが得られませんでした。

補足情報(FW/ツールのバージョンなど)

コマンドプロンプト for VS 2019、サクラエディタを使用しています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

episteme

2020/06/18 08:12

> double cosine(int D[4],int q[8]) なんでふたつの配列の要素数が異なるんですか?
mememe0331

2020/06/21 13:15

episteme様、回答ありがとうございます。 Dを4列で表示したいので、4にしました。しかし、使い方がわかっていないので質問させて頂きました。
guest

回答3

0

C

1#include <stdio.h> 2#include <math.h> 3 4double cosine(int D[8], int q[8]) { 5 int i; 6 double y1 = 0, y2 = 0; 7 double sum = 0, sum_d = 0, sum_q = 0; 8 9 for (i = 0; i < 8; i++) { 10 sum += D[i] * q[i]; 11 sum_d += D[i] * D[i]; 12 sum_q += q[i] * q[i]; 13 } 14 y1 = sqrt(sum_d); 15 y2 = sqrt(sum_q); 16 17 return sum / (y1 * y2); 18} 19 20void similarity(int q[8], int D[4][8], double res[4]) { 21 int i; 22 23 for (i = 0; i < 4; i++) { 24 res[i] = cosine(D[i], q); 25 } 26 27} 28 29int main(void) { 30 int D[4][8] = { 31 {0,1,1,1,0,1,0,1}, 32 {0,0,0,0,1,1,1,0}, 33 {1,0,0,0,0,0,1,0}, 34 {0,1,0,0,1,0,0,0} 35 }; 36 37 int q[8] = { 0, 0, 0, 0, 0, 1, 1, 0 }; 38 double res[4]; 39 similarity(q, D, res); 40 41 printf("d1とqの類似度:%.3f\n", res[0]); 42 printf("d2とqの類似度:%.3f\n", res[1]); 43 printf("d3とqの類似度:%.3f\n", res[2]); 44 printf("d4とqの類似度:%.3f\n", res[3]); 45 46 return 0; 47}

実行結果:

d1とqの類似度:0.316 d2とqの類似度:0.816 d3とqの類似度:0.500 d4とqの類似度:0.000

投稿2020/06/18 10:24

episteme

総合スコア16612

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mememe0331

2020/06/21 13:49

episteme様、回答ありがとうございます。 入力しを宣言して行ったら、実行する事が出来ました。 ありがとうございます!
guest

0

ベストアンサー

質問者の求めたいコサイン類似度がわからなかったので、検索をかけてそれっぽいやつを実装化してみました。

コサイン類似度について(赤澤康幸さんのホームページ)
上記サイトトップ

C

1// コサイン類似度を求めるプログラム 2// コサイン類似度の詳細は以下のページを参照のこと 3// https://www.cse.kyoto-su.ac.jp/~g0846020/keywords/cosinSimilarity.html 4 5#include <stdio.h> 6#include <math.h> 7 8#define VECTOR_SIZE 4 9 10double innerProduct(double *a, double *b) { 11 double sum = 0.0; 12 for (int i = 0; i < VECTOR_SIZE; ++i) 13 sum += a[i] * b[i]; 14 return sum; 15} 16 17double cosineSimilarity(double *a, double *b) { 18 double ab = innerProduct(a, b); 19 double aa = innerProduct(a, a); 20 double bb = innerProduct(b, b); 21 return ab / sqrt(aa) * sqrt(bb); 22} 23 24int main() { 25 double d1[] = { 0.789, 0.515, 0.335, 0.0 }; 26 double d2[] = { 0.832, 0.555, 0.0, 0.0 }; 27 double d3[] = { 0.524, 0.465, 0.405, 0.588 }; 28 29 double *D[] = { d1, d2, d3 }; 30 31 printf("cos(D1, D2) = %f\n", cosineSimilarity(D[0], D[1])); 32 printf("cos(D1, D3) = %f\n", cosineSimilarity(D[0], D[2])); 33 printf("cos(D2, D3) = %f\n", cosineSimilarity(D[1], D[2])); 34 return 0; 35}

実行結果

cos(D1, D2) = 0.942404 cos(D1, D3) = 0.788822 cos(D2, D3) = 0.694154

ただ、この実行結果はホームページで示されていた計算例と微妙に値が異なります。なので私の方でOpen Office Calcを使って計算を行ってみました。

Open Office Calcによる計算結果

計算結果はサイトのものとも作成したプログラムのものともどっち付かずなものとなったため、恐らくプログラムは正しいのであろうと判断しました。

このプログラムはスケーラビリティを意識しているのでベクトル長が8の場合にも対応できると思います。インターフェースとしては作成したプログラムを参考にしていただければと思います。

ちなみにCで部分配列(という言葉はCにはない)を引っ張ってくる方法ですが、

int D[][] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};

int E[] = {1,2,3,4,5,6,7,8,9,10,11,12};

と同じデータ構造なので、{5,6,7,8}が欲しい場合は&D[1][0]で取得できると思います。{2,6,10}が欲しい場合は別途ルーチンを用意して取得する必要があります。

投稿2020/06/18 09:33

anndonut

総合スコア667

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mememe0331

2020/06/21 13:51

anndonut様、回答ありがとうございます。 めちゃくちゃ調べてくださってありがとうございます! 勉強になりました!
guest

0

べつにその分の配列変数を用意して、必要な部分をコピーし、それを関数に渡します

Cでは配列の部分配列だけを取り出すという操作はありません

投稿2020/06/18 08:01

y_waiwai

総合スコア88042

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mememe0331

2020/06/21 13:17

y_waiwai様、回答ありがとうございます。 勉強になります
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問