Draw graph without using eval() - javascript

I have created a Chrome extension that can draw the graph of the math equation user has inputted. To get the value of y easily, I used eval() (Yes I know it is bad) because the easiest way to achieve it.
var equ = $("#equ1").val(); //some element
//let's say equ = "2(2^x) + 3x"
//some magic code
//equ becomes "2*(pow(2,x))+3*x"
for(var x = -10; x < 10; x++){
var y = eval(equ.replace(/x/ig, x)); //calculate y value
drawPoint(x, y);
}
console.log("Graphing done.");
However, because of the new manifest version 2, I can't use eval anymore. I can't think of any way to manipulate the string. Any idea?

The clean way: You could try parsing the expression using Jison and building an AST from the input string. Then, associate functions with the AST node that apply the operations that the nodes represent to data given to them. This would mean that you have to explicitly put every math expression that you want to support in your grammar and your node code, but on the other hand, this would also make it easier to support mathematical operators that JS doesn't support. If you're willing to invest some time, this probably is the way to go.
The dirty way: If your extension is used on normal websites, you might be able to do some kind of indirect eval by injecting a <script> element into the website or so – however, that would likely be insecure.

Did you try New Function() ... ??
var some_logic = "2*(Math.pow(2,x))+3*x";
args = ['x', 'return (' + some_logic + ');'];
myFunc = Function.apply(null, args);
for (var x = -10; x < 10; x++) {
var y = myFunc(x);
console.log(x, y);
}
console.log("Graphing done.");
Fiddle - http://jsfiddle.net/atif089/sVPAH/

Related

string + string VS += in Javascript

space and/or perfomance wise, what would be a more efficient way to add strings, in the case of having many string literals concatenated together, in Javascript?
x += y;
OR
x + y;
I've been pondering about this for a while. Of course for a case where there are only two strings being concatenated together there would be virtually no difference, but what about cases where a CSS or html document is being structured inside the JS, or a huge XML, for whatever reason?
string += " classA {}";
...
.....
string += "classX {}";
VS
string + "classA {}" +
...
.....
+ "classX {}";
Sorry if this sounds like a basic question, but I had a similar problem when I had to code an XML parser in Java and realized the usage of StringBuilder. Not sure how this translates to JavaSript.
Do you want to modify x? More specifically, does it matter if x gets modified?
x + y on its own doesn't do anything unless used as an argument or captured to a variable. let z = x + y does, as does f(x + y).
x += y is equivalent to x = x + y and so modifies x, which may or may not be what you want.
Normally if your intent is to "append to x" and save the result then you'd say x += y.
If your intent is to use the combined x and y in some other place, such as f(x + y), then that's appropriate. Here f(x += y) sends mixed messages, as it's not clear why you'd be appending and calling.
It's purely your own choice. How you're comfortable doing. Doesn't have any specific standard to it. I could argue that when using x += y when you have to use multiple statements between the string declaration & modification. However, again it still comes down to your own choice.

Javascript variable what is less efficient

I am learning Javascript currently.I was wondering if there is any difference between:
var factor=0.1;
var limit=10;
var x;
var y;
x= limit*factor;
y= limit*factor;
//or
var limit=10;
var x;
var y;
x=limit *0.1;
y=limit*0.1;
Does it make any difference (when looking at performance for example)? If so, why it is different? The second example looks less promising to me, because I keep thinking that I am declaring the variable 0.1 twice. Thanks for your help in advance.
There is a very small difference. When you use factor in the two multiplications, the JavaScript engine has to go look up the value of factor in the current lexical environment object each time — in theory, anyway; optimization may well be able to get rid of that, if and when the code is chosen for optimization by the JavaScript engine.
But regardless: Worry about performance problems when you have a performance problem to worry about. Instead, concentrate on readability and maintainability. If x and y are meant to be multiplied by the same value, put that value in something (a var, or perhaps a const with ES2015+), and use it in both places.
I would suggest you go ahead with the first example, but with a modification. Variables are meant to hold dynamic data, it is better to hold 0.1 in a variable, so you can change it over time if required.
// have a function so that you don't repeat the code
function getFactor(factor, limit) {
return limit * factor;
}
//declare the variables and set the required default values
var factor = 0.1,
limit = 10,
x, y;
//assign getFactor to x and y variables
x = y = getFactor(factor, limit);

Solving simulataneous equations with Coffeequate

I'm looking for a Computer Algebra System to run in a browser, with a particular interest in finding roots to systems of equations.
I'm currently evaluating Coffeequate.
The simplest non-trivial system I came up with that wasn't on the demo page was a system of two simultaneous linear equations:
var exp1 = CQ('x = 2 * y + 6');
var exp2 = CQ('x - y = 10');
exp2.sub({x: exp1.solve('x')})
.solve('y');
Unfortunately, this hangs at the sub call.
What I would like to obtain is the value for all unknowns (i.e. x and y) that are knowable – there is guaranteed to be a solution in this case.
What am I doing wrong here?
CQ().solve returns an array of solutions (in case there are multiple solutions). However, things that you want to substitute in using CQ().sub have to be integers or CQ() objects themselves. The following code works:
var exp1 = CQ('x = 2 * y + 6');
var exp2 = CQ('x - y = 10');
exp2.sub({x: exp1.solve('x')[0]}).solve('y'); // 4
The fact that it actually hangs instead of erroring when you pass in an array is a bug; I'll patch that.
(Disclaimer: I wrote Coffeequate)

JS: Resolve a Formula for x

I have a formula with several components, let's say w = x * y / z^2 + c. Now I have an input-field for each variable. My goal is, to calculate the missing one as soon, as all the others were entered. Difficulty is, that you can choose which fields you fill and which you want to leave free.
The easy (naive) way would of course be to resolve it for each variable by hand, detect the missing var, and have seperate js functions for each case. But I even have linked formulas (like x in the above formula is x = a + b, too) as well and the options are almost infinitive. Is there any option in JS to solve a formula by a specified variable? I could then replace each variable string with the assigned value and then eval the string.
First I thought Nerdamer would be the thing, but it turned out that it can only evaluate expressions and can't handle equations.
Is this possible? Any better idea?
Thanks in advance!
P.S.: My actual set of formula is:
dR = c * I^2 / A
R = L * dR
P = I * U
DV = R * I
DW = DV * I
It's for calculating losses in a cable due to ohm's resistance. Each Variable has a corresponding input field.
The following solution can be built for finding "R" using nerdamer. The logic can be extended to solve for the remaining variables. Do keep in mind that the current limitation is that nerdamer can currently only solve up to cubic functions algebraically. Higher order functions will be solved numerically.
//You can then take care of the non linear containing I. I is quadratic
var dR = nerdamer('R=L*dR').solveFor('dR');
var I = nerdamer('dR=c*I^2/A').sub('dR', dR).solveFor('I');
//You can first start by reducing the first few equations since they are linear and you can solve them as a linear system
var solutions = nerdamer.solveEquations(['P = I * U', 'DV = R * I', 'DW = DV * I'], ['I', 'DW', 'P']);
//the solutions come back as an array arrays in the form of [variable, value]
//you can see what they look like. In your case all your solutions will be in terns of DV & U since these are the only actual knowns
//You can see what the solutions look like
solutions.map(function(x) {
console.log('-'+x[0]+' = '+x[1]);
});
console.log('------------------ R ----------------');
var R = nerdamer.setEquation(I[0], solutions[0][1]).solveFor('R');
//I will have 3 solutions since it's cubic. You can console.log them below
R.map(function(x) {
console.log('R = '+x.toString());
});
<script src="https://cdn.jsdelivr.net/npm/nerdamer#latest/nerdamer.core.js"></script>
<script src="https://cdn.jsdelivr.net/npm/nerdamer#latest/Algebra.js"></script>
<script src="https://cdn.jsdelivr.net/npm/nerdamer#latest/Calculus.js"></script>
<script src="https://cdn.jsdelivr.net/npm/nerdamer#latest/Extra.js"></script>
<script src="https://cdn.jsdelivr.net/npm/nerdamer#latest/Solve.js"></script>

Parsing XML Text with jQuery

I'm working with a database that has X and Y points per group, it's being used to draw outlines of images.
Right now in my web side this code is what I use to get the points:
var Drawing = $(XML).find('DrawingXML');
alert($(Drawing[1]).text());
Result:
<DrawingPoints>
<Point><X>1</X><Y>2</Y></Point>
<Point><X>2</X><Y>4</Y></Point>
<Point><X>3</X><Y>5</Y></Point>
<Point><X>2</X><Y>2</Y></Point>
<Point><X>0</X><Y>4</Y></Point>
</DrawingPoints>
Using the .replace() call only changes one item so it's usable for something like this:
.replace("</DrawingPoints>","");
but if I want to replace all 'Point' tags I'm out of luck.
My goal is to use the canvas feature to draw the points out so I want it to be parsed like this:
ctx.beginPath();
ctx.moveTo(1,2);
ctx.lineTo(2,4);
ctx.lineTo(3,5);
ctx.lineTo(2,2);
ctx.lineTo(0,4);
ctx.stroke();
I'm not going to use this with IE browsers just Safari/Chrome, if that helps out.
In this case you'll probably save an awful lot of brainache by using a library instead of writing your own code.
I reckon d3 does what you need:
d3.xml
d3.geo.path
Check out this question/answer. It's not Prototype specific and should help you here.
How to parse XML string with Prototype?
Get all your X and Y values at once:
var points = {};
points.X = Array();
points.Y = Array();
var ix = 0;
$(XML).find('DrawingXML DrawingPoints Point X').each(function()
{
points.X[ix++] = $(this).text();
});
$(XML).find('DrawingXML DrawingPoints Point Y').each(function()
{
points.Y[ix++] = $(this).text();
});
This might not be exact, I didn't test it and my Javascript is a bit rusty, but you get the idea.

Categories