jquery calculate dynamic equation - javascript

I need to perform calculation on dynamic string.
I will get an equation from db named rule through ajax.
the rule may contain equation with operators like +,-,*,/,%.
how to perform this calculation?
for (var i = 0; i < rules.length; i++) {
var rule = rules[i].rule; // may contain $structurename1$*$structurename2$/$structurename3$ like this
$('form :input[type="text"]').each(function(index,value){
rule = rule.replace('$'+$(this).attr('structurename')+'$',$(this).val());
});
}
$('#result').val(rule);

Calculate string value in javascript, not using eval
Using a combination of code from above link:
1. Strip anything in formula that thats not a number, parenthesis, OR operator.
2. evalulate formula as function
Modified to return NaN if the function errors due to invalid input. Which shouldn't happen due to the RegExp replacements in step 1.
function calc(fn) {
var formula = fn.replace(/[^-()\d/*+.]/g, '');
try {
return new Function('return ' + formula)();
} catch (err) {
return NaN;
}
}
DEMO:
https://jsfiddle.net/tjywg716/

var str_expression=textbox1.text();
var result=eval(str_expression);
textbox2.text(result);

Related

How to use .toFixed() (or any alternative) on Nerdamer.solve solutions?

I'm using Nerdamer.solve() to get some linear equation roots. It's working fine but I wonder if there is any way to get only the first 4 decimals of every solution.
EquationSolver.js
//First step, using Nerdamer to solve the equation stored in value
sol_raw = this.nerdamer.solve(value,'x');
xs = this.nerdamer(sol_raw.toString());
//Second step, using Function() in order to evaluate the solutions
solution= Function('return ' + this.nerdamer(xs).evaluate().toString())()
At this point, I'm getting correct results like: 1.74343434. Since I'm rendering the results using Katex, I would like to know where to implement .toFixed(4) or any pseudo way (maybe a Nerdamer method to use n number of decimals on .evaluate()?).
Note.
The result (solution) is a string like [1.74343434, 0.434343, ...] so I could transform it into a float variable and then use .toFixed() but this not an easy solution because the number of roots depends on the equation's grade.
Nerdamer's documentation about evaluate: documentation
#CoronelV,
Another possible approach is to create a toFixed function for formatting the numbers which would take into account real and complex solutions and then calling it on your solutions. Here's a more generalized approach.
var toFixed = function(value, n) {
var img = Number(nerdamer.imagpart(value).text()).toFixed(n);
var real = Number(nerdamer.realpart(value).text()).toFixed(n);
// Format the number assuming i denotes imaginary in your case
var formatted = '';
if(real !== '0.0000') {
formatted += real;
}
if(img !== '0.0000') {
// Put the plus sign betweent the real and imaginary
if(img.charAt(0) !== '-' && formatted) {
formatted += '+';
}
// Assuming you're using i and not j for instance
formatted += img+'i';
}
return formatted;
};
So in your case this would be become something like:
sol_raw = this.nerdamer.solve(value,'x');
xs = this.nerdamer(sol_raw.toString()).each(function(solution) {
roundedSolutions.push(toFixed(solution, 4));
});
this.setState({
solution: roundedSolution.join(''),
equation:value})
This would possibly eliminate the need for your try catch block.
Since the solution is rendered using KaTeX, it's possible rounding the solution via Latex's package, but its even simplest taking the suggestion of #Dj Burb.
Here is my approach:
try {
sol_raw = this.nerdamer.solve(value,'x');
xs = this.nerdamer(sol_raw.toString());
Function('return '+ this.nerdamer(xs).evaluate().toString())().forEach(element => {
roundedSolution.push(element.toFixed(4)) });
} catch (e) {
}
this.setState({
solution: roundedSolution.join(''),
equation:value})
The use of try catch is imperative because while writing the equation, solution.toFixed() returns an error.

Javascript Front end - Evaluate string as expression - Alternative for using eval()

I would like to evaluate a string as an expression in Javascript. I'm reading the string from a JSON which is dynamic. So, the expression can be anything. Here is the pseudo code I'm using
var formula = {
"expression":"value * 9/5 + 32" //Dynamic JSON
}
var value = 26; // Dynamic value
var result = evaluateExpression(value, formula);
function evaluateExpression(value, formula) {
return eval(formula.expression);
}
This is how I've been using eval(). Is there any other alternative to this? I've also considered using Math.js, which I think is overkill for my requirements.
An alternative to eval would be to create a parser and evaluator in javascript. This is rather trivial, but a bit tedious. eval is mostly fine, unless you're going to evaluate strings provided by one user in the other user's browser. If this is the case, you'll have to write a parser (or generate it with a tool like PEG.js).
you could achieve the same using Function constructor
var formula = {
"expression":"value * 9/5 + 32" //Dynamic JSON
}
var value = 26; // Dynamic value
var result = evaluateExpression(value, formula);
alert(result);
function evaluateExpression(value, formula) {
return (new Function( 'value', 'return (' + formula.expression + ')' )(value));
//return eval(formula.expression);
}

I need a JavaScript procedure that reverses the following procedure

I have the following function that encrypts a string and I was hoping for a function that reverses the process.
function encryptStr(thisString)
{
retString = "";
/* Make retString a string of the 8-bit representations of
the ASCII values of its thisCharacters in order.
EXAMPLE: "abc" --> "011000010110001001100011"
since the ASCII values for 'a', 'b' and 'c'
are 97=01100001, 98=01100010 and 99=01100011
respectively
*/
for (i = 0, j = thisString.length; i < j; i++)
{
bits = thisString.charCodeAt(i).toString(2);
retString += new Array(8-bits.length+1).join('0') + bits;
}
/* Compress retString by taking each substring of 3, 4, ..., 9
consecutive 1's or 0's and it by the number of such consecutive
thisCharacters followed by the thisCharacter.
EXAMPLES:
"10101000010111" --> "10101401031"
"001100011111111111111" --> "0011319151"
*/
retString = retString.replace(/([01])\1{2,8}/g, function($0, $1) { return ($0.length + $1);});
return retString;
}
I tried to make a function and I'm probably doing it wrong because it's 50 lines already. I'm realizing that there's tons of error checking that needs to go on. For instance, I just realized a potential problem because JavaScript characters don't span the entire 127 ASCII values. Should I just give up? Is this a futile problem?
First, find the numbers in the string which are not 0 or 1. Then, expand them in the opposite way that the original function collapsed them. You can again use String.prototype.replace() here with a replacement function...
str.replace(/([2-9])([01])/g,
function(all, replacementCount, bit) {
return Array(+replacementCount + 1).join(bit);
});
Then, simply decode the bit stream back into characters with String.fromCharCode(). You'd need to chunk the stream into 8 bit chunks, and then perform the conversion. I chose to use Array.prototype.reduce() as it's quite suited to this task. Alternatively, you could use String.fromCharCode.apply(String, chunks.map(function(byte) { return parseInt(byte, 2); })) to get the resulting string.
Something like...
str.split(/(.{8})/g).reduce(function(str, byte) {
return str + String.fromCharCode(parseInt(byte, 2));
}, "");
Put it together, and you get a function like...
function decryptStr(thisString) {
return thisString.replace(/([2-9])([01])/g,
function (all, replacementCount, bit) {
return Array(+replacementCount + 1).join(bit);
}).split(/(.{8})/g).reduce(function (str, byte) {
return str + String.fromCharCode(parseInt(byte, 2));
}, "");
}
jsFiddle.
Also, remember to place var in front of your variable declarations, otherwise those variable identifiers will leak to the containing scope until they're resolved (which is usually the global object).

Javascript - Format number to always show the original decimal places

I need a js function that show the original count of decimals in a number. For example:
value display
2.31 2
1.0 1
2.3500 4
The problem is that i dont know how get the count of decimals.
I have that code:
value=2.3500;
return CountofDecimals(value); // must be display 4:
Anything help??? Thanks :P
That's not possible. There's no difference between the number 3.5 and 3.50 in JavaScript, or indeed in any other common programming language.
If you actually mean they're strings (value = '2.3500' rather than value = 2.3500) then you can use indexOf:
var decimalPlaces = value.length - value.indexOf('.') - 1;
Caveat: I hate this answer, I don't really advocate it
Don't store it as a number, store it as a string. This can result in "stringly typed" code quickly so it is inadvisable. It is a workaround since JavaScript uses a float as the number type.
Alternatively store it as an Object and parse out the format via a function call:
{ value = "1.2345", decimal = 4}
and use that to create the correct number format. If I had the requirement this is probably the hack I'd use. Or, I would have my server return the formatted string as you can pull that off easily server side.
If it would be possible take these numbers as strings, it definitely is possible..And quite simple actually.
function countDecimals(string){
var delimiters = [",","."];
for(var i = 0; i<delimiters.length; i++){
if(string.indexOf(delimiters[i])==-1) continue;
else{
return string.substring(string.indexOf(delimiters[i])+1).length;
}
}
}
You could use this function:
function decimalplaces(number)
{
numberastring = number.toString(10);
decimalpoint = numberastring.indexOf(".");
if(decimalpoint == -1)
{
return 0;
}
else
{
return numberastring.length - decimalpoint - 1;
}
}

javascript parseFloat '500,000' returns 500 when I need 500000

How would it be a nice way of handling this?
I already thought on removing the comma and then parsing to float.
Do you know a better/cleaner way?
Thanks
parseFloat( theString.replace(/,/g,'') );
I don't know why no one has suggested this expression-
parseFloat( theString.replace(/[^\d\.]/g,'') );
Removes any non-numeric characters except for periods. You don't need custom functions/loops for this either, that's just overkill.
Nope. Remove the comma.
You can use the string replace method, but not in a one liner as a regexp allows.
while(str.indexOf(',')!=-1)str= str.replace(',','');
parseFloat(str);
Or to make a single expression without a regexp=
return parseFloat(str.split(',').join(''));
I'd use the regexp.
I don't have enough reputation to add a comment, but for anyone wondering on the performance for regex vs split/join, here's a quick fiddle: https://jsfiddle.net/uh3mmgru/
var test = "1,123,214.19";
var t0 = performance.now();
for (var i = 0; i < 1000000; i++)
{
var a = parseFloat(test.replace(/,/g,''));
}
var t1 = performance.now();
document.write('Regex took: ' + (t1 - t0) + ' ms');
document.write('<br>')
var t0 = performance.now();
for (var i = 0; i < 1000000; i++)
{
var b = parseFloat(test.split(',').join(''));
}
var t1 = performance.now();
document.write('Split/join took: ' + (t1 - t0) + ' ms');
The results I get are (for 1 million loops each):
Regex: 263.335 ms
Split/join: 1035.875 ms
So I think its safe to say that regex is the way to go in this scenario
Building on the idea from #kennebec, if you want to make sure that the commas are correct, and you don't want to replace commas, you could try something like this:
function myParse(num) {
var n2 = num.split(",")
out = 0
for(var i = 0; i < n2.length; i++) {
out *= 1000;
out += parseFloat(n2[i])
}
return out
}
alert(myParse("1,432,85"));
// Returns 1432085, as the comma is misplaced.
It may not be as fast, but you wanted alternatives :)
What about a simple function to solve most of the common problems?
function getValue(obj) {
Value = parseFloat( $(obj).val().replace(/,/g,'') ).toFixed(2);
return +Value;
}
The above function gets values from fields (using jQuery) assuming the entered values are numeric (I rather validate fields while user is entering data, so I know for sure field content is numeric).
In case of floating point values, if well formatted in the field, the function will return a float point value correctly.
This function is far from complete, but it quickly fix the "," (comma) issue for values entered as 1,234.56 or 1,234,567. It will return valid number as far the content is numeric.
The + (plus) sign in front of the variable Value in the return command is a "dirty trick" used in JavaScript to assure the variable content returned will be numeric.
it is easy to modify the function to other purposes, such as (for instance), convert strings to numeric values taking care of the "," (comma) issue:
function parseValue(str) {
Value = parseFloat( str.replace(/,/g,'') ).toFixed(2);
return +Value;
}
Both operations can even be combined in one function. I.e.:
function parseNumber(item,isField=false) {
Value = (isField) ? parseFloat( $(item).val().replace(/,/g,'') ).toFixed(2) : parseFloat( item.replace(/,/g,'') ).toFixed(2)
return +Value;
}
In such case, if function is called result = parseNumber('12,092.98'); it will parse the value as it is a String. But if called as result = parseNumber('#MyField', true); it will try to obtain the value from '#MyField'.
As I said before, such functions are far from complete, and can be expanded in many ways. One idea is to check the first character of the given parameter (string) and decide based on the string format where to obtain the value to be parsed (if 1st character is = '#' then it is an ID from a DOM object, otherwise, if it begins with a number, it must be a string to be parsed).
Try it... Happy coding.

Categories

Resources