zoukankan      html  css  js  c++  java
  • distance.c

      1 #include "stdio.h"
      2 #include "string.h"
      3 #include "math.h"
      4 #include "malloc.h"
      5 
      6 const long long Max_size = 2000;//输入字符串的最大长度,可以由单个词条和多个词条组成
      7 const long long N = 40;//输出与某个单词最接近的N个词
      8 const long long Max_w = 50;//单个词条的最大长度
      9 
     10 int main(int argc,char **argv)
     11 {
     12     FILE *f;//读取的文件指针
     13     char stemp[Max_size];//中间变量
     14     char *bestw[N];//存储与某个词最接近N个词条
     15     char ch;
     16     float *M;//存储所有词条的距离相关信息
     17     char *vocab;//存储所有词条的字符信息
     18 /*
     19 *file_name[Max_size];存放要读取内容的文件名;
     20 *st[100][Max_size];//二维数组,中间变量
     21 *dist:距离;len:长度;bestd[N]:存储与某个词最接近的N个词的距离
     22 *vec[Max_size]:存储Max_size个词与某个指定词的距离
     23 *words:词条的总数目;size:词条表示的维数;
     24 *key[100],存储某个词条在总词条中的位置下标
     25 */
     26     char file_name[Max_size],st[100][Max_size];
     27     float dist,len,bestd[N],vec[Max_size];
     28     long long words,size,i,j,k,l,num,key[100];
     29      
     30     if(argc<2)//打印程序所在路径
     31     {
     32         printf("Usage:./distance<FILE>
    where FILE contains word projections in the  BINARY FORMAIN
    ");
     33         return 0;
     34     }
     35 
     36     strcpy(file_name,argv[1]);//argv[1]中存放的文件名赋给file_name
     37     f  = fopen(file_name,"rb");
     38 
     39     if(f == NULL)//文件打开失败
     40     {
     41         printf("Input file not found
    ");
     42         return -1;
     43     }
     44 
     45     fscanf(f,"lld",&words);//输入总词条数组
     46     fscanf(f,"lld",&size);//输入用来表示每个词条的维数大小
     47 
     48     vocab = (char *)malloc((long long)words * Max_w *sizeof(char));
     49 
     50     //根据实际的维数分配存储块大小
     51     for(i = 0; i < N; i++)bestw[i] = (char *)malloc(Max_size *  sizeof(char));
     52 
     53     M = (float *)malloc((long long)words * (long long)size *sizeof(float));
     54     if(M==NULL)//不能分配所需要大小的内存
     55     {
     56         printf("Cannot allocate memory:%lld MB %lld %lld
    ",(long long )words *size*sizeof(float)/1024/1024,words,size);
     57         return -1;
     58     }
     59 
     60     for(j = 0; j < words; j++)//words个词条每个词条坐标进行归一化
     61     {
     62         i = 0;
     63         while(true)
     64         {
     65             vocab[j*Max_w + i] = fgetc(f);
     66             if(feof(f) || vocab[j * Max_w + i] == ' ')break;
     67             if((i <Max_w)&&(vocab[j * Max_w + i] !='
    '))i++;
     68         }
     69         vocab[j * Max_w + i] = 0;
     70         for(i = 0;i < size ; i++ ) fread(&M[j * size + i],sizeof(float),1,f);
     71         len = 0;
     72         for(i = 0 ; i < size ; i++ ) len += M[j * size + i]*M[j * size + i];
     73         len = sqrt(len);
     74         for(i = 0 ; i < size ; i++ )  M[j * size + i] = M[j * size + i] / len; //坐标归一化
     75     }
     76     fclose(f);
     77 
     78     while(true)
     79     {
     80         for(i = 0 ; i < N ; i++ )
     81         {
     82             bestd[i] = 0;//N个词条距离初始为0
     83             bestw[i][0] = 0 ;//初始化
     84         }
     85 
     86         printf("Entor word or sentence(EXIT to break:)");
     87 
     88         i = 0;
     89         while(true)//键盘读入单个词条或多个词条  ;当字符数组超过Max_size -1 或者遇到回车符结束
     90         {
     91             stemp[i] = fgetc(stdin);
     92             if((stemp[i] == '
    ')||(i >=Max_size -1))
     93             {
     94                 stemp[i] = 0;
     95                 break;
     96             }
     97         }
     98         if(!strcmp(stemp,"EXIT"))break;//如果输入的是"EXIT",则退出
     99 
    100         num = 0 ;//用来统计键盘输入词条的数目
    101         j = 0;
    102         k = 0;
    103         while(true)
    104         {
    105             st[num][j++] = stemp[k++];
    106             st[num][j] = 0;
    107             if(stemp[k] ==0)break;//读完结束
    108             if(stemp[k++] == ' ')//遇到空格 词条数目+1
    109             {
    110                 num++;//词条数目+1
    111                 j = 0;
    112             }
    113         }
    114 
    115         num++;//词条的总数目
    116 
    117         //找出每个词条 最接近的N个词条
    118         for(i = 0 ; i < num ; i++)
    119         {
    120             for(j = 0 ; j < words ;j++)if(!strcmp(&vocab[j * Max_w],st[j]))break;//在总词条中找到这个词条,获得这个词条在总词条中的位置
    121             if(j == words)  j = -1;//这个词条不存在
    122             key[i] = j;
    123             printf("
    Word:%s Position in vocabulary: %lld
    ",st[i],key[i]);
    124 
    125             if(j == -1)//这个词条不在这个词汇表中
    126             {
    127                 printf("Out of dictionary word!
    ");
    128                 break;//终止循环
    129             }
    130         }
    131 
    132         if(j==-1)continue;//继续执行
    133 
    134          printf("
                                                  Word       Cosine distance
    ");
    135          printf("------------------------------------------------------------------------
    ");
    136 
    137          for(i = 0 ; i < size ; i++ ) vec[i] = 0;//距离初始化为0
    138          for(j = 0 ; j < num ; j++ ) //遍历每个词,如果输入多个词向量vec[i]是各个词向量的累加和
    139          {
    140              if(key[j] == -1)continue;
    141              for(i = 0 ; i < size ; i++ ) vec[i] += M[i + key[j]*size];      
    142          }
    143 
    144          len = 0;
    145          for(i = 0 ; i< size ; i++) len +=vec[i] * vec[i];
    146          len = sqrt(len);
    147 
    148          for(i = 0; i < size ; i++) vec[i] = vec[i] / len;//将vec归一化,当只输入一个词时,不起作用
    149 
    150          for(i = 0 ; i < N ; i++)
    151          {
    152              bestd[i] = -1;
    153              bestw[i][0] = 0;
    154          }
    155 
    156          //由于查询词和词汇表都做了归一化,所以余弦相似度等价于向量的内积,内机越大越相似
    157          for(k = 0 ; k < words ; k++)//遍历词汇表
    158          {
    159              i = 0;
    160              for(j = 0 ; j < num ; j++)//i的作用;如果遍历词和查询词相同,则跳过此词
    161              {
    162                  if(key[j] == k) i =1;
    163              }
    164              if(i == 1) continue;
    165              dist = 0;
    166 
    167              for(i = 0 ; i < N ; i++ )
    168              {
    169                  dist += vec[i] * M[k * size + i] ;
    170              }
    171 
    172              for(i = 0 ; i < N ; i++ )
    173              {
    174                  if(dist > bestd[i])
    175                  {
    176                      for(j = N-1 ; j > i ; j--)
    177                      {
    178                          bestd[j] = bestd[j - 1 ];
    179                          strcpy(bestw[j],bestw[j-1]);
    180                      }
    181                      bestd[j] = dist;
    182                      strcpy(bestw[i] , &vocab[k * Max_size]);
    183                      break;
    184                  }
    185              }
    186          }
    187          for(i = 0 ; i < N ; i++ )printf("%50s		%f
    ",bestw[i],bestd[i]);
    188     }
    189     return 0;
    190 }
  • 相关阅读:
    C语言中for循环的使用
    详解C语言的main函数
    计算机语言的发展(the history of computer's language)
    hdu 1001
    hoj 1002
    hdu 1000
    POJ 1000(水题)
    hoj 1001
    code hunt题解(1)
    《C和指针》学习笔记(3)
  • 原文地址:https://www.cnblogs.com/minmsy/p/5233217.html
Copyright © 2011-2022 走看看