JavaScript Cosine similarity function - javascript

I am trying to create a cosine similarity function and then display the results in a HTML element. I have written the following:
function cosinesim(A,B){
var dotproduct=0;
var mA=0;
var mB=0;
for(i = 0; i < A.length;){
dotproduct += (A[i] * B[i]);
mA += (A[i]*A[i]);
mB += (B[i]*B[i]);
}
mA = Math.sqrt(mA);
mB = Math.sqrt(mB);
var similarity = (dotproduct)/(mA)*(mB)
return similarity;
}
//.....
var array1 = [1,0,0,1];
var array2 = [1,0,0,0];
var p = cosinesim(array1,array2);
document.getElementById("sim").innerHTML = String(p);
I have tested and both the arrays I am inputting are the same length, however when my code runs to this bit it crashes and I cant seem to find what is wrong.
Any help is appreciated, thanks.

function cosinesim(A,B){
var dotproduct=0;
var mA=0;
var mB=0;
for(i = 0; i < A.length; i++){ // here you missed the i++
dotproduct += (A[i] * B[i]);
mA += (A[i]*A[i]);
mB += (B[i]*B[i]);
}
mA = Math.sqrt(mA);
mB = Math.sqrt(mB);
var similarity = (dotproduct)/((mA)*(mB)) // here you needed extra brackets
return similarity;
}
var array1 = [1,0,0,1];
var array2 = [1,0,0,0];
var p = cosinesim(array1,array2);
console.log(p);
This should give the actual cosine similarity.
You were missing: 1.) The i++ in your loop, as mentioned before. 2.) Extra brackets around (mA)*(mB) in this line: var similarity = (dotproduct)/((mA)*(mB)) -> otherwise the division is done before the multiplication.

you missed i++ in your loop which leads to an endless one
replacing for(i = 0; i < A.length;) to for(i = 0; i < A.length;i++) fixed the issue

Using the map and reduce the functionality of javascript
function dotp(x, y) {
function dotp_sum(a, b) {
return a + b;
}
function dotp_times(a, i) {
return x[i] * y[i];
}
return x.map(dotp_times).reduce(dotp_sum, 0);
}
function cosineSimilarity(A,B){
var similarity = dotp(A, B) / (Math.sqrt(dotp(A,A)) * Math.sqrt(dotp(B,B)));
return similarity;
}
var array1 = [1,2,2,1];
var array2 = [1,3,2,0];
var p = cosineSimilarity(array1,array2);
console.log(p);
Hope this helps!! Happy coding!!

function cosinesim(A,B){
var dotproduct=0;
var mA=0;
var mB=0;
for(i = 0; i < A.length; i++){
dotproduct += (A[i] * B[i]);
mA += (A[i]*A[i]);
mB += (B[i]*B[i]);
}
mA = Math.sqrt(mA);
mB = Math.sqrt(mB);
var similarity = (dotproduct)/(mA)*(mB)
return similarity;
}
var array1 = [1,0,0,1];
var array2 = [1,0,0,0];
var p = cosinesim(array1,array2);
console.log(p);

Related

How to display output of one function after another

I have written a Javascript file of two algorithms. As shown in the code below, I am using a for loop to generate random values which are used by both algorithms as input.
At present, I am displaying output of the binarySearch and SearchSorted alternatively.
The problem I am facing is I have to pass the same array values generated by randomlyGenerateArray in the main program to both the algorithms for a meaningful comparison. But I don't know how to change the output format.
I have thought of adding them in different loops, but as I have explained above i need to use the same randomArray values for both the algorithms.
i.e., The below code produces output as shown below -
Binary Search Successful 1
Search Sorted Successful 5
Binary Search Successful 3
Search Sorted Successful 10
How do I display the output of Binary Search First and then display output of Search Sorted? it's something like this. Any help will be greatly appreciated.
Binary Search Successful 1
Binary Search Successful 3
Search Sorted Successful 5
Search Sorted Successful 10
// Binary Search Algorithm
function binarySearch(A,K)
{
var l = 0; // min
var r = A.length - 1; //max
var n = A.length;
var operations = 0;
while(l <= r)
{
var m = Math.floor((l + r)/2);
operations++;
if(K == A[m])
{
console.log('Binary Search Successful %d',operations);
return m;
}
else if(K < A[m])
{
r = m - 1;
}
else
{
l = m + 1;
}
}
operations++;
console.log('Binary Search Unsuccessful %d',operations);
return -1;
}
// Search Sorted Algorithm
function searchSorted(A, K)
{
var n = A.length;
var i = 0;
var operations = 0;
while (i < n)
{
operations++;
if (K < A[i])
{
return -1;
}
else if (K == A[i])
{
console.log('Search Sorted Successful %d', operations);
return i;
}
else
{
i = i + 1;
}
}
operations++;
console.log('Search Sorted Unsuccessful %d', operations);
return -1;
}
// Random Array generator
var randomlyGenerateArray = function(size)
{
var array = [];
for (var i = 0; i < size; i++)
{
var temp = Math.floor(Math.random() * maxArrayValue);
var final = array.splice(5, 0, 30);
array.push(final);
}
return array;
}
//Sort the Array
var sortNumber = function(a, b)
{
return a - b;
}
// Main Program
var program = function()
{
var incrementSize = largestArray / numberOfArrays;
for (var i = smallestArray; i <= largestArray; i += incrementSize)
{
var randomArray = randomlyGenerateArray(i);
var sort = randomArray.sort(sortNumber);
var randomKey = 30;
binarySearch(sort, randomKey);
searchSorted(sort, randomKey);
}
}
var smallestArray = 10;
var largestArray = 10000;
var numberOfArrays = 1000;
var minArrayValue = 1;
var maxArrayValue = 1000;
program();
You could store the sorted randomArrays in an array (which I've called sortedRandomArrays), then run a for loop for each search.
The Main Program would then look like:
// Main Program
var program = function()
{
var incrementSize = largestArray / numberOfArrays;
var sortedRandomArrays = [];
for (var i = smallestArray; i <= largestArray; i += incrementSize)
{
var randomArray = randomlyGenerateArray(i));
var sort = randomArray.sort(sortNumber);
sortedRandomArrays.push(sort);
var randomKey = 30;
}
for (var i = 0; i < sortedRandomArrays.length; i++)
{
binarySearch(sortedRandomArrays[i], randomKey);
}
for (var i = 0; i < sortedRandomArrays.length; i++)
{
searchSorted(sortedRandomArrays[i], randomKey);
}
}
Solution is simple: store the results and print with 2 separate loops (take out the printing from within the functions).
var program = function()
{
var binarySearchResults = [];
var sortedSearchResults = [];
var incrementSize = largestArray / numberOfArrays;
for (var i = smallestArray; i <= largestArray; i += incrementSize)
{
var randomArray = randomlyGenerateArray(i);
var sort = randomArray.sort(sortNumber);
var randomKey = 30;
binarySearchResults[i] = binarySearch(sort, randomKey);
sortedSearchResults[i] = searchSorted(sort, randomKey);
}
for (var i = smallestArray; i <= largestArray; i += incrementSize)
{
//print binary results
}
for (var i = smallestArray; i <= largestArray; i += incrementSize)
{
//print sorted results
}
}

Array equals itself plus number = NaN

I must be doing something stupid. The array newArea needs to add up data from all regions, i.e. be global. Regions are represented by variable p. But when I try to get newArea array to add to itself, e.g. newArea[p] += otherArray, it outputs NaNs. Even newArea[p] += 1 outputs NaNs.
Can anyone spot what I'm doing wrong? It's driving me mad and I'm working to a deadline.
mm=0
var maxVolume = 0;
var tempCAGR = 0;
var maxCAGR = 0;
var newArray = [];
var newRegions = [];
var newConsValues = [];
var newArea = [];
for (var p=0; p<arrayRef[mm].length; p++) {//9 regions
newArray[p] = [];
for (var q=0; q<arrayRef[mm][p].length; q++) {//4 scenarios
newArea[q] = [];
if (q==0) {
newRegions.push(arrayRef[mm][p][q][0]);
newConsValues.push(arrayRef[mm][p][q][1]);
}
for (var r=0; r<dates.length; r++) {//time
//console.log('p: '+p+', q: '+q+', r: '+r);
if (p==0) {
newArea[q][r] = 1;
} else {
newArea[q][r] += 1;
}
}
arrayRef[mm][p][q].shift();
tempCAGR = Math.pow(( arrayRef[mm][p][q][len] / arrayRef[mm][p][q][1] ),(1/len))-1;
//console.log(newRegions[p]+', num: '+arrayRef[mm][p][q][len-1]+', denom: '+arrayRef[mm][p][q][0]+', len: '+len+', cagr: '+tempCAGR);
newArray[p][q] = tempCAGR;
maxCAGR = Math.max(maxCAGR,tempCAGR);
}
}
console.log(newArea);
You are cleaning the array in newArea everytime you loop through it:
...loop q ...
newArea[q] = []; // <-- resets the array at q pos
... loop r ...
if (p==0) {
newArea[q][r] = 1;
} else {
newArea[q][r] += 1;
}
So when p === 0 it will fill an array at q pos of your newArea array. However, next iteration of p will clear them out, so there's nothing there to sum.
You probably want to keep the old array or create a new one if there isn't one.
newArea[q] = newArea[q] || [];
It looks like you do not have the variable initialised. With adding something to undefined, you get NaN.
You can change the art of incrementing with a default value:
if (p == 0) {
newArea[q][r] = 1;
} else {
newArea[q][r] = (newArea[q][r] || 0) + 1;
}

Average of Numbers in Javascript/Angularjs

I have a json response where have to calculate the average of "throughput_kbps" where protocol name is "TCP" for each result array.
I using Javascript/Angularjs for this
Please refer This json
Thanx in advance
You could do something like this:
var len1 = obj['flows'].length;
for (var i=0; i<len1; i++)
{
var tmp = obj.['flows'][i];
var len2 = tmp.['results'].length;
var mean = 0;
for (var j=0; j<len2; ++j)
{
var tmpResult = tmp.['results'][j];
if (tmpResult['protocol'] === 'TCP')
mean += tmpResult['throughput_kbps'];
}
console.log(mean);
}
Try this
var sum = 0;
var count = 0;
data.flows.map(function(d){
return d.results.filter(function(res){
if(res.protocol == 'TCP'){
sum += res.throughput_kbps;
count++;
return sum;
}
})
});
var avg = sum/count;
Pass your JSON as an argument to this function. This'll return you the average throughput you ask for.
function calculateThroughput(json){
var flowsObj = json.flows;
var throughputSum = 0;
var noOfSamples = 0;
for(noOfFlows in flowsObj){
var resultObj = flowsObj[noOfFlows].results;
for(noOfResults in resultObj){
if(resultObj[noOfResults].protocol == "TCP"){
throughputSum += resultObj[noOfResults].throughput_kbps;
noOfSamples++;
}
}
}
return (throughputSum/noOfSamples);
};
Hope this helps.

Binary to Decimal Javascript

This code is supposed to take in a string ("100101") and output the result in decimal.I'm not quite sure why it's not working.Any help would be appreciated.
function BinaryConverter(str) {
var num=str.split("");
var powers=[];
var sum=0;
for(var i=0;i<num.length;i++){
powers.push(i);
}
for(var i=powers.length-1;i>=0;i--){
for(var j=0;j<num.length;i++){
sum+=Math.pow(2,i)*num[j];
}
}
return sum;
};
Here's my updated code below .For an input "011" it should do( 2^2*0 +2^1*1 +2^0*1)to =3 but it returns 14.Anybody know where I'm going wrong?
function BinaryConverter(str) {
var num=str.split("");
var powers=[];
var sum=0;
for(var i=0;i<num.length;i++){
powers.push(i);
}
for(var i=powers.length-1;i>=0;i--){
for(var j=0;j<num.length;j++){
sum+=Math.pow(2,i)*num[j];
}
}
return sum;
};
The two nested for loops have a problem. The first one subtracts an i, while the second adds an i forever creating a never ending loop.
ALSO your code should be this:
function BinaryConverter(str) {
var num=str.split("");
var powers=[];
var sum=0;
var numlength=num.length;
for(var i=0;i<num.length;i++){
powers.push(i);
}
for(var i=powers.length-1;i>=0;i--){
sum+=Math.pow(2,i)*num[numlength-i-1];
}
return sum;
};
I don't think you need the nested for loop
If you don't want to do that with parseInt() for some reason (like, because the homework problem says you can't), you can do this without the complexity and expense of calling Math.pow() for each digit:
function parseBinary(str) {
var i, value = 0;
for (i = 0; i < str.length; ++i)
value = value * 2 + +str[i];
return value;
}
That doesn't check for invalid input strings.
ace040686 only inverted the pow(2,i) and num[len-1-i] in his answer, otherwise it would be correct. Also you're pushing 0..str.length-1 unnecessarily to powers, those are implicit indices.
function convertNaive(str) {
var num = str.split("");
var len = num.length;
var sum = 0;
for(var i = len - 1; i >= 0; --i)
sum += Math.pow(2, len - 1 - i) * num[i];
return sum;
}
You can improve this a bit to avoid the unnecessary array and especially Math.pow:
function convertImproved(str) {
var len = str.length;
var sum = 0;
for(var i = 0, fac = 1; i < len; ++i, fac *= 2)
sum += fac * str[len - 1 - i];
return sum;
}
Try it yourself:
var input = "100101";
var logNode = document.getElementById("log");
function log(line) {
var text = document.createTextNode(line);
var node = document.createElement("p");
node.appendChild(text);
logNode.appendChild(node);
}
function convertNaive(str) {
var num = str.split("");
var len = num.length;
var sum = 0;
for(var i = len - 1; i >= 0; --i)
sum += Math.pow(2, len - 1 - i) * num[i];
return sum;
}
function convertImproved(str) {
var len = str.length;
var sum = 0;
for(var i = 0, fac = 1; i < len; ++i, fac *= 2)
sum += fac * str[len - 1 - i];
return sum;
}
log("input: " + input);
log("parseInt(input, 2): " + parseInt(input, 2));
log("convertNaive(input): " + convertNaive(input));
log("convertImproved(input): " + convertImproved(input));
<div id="log" />
Here is the simple implementation of binary to decimal in javascript.
main();
function main() {
let binaryInput = 10000100111;
let decimalOutput = binaryTodecimal(binaryInput);
console.log(decimalOutput);
}
function binaryTodecimal(input) {
let inputString = input.toString();
let result = 0;
let exponent = 1;
let currentBit = 0;
for (let i = inputString.length - 1; i >= 0; i--) {
currentBit = parseInt(inputString[i]);
currentBit *= exponent;
result += currentBit;
exponent *= 2;
}
return result;
}

Trying to square every digit of a number, but my algorithm is not working?

I'm trying to square every digit of a number;
for example:
123 should return 149
983 --> 81649 and so on
I messed it up somewhere in the following Javascript code and I'm looking for some guidance.
function splitNumber(num){
var arr = [];
while(num>0){
var c = num%10;
arr[arr.length]=c;
num=num/10;}
return arr;
}
function squareArrToNumber(arr){
var c = 0;
for(var i=arr.length-1;i>=0;i--){
arr[i]=arr[i]^2;
if(arr[i]^2>10)
c = c*100+arr[i];
else
c = c*10+arr[i];
}
return c;
}
function squareDigits(num){
squareArrToNumber(splitNumber(num));
}
Try out this code
function numToSqr(num){
var i, sqr=[],n;
num = num.toString();
for(i=0;i<num.length;i++){
n = Number(num[i]);
sqr.push(n*n);
}
return Number(sqr.join(""));
}
There are multiple things wrong with your code, starting with an overcomplication to split a string of numbers into its consituant characters just use .splt(""):
var str = "123";
var arr = str.split("");
for(var i = 0;i<arr.length;i++)
alert(arr[i]);
Next, the code num ^ 2 does not square a number. To do a square, simply multiply a number by itself (num * num)
This leaves us with a rather simple solution
function splitNumber(num){
return num.split("");
}
function joinArray(arr){
return arr.join("");
}
function squareArrToNumber(arr){
var newArr = [];
for(var i=0;i<arr.length;i++){
newArr.push(arr[i] * arr[i]);
}
return joinArray(newArr);
}
function squareDigits(num){
return squareArrToNumber(splitNumber(num));
}
alert(squareDigits("123"));
alert(squareDigits("983"));
Here is how I would do such a thing:
var num = 123;
var numArray = num.toString().split("");
var result = "";
for(var i = 0; i < numArray.length; i++){
result += parseInt(numArray[i]) * parseInt(numArray[i]);
}
function squareNum(number) {
var array = [];
// Split number into an array of numbers that make it up
array = String(number).split('');
for (let i = 0; i < array.length; i++) {
// Take each number in that array and square it (in place)
// Also can be done with forEach depending on what es version you're targetting
array[i] = Math.pow(array[i], 2);
}
// combine and return the elements of the array
return Number(array.join(''));
}
squareNum(123);
squareNum(983);
try this example
function squareDigits(n) {
return +(n.toString().split('').map(val => val * val).join(''));
}
console.log(squareDigits(4444));
here + sign is convert the string into an integer.
if(arr[i]^2>10)
should be
if(arr[i]>10)
And, as #Luaan noted, it should be
arr[i] *= arr[i]

Categories