JavaScript Pattern Comparison - javascript

I'm working on a small machine learning theoretical algorithm using nodeJs.
My goal is to compare many array patterns to one source pattern then return how
similar they are represented as a percent . For an example pattern1 maybe 80% similar to the source pattern .
What can be the best method for determining percent similarity for one array to another?
What I've done so far..
//source
var soureSequence = [0.53,0.55,0.50,0.40,0.50,0.52,0.58,0.60]
//patterns to compare
var sequence1 = [0.53,0.54,0.49,0.40,0.50,0.52,0.58,0.60]
var sequence2 = [0.53,0.55,0.50,0.42,0.50,0.53,0.57,0.62]
Since I've chosen a percent based outcome , I figured I should base my source pattern off percentage change from first value to second value in array .
var percentChange = (firstVal, secondVal) => {
var pChange = ((parseFloat(secondVal) - firstVal) /
Math.abs(firstVal)) * 100.00;
//To avoid NaN , Infinity , and Zero
if(!pChange || pChange == 0){
return 0.00000001
}
return pChange;
}
Here I will generate my source pattern from my source sequence
var storePattern = function(sequence){
var pattern = [];
for(var i = 0 ; i < sequence.length ; i++){
let $change = percentChange(sequence[i] , sequence[i + 1]);
if(i != sequence.length && $change ){
pattern.push($change)
}
}
return pattern;
}
var sourcePattern = storePattern(soureSequence);
Now I will create more patterns to be compared
var testPattern1 = storePattern(sequence1);
var testPattern2 = storePattern(sequence2);
Below is my comparison function
var processPattern = function(source , target){
var simularityArray = [];
for(var i = 0 ; i < target.length ; i++){
//Compare percent change at indexof testPattern to sourcePattern of same index
let change = Math.abs(percentChange(target[i] , source[i]));
simularityArray.push(100.00 - change);
}
var rating = simularityArray.reduce((a,b) => {
return a + b
});
//returns percent rating based of average of similarity pattern
rating = rating / parseFloat(source.length + ".00");
return rating;
}
Now I can try to estimate the similarity
var similarityOfTest1 = processPattern(sourcePattern , testPattern1)
My problem is that this only works on sequences within the same range of value .. for example 0.50 , 0.52 .. the percent change in these values would not be the same for 0.20 , 0.22 but the value difference is the same ie -> 0.02
I thought about a difference in value based pattern but at this point I'm lost.
All answers will be considered . Thanks for the help!

used reduce to get the difference than the average.
//patterns to compare
var sequence1 = [0.53,0.54,0.49,0.40,0.50,0.52,0.58,0.60]
var sequence2 = [0.53,0.55,0.50,0.42,0.50,0.53,0.57,0.62]
function diff(sequence){
var soureSequence = [0.53,0.55,0.50,0.40,0.50,0.52,0.58,0.60]
var delta = soureSequence.reduce(function (r, a, i, aa) {
i && r.push(a - sequence[i]);
return r;
}, []),
average = delta.reduce(function (a, b) { return a + b; }) / delta.length;
return {delta:delta, average:average}
}
console.log('sequence1',diff(sequence1));
console.log('sequence2',diff(sequence2));

In my experience, the similarity of two vectors (arrays) is measured using the dot product ex. Like it says in that link, you multiply each corresponding elements of the arrays, add those up, then divide by the magnitude of each array (square root of the sum of the squares of each component). Rosetta Code has an example of the dot product in JavaScript, copied here
// dotProduct :: [Int] -> [Int] -> Int
const dotProduct = (xs, ys) => {
const sum = xs => xs ? xs.reduce((a, b) => a + b, 0) : undefined;
return xs.length === ys.length ? (
sum(zipWith((a, b) => a * b, xs, ys))
) : undefined;
}
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
const zipWith = (f, xs, ys) => {
const ny = ys.length;
return (xs.length <= ny ? xs : xs.slice(0, ny))
.map((x, i) => f(x, ys[i]));
}
So, you would call
const score1 = dotProduct(sourceSequence, sequence1);
const score2 = dotProduct(sourceSequence, sequence2);
And whichever is bigger is the closer sequence to sourceSequence.

I'm not sure you need machine learning for this. You have a source pattern and you have some inputs and you basically want to perform a diff of the patterns.
Machine learning could be used to find the patterns, assuming you have some heuristic for measuring the error (if you're using unsupervised learning techniques) or you have sample sets to train the network.
But if you are simply wanting to measure the differences between one pattern and another pattern then just perform a diff operation. What you'll need to do is decide what differences your measuring and how to normalize the result.

I can't tell how exactly you would like to measure the similarity. I go by calculating the difference of corresponding items and accumulating these differences to see how much deviation it would result from the sum of the source array. You can play with the calculation the way you like.
function check([x,...xs],[y,...ys], state = {sumSource: 0, sumDiff: 0}){
state.sumSource += x;
state.sumDiff += Math.abs(x-y);
return xs.length ? check(xs,ys,state) : (100 - 100 * state.sumDiff / state.sumSource).toFixed(4) + "% similarity";
}
var soureSequence = [0.53,0.55,0.50,0.40,0.50,0.52,0.58,0.60],
sequence1 = [0.53,0.54,0.49,0.40,0.50,0.52,0.58,0.60],
sequence2 = [0.53,0.55,0.50,0.42,0.50,0.53,0.57,0.62];
console.log(check(soureSequence,sequence1));
console.log(check(soureSequence,sequence2));

Related

Algorithm or formula that can take an incrementing counter and make it appear uniquely random

I am wondering if there is a general formula of some sort that can take a single incrementing integer, and run it through a modulus sort of thing to shift it to a random place, so as you increment the counter, its output value jumps around and appears random, yet no value is ever hit twice. Assuming some limit on the set of numbers like 16-bit integers (65536 integers), or 32-bit integers, etc.. Perhaps there is a way to spiral numbers down somehow, I don't know. The sequence would be predictable, but to a layman it would appear random without thinking much of it.
For example, you can multiply a number by 2 to make it not appear directly incremented. But that's not very sophisticated. You could perhaps start the number at the middle of the set (like 30103 for 16-bit integers), then multiply by 2 and rotate the numbers using a modulus, and this would appear even less incremented. But you could still see a pattern.
I'm wondering what sorts of patterns or equations you could run an incremented number through (in a bounded set of integers) so that the output appears the least predictable as possible, and at the same time it never hits the same number twice. This way you could make IDs appear randomly generated to the layman without having to store all the IDs in a database in random order in advance. The formula would generate them from a single stored integer. What is possible in this regard, and what is the equation? How far can it theoretically go?
Maybe you could make the set odd, and skip every 20th number, and somehow prove that it will eventually revolve through the whole set without repeats. I can't figure this out though.
Update: This seems to be in the field of pseudorandom number generation, like this, but I'm not sure if they fit the added constraint of never repeating the number.
Here is what I found and implemented, but it's giving some duplicates :/.
const fetch = (x, o) => {
if (x >= o) {
return x
} else {
const v = (x * x) % o
return (x <= o / 2) ? v : o - v
}
}
const fetch32 = (x) => fetch(x, 4294967291)
const fetch16 = (x) => fetch(x, 65519)
const fetch8 = (x) => fetch(x, 251)
// the last number can be anything.
const build32 = (x, o) => fetch32((fetch32(x) + o) ^ 1542469173)
const build16 = (x, o) => fetch16((fetch16(x) + o) ^ 42703)
const build8 = (x, o) => fetch8((fetch8(x) + o) ^ 101)
let i = 0
let n = Math.pow(2, 32)
while (i < n) {
let j = 0
let r = {}
while (j < n) {
let x = build32(j, i)
if (r[x]) throw `${i}:${j}:${x}`
r[x] = true
j++
}
i++
}
The other linked question in the comment doesn't show a JavaScript implementation that adheres the the uniqueness constraint.
If you are looking for a sequence, where one value is produced from knowing what the previous value was, then what you are looking for could be a Linear congruential generator, with a modulus of a power of 2. There are a few parameters involved:
m: the modulus, which in your case is 28, 216, or 232.
a: the multiplier. To ensure that all values are produced before the first duplicate is generated, this must be a multiple of 4 plus 1 (assuming m is a power of 2).
c: the increment. It must be odd.
You can play with these numbers to arrive at a series that you are satisfied with in terms of "randomness".
The above referenced Wikipedia article lists some parameter choices that are used in some pseudo random generators. I have just selected a=97 and c some odd number half way the range.
Here is some code to prove the uniqueness:
/*
Assuming that m is a power of 2:
- c must be odd
- a % 4 must be 1
*/
function createFetch(m, a, c) { // Returns a function
return x => (a * x + c) % m;
}
const m = 2**16;
const fetch16 = createFetch(m, 97, (m>>1)-1);
const r = new Set;
let x = 1;
for (let i = 0; i < m; i++) {
x = fetch16(x);
if (i < 10) console.log(x);
if (r.has(x)) throw `${i}:${x}`
r.add(x);
}
console.log("...");
console.log(`generated ${r.size} unique numbers`);
NB/ this is a good use case for a generator, which in JavaScript looks like this:
function * fetch(m, a, c, x=1) {
while (true) {
x = (a * x + c) % m;
yield x;
}
}
const m = 2**16;
const fetch16 = fetch(m, 97, (m>>1)-1);
const r = new Set;
for (let i = 0; i < m; i++) {
x = fetch16.next().value;
if (i < 10) console.log(x);
if (r.has(x)) throw `${i}:${x}`
r.add(x);
}
console.log("...");
console.log(`generated ${r.size} unique numbers`);
Any block cipher whose block size is n bits is a permutation of {0,1,2, ..., 2n-1}. Thus, if E is such a block cipher and k is a valid key for E, then Ek(0), Ek(1), ..., Ek(2n-1) are all distinct. If the block cipher is good then the values appear "random" to the naked eye. If you change the key k you get a different permutation.
This is actually mentioned in the link you provided.
Consider this answer as well.
var bottomLimit = 1
var topLimit = 10
var arr = []
for (var i = bottomLimit; i < topLimit; i++) {
arr.push(i)
}
arr = shuffle(arr);
console.log(arr);
//https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array#answer-2450976
function shuffle(array) {
var currentIndex = array.length,
temporaryValue, randomIndex;
while (0 !== currentIndex) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
Well,you can generate random no. inside the range of two no.
public static int getRandomVal(int min, int max) {
Random random = new Random();
return random.nextInt((max - min) + 1) + min;
}
public static void getRandomNumbers(int size, int min,
int max) {
ArrayList<Integer> numbers = new ArrayList<Integer>();
while (numbers.size() < size) {
int random = getRandomVal(min, max);
if (!numbers.contains(random)) {
numbers.add(random);
System.out.println(" "+random);
}
}
}
now to generate 10 different no. between 50 and 100 you can use
getRandomNumbers(10, 50,100);
This approach is very easy I am creating an array and just checking the random value if it is already present or not. If it is not present I am pushing it to the array and outputting it.
Get yourself a seeded random number generator.
Seed with 1, return next random number. Seed with 2, return next random number. Seed with 3, return next random number...
If you seed with an integer then the next random number will be repeatable and pseudo random.

I need to extract every nth char of a string in Javascript

Ive been reading everything online but its not exactly what I need
var x = 'a1b2c3d4e5'
I need something to get me to
using 1 the answer should be abcde
using 2 the answer should be 12345
using 3 the answer should be b3e
the idea behind it if using 1 it grabs 1 skips 1
the idea behind it if using 2 it grabs 2 skips 2
the idea behind it if using 3 it grabs 3 skips 3
I dont want to use a for loop as it is way to long especially when your x is longer than 300000 chars.
is there a regex I can use or a function that Im not aware of?
update
I'm trying to some how implement your answers but when I use 1 that's when I face the problem. I did mention trying to stay away from for-loops the reason is resources on the server. The more clients connect the slower everything becomes. So far array.filter seem a lot quicker.
As soon as I've found it I'll accept the answer.
As others point out, it's not like regular expressions are magic; there would still be an underlying looping mechanism. Don't worry though, when it comes to loops, 300,000 is nothing -
console.time('while')
let x = 0
while (x++ < 300000)
x += 1
console.timeEnd('while')
// while: 5.135 ms
console.log(x)
// 300000
Make a big string, who cares? 300,000 is nothing -
// 10 chars repeated 30,000 times
const s =
'abcdefghij'.repeat(30000)
console.time('while string')
let x = 0
let interval = 2
let values = []
while (x < s.length)
{ values.push(s[x])
x += interval
}
let result = values.join('')
console.timeEnd('while string')
// while string: 31.990ms
console.log(result)
console.log(result.length)
// acegiacegiacegiacegiacegiacegiacegiacegia...
// 150000
Or use an interval of 3 -
const s =
'abcdefghij'.repeat(30000)
console.time('while string')
let x = 0
let interval = 3
let values = []
while (x < s.length)
{ values.push(s[x])
x += interval
}
let result = values.join('')
console.timeEnd('while string')
// while string: 25.055ms
console.log(result)
console.log(result.length)
// adgjcfibehadgjcfibehadgjcfibehadgjcfibe...
// 100000
Using a larger interval obviously results in fewer loops, so the total execution time is lower. The resulting string is shorter too.
const s =
'abcdefghij'.repeat(30000)
console.time('while string')
let x = 0
let interval = 25 // big interval
let values = []
while (x < s.length)
{ values.push(s[x])
x += interval
}
let result = values.join('')
console.timeEnd('while string')
// while string: 6.130
console.log(result)
console.log(result.length)
// afafafafafafafafafafafafafafafafafafafafafafa...
// 12000
You can achieve functional style and stack-safe speed simultaneously -
const { loop, recur } = require('./lib')
const everyNth = (s, n) =>
loop
( (acc = '', x = 0) =>
x >= s.length
? acc
: recur(acc + s[x], x + n)
)
const s = 'abcdefghij'.repeat(30000)
console.time('loop/recur')
const result = everyNth(s, 2)
console.timeEnd('loop/recur')
// loop/recur: 31.615 ms
console.log(result)
console.log(result.length)
// acegiacegiacegiacegiacegiacegiacegia ...
// 150000
The two are easily implemented -
const recur = (...values) =>
({ recur, values })
const loop = f =>
{ let acc = f()
while (acc && acc.recur === recur)
acc = f(...acc.values)
return acc
}
// ...
module.exports =
{ loop, recur, ... }
And unlike the [...str].filter(...) solutions which will always iterate through every element, our custom loop is much more flexible and receives speed benefit when a higher interval n is used -
console.time('loop/recur')
const result = everyNth(s, 25)
console.timeEnd('loop/recur')
// loop/recur: 5.770ms
console.log(result)
console.log(result.length)
// afafafafafafafafafafafafafafa...
// 12000
const recur = (...values) =>
({ recur, values })
const loop = f =>
{ let acc = f()
while (acc && acc.recur === recur)
acc = f(...acc.values)
return acc
}
const everyNth = (s, n) =>
loop
( (acc = '', x = 0) =>
x >= s.length
? acc
: recur(acc + s[x], x + n)
)
const s = 'abcdefghij'.repeat(30000)
console.time('loop/recur')
const result = everyNth(s, 2)
console.timeEnd('loop/recur')
// loop/recur: 31.615 ms
console.log(result)
console.log(result.length)
// acegiacegiacegiacegiacegiacegiacegia ...
// 150000
Since I'm not an expert of regex, I'd use some fancy es6 functions to filter your chars.
var x = 'a1b2c3d4e5'
var n = 2;
var result = [...x].filter((char, index) => index % n == 0);
console.log(result);
Note that because 0 % 2 will also return 0, this will always return the first char. You can filter the first char by adding another simple check.
var result = [...x].filter((char, index) => index > 0 && index % n == 0);
As a variant:
function getNth(str, nth) {
return [...str].filter((_, i) => (i + 1) % nth === 0).join('');
}
console.log(getNth('a1b2c3d4e5', 2)); // 12345
console.log(getNth('a1b2c3d4e5', 3)); // b3e
What I'd suggest, to avoid having to iterate over the entire array, is to step straight into the known nth's.
Here's a couple of flavors:
function nthCharSubstr(str, nth) {
let res = "";
for (let i = nth - 1; i < str.length; i += nth) {
res += string[i];
}
return res;
}
More ES6-y:
const nthCharSubstr = (str, nth) =>
[...Array(parseInt(str.length / nth)).keys()] // find out the resulting number of characters and create and array with the exact length
.map(i => nth + i * nth - 1) // each item in the array now represents the resulting character's index
.reduce((res, i) => res + str[i], ""); // pull out each exact character and group them in a final string
This solution considers this comment as being valid.

Can't get Lotka-Volterra equations to oscillate stable with math.js

I'm trying to implement a simple Lotka-Volterra system in JavaScript, but get different result from what I see in academic papers and slides. This is my equations:
sim2.eval("dxdt(x, y) = (2 * x) - (x * y)");
sim2.eval("dydt(x, y) = (-0.25 * y) + (x * y)");
using coefficients a = 2, b = 1, c = 0.25 and d = 1. Yet, my result looks like this:
when I expected a stable oscillation as seen in these PDF slides:
Could it be the implementation of ndsolve that causes this? Or a machine error in JavaScript due to floating-point arithmetic?
Disregard, the error was simply using a too big evaluation step (dt = 0.1, must be 0.01 at least). The numerical method used is known for this problem.
For serious purposes use a higher order method, the minimum is fixed step classical Runge-Kutta. Then you can also use dt=0.1, it is stable for multiple periods, I tried tfinal=300 without problems. However you will see the step size in the graph as it is visibly piecewise linear. This is much reduced with half the step size, dt=0.05.
function odesolveRK4(f, x0, dt, tmax) {
var n = f.size()[0]; // Number of variables
var x = x0.clone(),xh=[]; // Current values of variables
var dxdt = [], k1=[], k2=[], k3=[], k4=[]; // Temporary variable to hold time-derivatives
var result = []; // Contains entire solution
var nsteps = math.divide(tmax, dt); // Number of time steps
dt2 = math.divide(dt,2);
dt6 = math.divide(dt,6);
for(var i=0; i<nsteps; i++) {
// compute the 4 stages if the classical order-4 Runge-Kutta method
k1 = f.map(function(fj) {return fj.apply(null, x.toArray()); } );
xh = math.add(x, math.multiply(k1, dt2));
k2 = f.map(function(fj) {return fj.apply(null, xh.toArray()); } );
xh = math.add(x, math.multiply(k2, dt2));
k3 = f.map(function(fj) {return fj.apply(null, xh.toArray()); } );
xh = math.add(x, math.multiply(k3, dt));
k4 = f.map(function(fj) {return fj.apply(null, xh.toArray()); } );
x = math.add(x, math.multiply(math.add(math.add(k1,k4), math.multiply(math.add(k2,k3),2)), dt6))
if( 0==i%50) console.log("%3d %o %o",i,dt,x.toString());
result.push(x.clone());
}
return math.matrix(result);
}
math.import({odesolveRK4:odesolveRK4});

Javascript fill array with intermediate value

I'm trying to fill an array with missing intermediate data
My data input is like this
var data = [[5.23,7],[5.28,7],[5.32,8],[5.35,8]];
I wanna fill the array with missing value but I need to respect this rule:
The 1st value on 2d array must be the next sequence number, so 5.23
... 5.24 ... 5.25 ...
The 2nd value on 2d array must be the same element from the i+1
value
So the results in this case would be
var data = [[5.23,7],[5.24,7],[5.25,7],[5.26,7],[5.27,7],[5.28,7],[5.29,8],[5.30,8],[5.31,8],[5.32,8],[5.33,8],[5.34,8],[5.35,8]];
This little piece of code works, but I don't know
how to put in loop
and how to write a while loop that pass every time the new length of the array
var data = [[5.23,7],[5.28,7],[5.32,8],[5.35,8]];
if (data[1][0]-data[0][0] > 0.01) {
data.push([data[0][0]+0.01,data[1][1]]);
data.sort(function (a, b) { return a[0] - b[0]; });
} else {
check the next element
}
console.log(data);
Any idea?
Here's another idea... I thought it might feel more natural to loop through the sequence numbers directly.
Your final array will range (in this example) from 5.23 to 5.35 incrementing by 0.01. This approach uses a for loop starting going from 5.23 to 5.35 incrementing by 0.01.
key points
Rounding: Work in x100 then divide back down to avoid floating point rounding issues. I round to the neared hundredth using toFixed(2) and then converting back to a number (with leading + operator).
Indexing: Recognizing 5.23 is the zero index with each index incrementing 1/100, you can calculate index from numerical values, ex. 100*(5.31-5.23) equals 8 (so 5.31 belongs in output[8]).
2nd values: given a numerical value (ex. 5.31), just find the first element in the data array with a higher 1st value and use its 2nd value - this is a corollary of your requirement. Because 5.31 <= 5.28 is false, don't use 7 (from [5.28,7]). Because 5.31 <= 5.32 is true, use 8 (from [5.32,8]).
EDIT
I improved the performance a bit - (1) initialize output instead of modifying array size, (2) work in multiples of 100 instead of continuously rounding from floating point to hundredths.
I ran 5000 iterations on a longer example and, on average, these modifications make this approach 3x faster than Redu's (where the original was 2x slower).
var data = [[5.23,7],[5.28,7],[5.32,8],[5.35,8]];
var output = Array((data[data.length-1][0]-data[0][0]).toFixed(2)*100+1)
function getIndex(value){
return (value-data[0][0]*100)
}
for( var i = 100*data[0][0]; i <= 100*data[data.length-1][0]; i++ ){
output[getIndex(i)] = [i/100, data.find( d => i <= 100*d[0] )[1]]
}
//console.log(output)
// Performance comparison
function option1(data){
let t = performance.now()
var output = Array((data[data.length-1][0]-data[0][0]).toFixed(2)*100+1)
function getIndex(value){
return (value-data[0][0]*100)
}
for( var i = 100*data[0][0]; i <= 100*data[data.length-1][0]; i++ ){
output[getIndex(i)] = [i/100, data.find( d => i <= 100*d[0] )[1]]
}
return performance.now()-t
}
function option2(data){
let t = performance.now()
newData = data.reduce((p,c,i,a) => i ? p.concat(Array(Math.round(c[0]*100 - a[i-1][0]*100)).fill()
.map((_,j) => [Number((a[i-1][0]+(j+1)/100).toFixed(2)),c[1]]))
: [c],[]);
return performance.now()-t
}
var testdata = [[1.13,4],[2.05,6],[5.23,7],[5.28,7],[5.32,8],[5.35,8],[8.91,9],[10.31,9]];
var nTrials = 10000;
for(var trial=0, t1=0; trial<=nTrials; trial++) t1 += option1(testdata)
for(var trial=0, t2=0; trial<=nTrials; trial++) t2 += option2(testdata)
console.log(t1/nTrials) // ~0.4 ms
console.log(t2/nTrials) // ~0.55 ms
Array.prototype.reduce() is sometimes handy to extend the array. May be you can do as follows;
var data = [[5.23,7],[5.28,7],[5.32,8],[5.35,8]],
newData = data.reduce((p,c,i,a) => i ? p.concat(Array(Math.round(c[0]*100 - a[i-1][0]*100)).fill()
.map((_,j) => [Number((a[i-1][0]+(j+1)/100).toFixed(2)),c[1]]))
: [c],[]);
console.log(newData);
var data = [[1.01,3],[1.04,4],[1.09,5],[1.10,6],[1.15,7]],
newData = data.reduce((p,c,i,a) => i ? p.concat(Array(Math.round(c[0]*100 - a[i-1][0]*100)).fill()
.map((_,j) => [Number((a[i-1][0]+(j+1)/100).toFixed(2)),c[1]]))
: [c],[]);
console.log(newData);
I propose this solution :
var data = [[5.23,7],[5.28,7],[5.32,8],[5.35,8]];
var res = [];
data.forEach((item, index, arr) => {
res.push(item);
var temp = item[0];
while (arr[index+1] && arr[index+1][0]-temp > 0.01){
temp += 0.01;
res.push([temp, arr[index+1][1]]);
}
});
console.log(res);

Inverting a binary value of a number

I would like first to convert a number to binary, then invert it bitwise.
Like this:
Number is 793 = 1100011001
then convert the binary value into: 0011100110
In JavaScript I can do the following:
var x = 793;
document.write(x.toString(2)); // gives 0011100110
This will give me the binary value of the number.
But how do I invert the binary bitwise?
I tried the ~ operator, but not working probably. The output is: -1100011010
MooGoo's answer is correct.
Here is some information about what is happening.... Lets assume this is a 64 bit integer.
793 = 1100011001
~793 = -794 = 1111111111111111111111111111111111111111111111111111110011100110
0x3ff = 1111111111
(-793 & 0x3ff) = 11100110
So you could do this to solve for all cases with this code:
var x = 793; // input value
var y = x.toString(2);
var yl = y.length;
var mask = (Math.pow(2,yl)-1); // calculate mask
var result = ~x & mask;
document.write(result.toString(2)+"<br/>");
You need to use a bitmask.
(~793 & 0x3ff).toString(2) //11100110
Or with XOR
793 ^ 0x3ff
You want to XOR the binary value with 111111111 - however many 1s as there are digits in the original. So:
var x = 793;
var result = x ^ parseInt((new Array(x.toString(2).length+1)).join("1"),2);
(Code for str_repeat taken from PHP.JS)
Revisiting years later, try:
var x = 793;
var result = parseInt(x.toString(2).replace(/[01]/g,function(n) {return 1-n;}),2);
I believe this will be more efficient... probably. Could be completely wrong. Oh well.
Not the shortest code but more readable. My technique is similar to #Ivo Wetzel:
const bitwiseComplement = (N) => {
let binary = N.toString(2); // 793 is "1100011001" in binary
binary = binary.split('').map(x => {
return (x == 1) ? 0 : 1;
}).join('');
return binary; // with complement "0011100110" in binary
};
console.log(bitwiseComplement(793));
One-liner javascript solution. Regex /[0-1]/g means match a single character present in the list below [0-1].
const bitwiseComplement = (N) => {
return N.toString(2).replace(/[0-1]/g, (v) => (v == 1 ? 0 : 1));
};
console.log(bitwiseComplement(793));
I just do this
Let's say x = -11.3 and it's a 16 bit integer from somewhere.
My results will go into variable r.
var r = ((x & 0x7FFF) ^ 0x7FFF)+1;
It's the kiss principle.
Update
It's unclear to me whether you want a string of the inverted value, if so you can do this:
function invert(x){
var e = x.toString(2).split('');
for(var i = 0, l = e.length; i < l; i++) {
e[i] = e[i] === '0' ? '1' : (e[i] === '1' ? '0' : e[i]);
}
return e.join('');
}
invert(793); // '0011100110'
invert(-793); // '-0011100110'
This will also preserve leading zeros.

Categories

Resources