Compare Math expressions with JavaScript - javascript

How can I compare two math expressions in JavaScript?
For example "1 + x" and "x + 1".
There is a JavaScript Math parser but I couldn't find the logic to compare the parsed expressions:
https://github.com/silentmatt/js-expression-eval/blob/master/test.js
Are there other options?
Thanks

You will need a computer algebra system (CAS) to be able to truly test whether two expressions are equal. The only one I know of in JavaScript is javascript-cas, I'm not sure if this does what you need though. Other libraries like math.js and the mentioned js-expression-eval can parse expressions but miss to logic to understand whether two expressions are equal.
A pragmatic approach may be to compare the outcome of both expressions for a number of different values for x, and see if they have the same result. This will not always work though, for example 0/x+1 and x-x give the same result for every x but they aren't really equal.

If you need to know just the equality then you can do approximate comparison:
extract variable names from expressions
you have x+1 and 1+x so there is single variable x
genere pseudo random or grid set of values for them
use some spec point from -inf to +inf like x={ -1e-10, 1e-9, .... 1e+9,1e+10 }
add few randoms
parse each expression with current variable set
so take first x value
compute expressions value for it
if it is not the same expresions are not the same
try all cases from genered data set
if all pass then expressions are likely the same
if not (even if just in one pass) then expressions are not the same

Related

Math Equation Algorithm Javascript

for example, if I had a STRING = "3+3*(4-1)"
if a ran a function and wanted it to solve the equation using javascript, what Would I start with?
Assuming the equation has a correct syntax of javascript, you can use eval to evaluate the value.
i.e.
eval("3+3*(4-1)") = 12

Javascript eval - obfuscation?

I came across some eval code:
eval('[+!+[]+!+[]+!+[]+!+[]+!+[]]');
This code equals the integer 5.
What is this type of thing called? I've tried searching the web but I can't seem to figure out what this is referred to. I find this very interesting and would like to know where/how one learns how to print different things instead of just the integer 5. Letters, symbols and etc. Since I can't pin point a pattern in that code I've had 0 success taking from and adding to it to make different results.
Is this some type of obfuscation?
This type of obfuscation, eval() aside, is known as Non-alphanumeric obfuscation.
To be completely Non-alphanumeric, the eval would have to be performed by Array constructor prototypes functions and subscript notation:
[]["sort"]["constructor"]("string to be evaled");
These strings are then converted to non-alphanumeric form.
AFAIK, it was first proposed by Yosuke Hosogawa around 2009.
If you want to see it in action see this tool: http://www.jsfuck.com/
It is not considered a good type of obfuscation because it is easy to reverse back to the original source code, without even having to run the code (statically). Plus, it increases the file size tremendously.
But its an interesting form of obfuscation that explores JavaScript type coercion. To learn more about it I recommend this presentation, slide 33:
http://www.slideshare.net/auditmark/owasp-eu-tour-2013-lisbon-pedro-fortuna-protecting-java-script-source-code-using-obfuscation
That's called Non-alphanumeric JavaScript and it's possible because of JavaScript type coercion capabilities. There are actually some ways to call eval/Function without having to use alpha characters:
[]["filter"]["constructor"]('[+!+[]+!+[]+!+[]+!+[]+!+[]]')()
After you replace strings "filter" and "constructor" by non-alphanumeric representations you have your full non-alphanumeric JavaScript.
If you want to play around with this, there is a site where you can do it: http://www.jsfuck.com/.
Check this https://github.com/aemkei/jsfuck/blob/master/jsfuck.js for more examples like the following:
'a': '(false+"")[1]',
'b': '(Function("return{}")()+"")[2]',
'c': '([]["filter"]+"")[3]',
...
To get the value as 5, the expression should have been like this
+[!+[] + !+[] + !+[] + !+[] + !+[]]
Let us analyze the common elements first. !+[].
An empty array literal in JavaScript is considered as Falsy.
+ operator applied to an array literal, will try convert it to a number and since it is empty, JavaScript will evaluate it to 0.
! operator converts 0 to true.
So,
console.log(!+[]);
would print true. Now, the expression can be reduced like this
+[true + true + true + true + true]
Since true is treated as 1 in arithmetic expressions, the actual expression becomes
+[ 5 ]
The + operator tries to convert the array ([ 5 ]) to a number and which results in 5. That is why you are getting 5.
I don't know of any term used to describe this type of code, aside from "abusing eval()".
I find this very interesting and would like to know where/how one
learns how to print different things instead of just the integer 5.
Letters, symbols and etc. Since I can't pin point a pattern in that
code I've had 0 success taking from and adding to it to make different
results.
This part I can at least partially answer. The eval() you pasted relies heavily on Javascript's strange type coercion rules. There are a lot of pages on the web describing various strange consequences of the coercion rules, which you can easily search for. But I can't find any reference on type coercion with the specific goal of getting "surprising" output from things like eval(), unless you count this video by Destroy All Software (the Javascript part starts at 1:20). Most of them understandably focus on how to avoid strange bugs in your code. For your purpose, I believe the most useful things I know of are:
The ! operator will convert anything to a boolean.
The unary + operator will convert anything to a number.
The binary + operator will coerce its arguments to either numbers or strings before adding or concatenating them. Normally it will only go with strings if one or the other argument is already a string, but there are exceptions.
The bitwise operators output integers, regardless of input.
Converting to numbers is complicated. Booleans will go to 0 or 1. Strings will attempt to use parseInt(), or produce NaN if that fails. I forget the rest.
Converting an object to a string or number will invoke its "toString" or "toValue" method respectively, if one exists.
You get the idea. thefourtheye's answer walks through exactly how these rules apply to the example you gave. I'm not even going to try summarizing what happens when Dates, Functions, and Regexps are involved.
Is this some type of obfuscation?
Normally you'd simply get obfuscation for free as part of minification, so I have no idea why someone would write that in real production code (assuming that's where you found it).

Why Javascript ===/== string equality sometimes has constant time complexity and sometimes has linear time complexity?

After I found that the common/latest Javascript implementations are using String Interning for perfomance boost (Do common JavaScript implementations use string interning?), I thought === for strings would get the constant O(1) time. So I gave a wrong answer to this question:
JavaScript string equality performance comparison
Since according to the OP of that question it is O(N), doubling the string input doubles the time the equality needs. He didn't provide any jsPerf so more investigation is needed,
So my scenario using string interning would be:
var str1 = "stringwithmillionchars"; //stored in address 51242
var str2 = "stringwithmillionchars"; //stored in address 12313
The "stringwithmillionchars" would be stored once let's say in address 201012 of memory
and both str1 and str2 would be "pointing" to this address 201012. This address could then be determined with some kind of hashing to map to specific locations in memory.
So when doing
"stringwithmillionchars" === "stringwithmillionchars"
would look like
getContentOfAddress(51242)===getContentOfAddress(12313)
or 201012 === 201012
which would take O(1)/constant time
JSPerfs/Performance updates:
JSPerf seems to show constant time even if the string is 16 times longer?? Please have a look:
http://jsperf.com/eqaulity-is-constant-time
Probably the strings are too small on the above:
This probably show linear time (thanks to sergioFC) the strings are built with a loop. I tried without functions - still linear time / I changed it a bit http://jsfiddle.net/f8yf3c7d/3/ .
According to https://www.dropbox.com/s/8ty3hev1b109qjj/compare.html?dl=0 (12MB file that sergioFC made) when you have a string and you already have assigned the value in quotes no matter how big the t1 and t2 are (e.g 5930496 chars), it is taking it 0-1ms/instant time.
It seems that when you build a string using a for loop or a function then the string is not interned. So interning happens only when you directly assign a string with quotes like var str = "test";
Based on all the Performance Tests (see original post) for strings a and b the operation a === b takes:
constant time O(1) if the strings are interned. From the examples it seems that interning only happens with directly assigned strings like var str = "test"; and not if you build it with concatenation using for-loops or functions.
linear time O(N) since in all the other cases the length of the two strings is compared first. If it is equal then we have character by character comparison. Else of course they are not equal. N is the length of the string.
According to the ECMAScript 5.1 Specification's Strict Equal Comparison algorithm, even if the type of Objects being compared is String, all the characters are checked to see if they are equal.
If Type(x) is String, then return true if x and y are exactly the same sequence of characters (same length and same characters in corresponding positions); otherwise, return false.
Interning is strictly an implementation thingy, to boost performance. The language standard doesn't impose any rules in that regard. So, its up to the implementers of the specification to intern strings or not.
First of all, it would be nice to see a JSPerf test which demonstrates the claim that doubling the string size doubles the execution time.
Next, let's take that as granted. Here's my (unproven, unchecked, and probably unrelated to reality) theory.
Compairing two memory addresses is fast, no matter how much data is references. But you have to INTERN this strings first. If you have in your code
var a = "1234";
var b = "1234";
Then the engine first has to understand that these two strings are the same and can point to the same address. So at least once these strings has to be compared fully. So basically here are the following options:
The engine compares and interns strings directly when parsing the code. In this case equals strings should get the same address.
The engine may say "these strings are two big, I don't want to intern them" and has two copies.
The engine may intern these strings later.
In the two latter cases string comparison will influence the test results. In the last case - even if the strings are finally interned.
But as I wrote, a wild theory, for theory's sage. I'd first like to see some JSPerf.

Getting the numeric value after the hyphen in a string

How can I extract and get just the numeric value after the hyphen in a string?
Here is the input string:
var x = "-2147467259"
After some processing.... return:
alert(2147467259)
How do I accomplish this?
You could replace away the hyphen:
alert(+x.replace("-", ""));
And yes, the + is important. It converts a string to a number; so you're removing the hypen by replacing it with nothing, and then essentially casting the result of that operation into a number. This operation will also work if no hyphen is present.
You could also use substr to achieve this:
alert(+x.substr(1));
You could also use parseInt to convert the string to a number (which will end up negative if a hyphen is persent), and then find its absolute value:
alert(Math.abs(parseInt(x, 10));
As Bergi notes, if you can be sure that the first character in the string is always a hyphen, you can simple return its negative, which will by default cast the value into a number and then perform the negative operation on it:
alert(-x);
You could also check to see if the number is negative or positive via a tertiary operator and then perform the respective operation on it to ensure that it is a positive Number:
x = x >= 0 ? +x : -x;
This may be cheaper in terms of performance than using Math.abs, but the difference will be minuscule either way.
As you can see, there really are a variety of ways to achieve this. I'd recommend reading up on JavaScript string functions and number manipulation in general, as well as examining JavaScript's Math object to get a feel for what tools are available to you when you go to solve a problem.
How about:
Math.abs(parseInt("-2147467259"))
Or
"-2147467259".replace('-','')
or
"-2147467259".replace(/\-/,'')
#1 option is converting the string to numbers. The #2 approach is removing all - from the string and the #3 option even though it will not be necessary on this example uses Regular Expression but I wanted to show the possibility of using RegEx in replace situations.
If you need a number as the final value #1 is your choice if you need strings #2 is your choice.

Bitwise check in Javascript

I play a game, and in the database we set 100663296 to be a GM Leader but also this field in the database gets written to for different things, so it changes that number to 100794368
i was told to possible use a bit-wise check to check whether the first number is the same as the second number, and I have googled on using bit-wise checks but got confused as to what to use for my check.
Here are some other numbers that change, including the one from above.
predefined number new changed number/ever changing number.
100663296 = 100794368
67108864 = 67239936
117440512 = 2231767040
so how should i go about checking these numbers?
And here is part of my code that i was using before i noticed the change in the numbers.
if (playerData[i].nameflags == 67108864)
{
playerRows += '<img src ="icons/GM-Icon.png" alt="GM" title="GM"></img>';
}
thx to Bergi, for the answer.
if (playerData[i].nameflags & 0x400000 /* === 0x400000 */)
this seams to work great.
also thx to vr1911428
and every one else for the help on this.
So let's convert those numbers to binary representation (unsigned integer):
> 100663296
00000110000000000000000000000000
> 100794368
00000110000000100000000000000000
> 67108864
00000100000000000000000000000000
> 67239936
00000100000000100000000000000000
> 117440512
00000111000000000000000000000000
> 2231767040
10000101000001100001000000000000
Notice that the last number is out of the scope of JavaScripts bitwise arithmetic, which only works with 32-bit signed integers - you won't be able to use the leftmost bit.
So which bits do you want to compare now? There are lots of possibilities, the above scheme doesn't make it clear, yet it looks like you are looking for the 27th bit from the right (226 = 67108864). To match against it, you can apply a binary AND bitmask:
x & Math.pow(2, 26)
which should evaluate to 226 again or zero - so you can just check for truthiness. Btw, instead of using pow you could use hexadecimal notation: 0x4000000. With that, your condition will look like this:
if (playerData[i].nameflags & 0x400000 /* === 0x400000 */)
If you need to check for full bitwise equality of two integers, all you need is just '==' operator, but to use it, you should guarantee that both operands are integers:
left = 12323;
right = 12323;
if (left == right)
alert("Operands are binary equal; I'll guarantee that. :-)");
Be very careful though; if at least one of operands is string representing number, not a number, both operands will be considered strings and you can get confusing results:
left = "012323";
right = 12323;
if (left != right)
alert("Operands are not equal, even though they represent 'equal values', as they are compared as strings.");
In general, these days, the attempt to operate with strings representing data instead of data itself is a real curse of the beginners; and it's hard to explain to them. It is especially difficult to explain in JavaScript, with its loose-type typing concept, which is itself very complex and hard to understand, behind the illusory simplicity.
Finally, if you need to compare separate bits (and, from your question, I don't see this need), you can use binary operators:
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Bitwise_Operators
That's it, basically.
...................

Categories

Resources