Java 相似度 余弦函数 字符串

Java 字符串相似度计算,余弦算法

本文是计算两个字符串的相似度

具体步骤为

1、求出两个字符串的并集

2、计算两个字符串的词频

3、通过公式算出余弦值:夹角越小,相似度越大,越接近1,相似度越大

如:以下的其实是很接近的,那具体怎么算

String a1 = "今天天气真好";
String a2 = "今天天气不错";

1、算并集

{0=今, 1=天, 2=气, 3=真, 4=好, 5=不, 6=错}

2、算每个的词频

a1 = {0=1, 1=2, 2=1, 3=1, 4=1, 5=0, 6=0}

a2 = {0=1, 1=2, 2=1, 3=0, 4=0, 5=1, 6=1}

3、公式套用

https://img1.sycdn.imooc.com/5b7443960001494204230141.jpg

(1*1 + 2*2+1*1+1*0+1*0+0*1+0*1)/ { [平方根号(1*1 + 2*2 + 1*1 + 1*1 + 1*1 + 0*0 + 0*0)] * [ 平方根号(1*1 + 2*2 + 1*1 + 0*0 + 0*0 + 1*1 + 1*1)] }

import java.util.HashMap;
import java.util.Map;

public class Cosine {

	public static void main(String[] args) {
		//String str = "国药准字H20090101";
		
		String a1 = "今天天气真好";
		String a2 = "今天天气不错";
		
		long start=System.currentTimeMillis();
		double jgz = getVector(a1, a2);
		System.out.println("用时:"+(System.currentTimeMillis()-start));
	    System.out.println(jgz);
	   
	    
	}
	
	
	
	public static double getVector(String par,String bar){
		Map<Integer, String> map  = new HashMap<Integer, String>();
		Map<Integer, String> map2 = new HashMap<Integer, String>();
		Map<Integer, String> pmap = new HashMap<Integer, String>();
		Map<Integer, String> bmap = new HashMap<Integer, String>();
		
		// 词频存储的map
		Map<Integer, Integer> pmapcp = new HashMap<Integer, Integer>();
		Map<Integer, Integer> bmapcp = new HashMap<Integer, Integer>();
		
		// 结果值
		double jgz = -1;
		
		par = qbdfh(par);
		bar = qbdfh(bar);
		if(isNull(par) || isNull(bar)) {
			return -1;
		}
		String chb = par+bar;    // 初合并
		map = strChargeMap(chb); // 字符串放到map中
		map2 = mapQC(map);       // 合并为map,去重
		
		//计算词频
		pmap = strChargeMap(par);
		bmap = strChargeMap(bar);

				
		// 得到词频
		pmapcp = getcipin(map2, pmap);
		bmapcp = getcipin(map2, bmap);

		
		// 计算夹角
		jgz = getjgz(map2, pmapcp, bmapcp);
		return jgz;
	}
	
	/**
	 * 计算余弦值
	 * @param map2		并集
	 * @param pmapcp	p词频
	 * @param bmapcp	b词频
	 * @return
	 */
	public static double getjgz(Map<Integer, String> map2, Map<Integer, Integer> pmapcp, Map<Integer, Integer> bmapcp) {
		//计算的三个变量
		double zx = 0; //分子
		double ax = 0; //分母1
		double bx = 0; //分母2
		// 临时变量
		double ap = 0;
		double bp = 0;
		// 结果值
		double jgz = -1;
		if(isNull(map2) || isNull2(pmapcp) || isNull2(bmapcp)) return -1;
		for (int i = 0; i < map2.size(); i++) {
			Integer a = pmapcp.get(i);
			Integer b = bmapcp.get(i);
			zx = zx + a*b;
			ap = ap+a*a;
			bp = bp+b*b;
		}
		ax = Math.pow(ap, 1.0/2);
		bx = Math.pow(bp, 1.0/2);
		if (zx == 0) return -1;
		jgz = zx/(ax*bx);
		return jgz;
	}
	
	/**
	 * 字符串词频计算
	 * @param map2 并集
	 * @param strmap 字符串map
	 * @return
	 */
	public static Map<Integer, Integer> getcipin(Map<Integer, String> map2, Map<Integer, String> strmap){
		Map<Integer, Integer> cipin = new HashMap<Integer, Integer>();
		if(isNull(map2) || isNull(strmap)) return null;
		// 初始化词频
		for (int i = 0; i < map2.size(); i++) {
			cipin.put(i, 0);
		}
		// 词频赋值
		for (int i = 0; i < map2.size(); i++) {
			String map2value = map2.get(i);
			for (int j = 0; j < strmap.size(); j++) {
				String pmapvalue = strmap.get(j);
				if(map2value.equals(pmapvalue)) {
					cipin.put(i, cipin.get(i)+1);
				}
			}
		}
		return cipin;
	}
	
	
	/**
	 * map 去重
	 * @param map
	 * @return
	 */
	public static Map<Integer, String> mapQC(Map<Integer, String> map){
		Map<Integer, String> map2 = new HashMap<Integer, String>();
		int k = -1;
		if(isNull(map)) return null;
		for (int j = 0; j < map.size(); j++) {
			if (!map2.containsValue(map.get(j))) {
				k = k+1;
				map2.put(k,map.get(j));
			}
		}
		return map2;
	}
	
	/**
	 * 将字符串放到map中
	 * @param str
	 * @return
	 */
	public static Map<Integer, String> strChargeMap(String str){
		Map<Integer, String> map = new HashMap<Integer, String>();
		if(isNull(str)) return null;
		for(int i=0;i<str.length();i++){
		    map.put(i, String.valueOf(str.charAt(i)));
		}
		return map;
	}
	
	public static boolean isNull2(Map<Integer, Integer> map) {
		if(map == null || map.size() == 0) return true;
		return false;
	}
	
	public static boolean isNull(Map<Integer, String> map) {
		if(map == null || map.size() == 0) return true;
		return false;
	}
	
	public static boolean isNull(String str) {
		if(str == null || "".equals(str) || str.length() == 0) return true;
		return false;
	}
	
	/**
	 * 去标点符号
	 * @param str
	 * @return
	 */
	public static String qbdfh(String str) {
		if ("".equals(str) || str.length() == 0 || str == null) return "";
		return str = str.replaceAll( "[\\pP+~$`^=|<>~`$^+=|<>¥×]" , "");
	}
	

}

运行结果

用时:10
0.7499999999999999

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值