Converting excel formulae to JS? - javascript

I have this formula and it uses powers e.g. '10 to the power 30'
=B2*(B3/12) / (1-(1+(B3/12)) ^ -B6)
The problem is that I can't put ^ in JS/jQuery, I have to use Math.pow() as the equivalent.
I've tried quite a few different positions but I can't seem to get it correct, the brackets really confuse me. Which parts of the formula would I wrap the .pow within?
My attempt: =B2*(B3/12) / Math.pow( (1-(1+(B3/12)) , -B6) )
UPDATE:
Please see this Fiddle
Fiddle code:
var B2 = 500000; //£500,000
var B3 = 2.00; //2.00%
var B6 = 300; //Total number of payments
var original_formula = 'B2*(B3/12)/(1-(1+(B3/12))^-B6)';
var x = B2 * (B3 / 12) / Math.pow(1 - (1 + (B3 / 12)), -B6)
console.log(x);
//Expected/Excel result = 2,119.27
//Actual result = 2.9884337938456618e-229 <- what's going on here?

Have not tried this, but one problem is probably that you're wrapping the two arguments in Math.pow() with a set parentheses.
In your original formula, you wrap the base and exponent in parentheses to group them together:
(1 - (1 + (B3 / 12)) ^ -B6)
Math.pow() takes two arguments, the base, and the exponent:
Math.pow(base, exponent)
You can't use parentheses across two arguments in Javascript, and in fact you don't need to since the pow() function knows that the two arguments should be used together.
So instead of:
Math.pow((1 - (1 + (B3 / 12)), -B6))
I think that should be more like:
Math.pow(1 - (1 + (B3 / 12)), -B6)

=B2*(B3/12) / (1-(1+(B3/12)) ^ -B6)
is the same as
=B2*B3/12 / ( 1 - (1+B3/12) ^ -B6 )
With this reduced number of parantheses it is perhaps easier to see that the javascript implementation should be
= B2*B3/12 / ( 1 - Math.pow(1+B3/12, -B6) )
You also need to translate B3=2.00% into B3=2.00/100 or B3=0.02. Then the result is indeed 2119.2716932202998
var B2 = 500000; //£500,000
var B3 = 2.00; //2.00%
var B6 = 300; //Total number of payments
var original_formula = 'B2*(B3/12)/(1-(1+(B3/12))^-B6)';
B3 = B3/100 // 2.0% is 0.02 as number
var x = B2*B3/12 / (1 - Math.pow(1 + B3/12, -B6) )
var log = document.getElementById("log")
log.innerHTML += "x="+x;
<div id="log"></div>

Related

Is there any problem with converting this excel formula to javascript?

Here is the excel formula:
=E2-(J2*2*G2)-(K2*E2*2)/30+IF((L2+M2)>60,((L2+M2)-60)*H2+60*G2,(L2+M2)*G2)+(N2/$AE$1)*$AE$2+(Q2*$AE$5+P2*$AE$4+O2*$AE$3)
Here what I tried (Javascript):
var E2 = $("#sentence").val();
var J2 = $("#deduction").val();
var G2 = 55145;
var K2 = $("#absence").val();
var L2 = $("#overtime").val();
var M2 = 0;
var H2 = 50050;
var N2 = $("#transportation").val();
var sixty;
if ((L2 + M2) > 60) {
sixty = ((L2 + M2) - 60) * H2 + 60 * G2;
} else {
sixty = (L2 + M2) * G2;
};
var result = E2 - (J2 * 2 * G2) - (K2 * E2 * 2) / 30 + sixty;
I couldn't find the way to conver this part of formula:
+(N2/$AE$1)*$AE$2+(Q2*$AE$5+P2*$AE$4+O2*$AE$3)
Here I found the problem:
Even if one of the variables sets to null, then the formula does not work properly.
It looks like some pretty basic math.
let total = (N2 / AE1) * AE2 + (Q2 * AE5 + P2 * AE4 + O2 * AE3 )
This is basically impossible to translate without seeing the actual spreadsheet but that should get you started. Also, make sure to take into consideration order of operations because the computer is going to evaluate it from left to right unless there are parenthesis (where it will evaluate those first).

Modular arithmetic does not work in Threshold signature (TSS) implementation

I was implementing threshold signatures protocol described in this paper and I run into a case where it fails and I don't understand reasons why. In the end, u and x should be the same, but they are not. I would appreciate any advice that will help me to find the bug.
This is JS code, it can be executed in browser console
/// TSS 2-of-2 case
// Field modulus, secp2561k
n = 115792089237316195423570985008687907852837564279074904382605163141518161494337n
// party 1 Polynomial coeff of degree 1
coeff_1 = 103808273981011494448342588544071102049904991793672697167547228275701563388858n
// coeff_1 = 10380827398101149444834258854407110204990499179367269716754722827570156338885n // Working coeff
// party 1 Polynomial coeff of degree 1
coeff_2 = 49961718147812071312795198333632033669565055597187655909241672498689891015278n
// coeff_2 = 4996171814781207131279519833363203366956505559718765590924167249868989101527n // Working coeff
// Party 1 secret
u_1 = 6989964936015280241594720270850184250394589151026058230978623558313385587815n
// Party 2 secret
u_2 = 91492373973552717359377053249757253672786176158857596037729237022345023720795n
// Party 1 Shamir points
y1_x = 1n
y1_1 = (y1_x * coeff_1 + u_1) % n
// 110798238917026774689937308814921286300299580944698755398525851834014948976673n
y1_2 = (y1_x * coeff_2 + u_2) % n
// 25662002884048593248601266574701379489513667476970347564365746379516753241736n
// Party 2 Shamir points
y2_x = 2n
y2_1 = (y2_x * coeff_1 + u_1) % n
// 98814423660722073714708912350304480497367008459296548183467916968198350871194n
y2_2 = (y2_x * coeff_2 + u_2) % n
// 75623721031860664561396464908333413159078723074158003473607418878206644257014n
// Party 1 point (y1_x, y1)
y1 = (y1_1 + y1_2) % n
// Party 2 point (y1_x, y1)
y2 = (y2_1 + y2_2) % n
// Common secret
u = (u_1 + u_2) % n
// Same secret, that went though Shamir schema
x = (y1*2n - y2) % n
// Checking calculations, should be 0
u - x
```
Your code is almost correct, just missing the final modulus at the end. Change the last line to
(u - x) % n;
The (u -x) is exactly n.
115792089237316195423570985008687907852837564279074904382605163141518161494337

calculate multiple input value in javascript

I have 5 input fields (range sliders) and I'm trying to return a result when any of the input values changes.
The problem is "value4" is used 2 times in the equation and this is causing the problem. If I change "value4" my result does not change.
function output(){
var value1 = document.getElementById('NumberOfEmployees_input').value;
var value2 = document.getElementById('AverageSalary_input').value;
var value3 = document.getElementById('AverageTime_input').value;
var value4 = document.getElementById('WorkdaysWeek_input').value;
var value5 = document.getElementById('AccountingHours_input').value;
document.getElementById('saving').innerHTML =
(((parseInt(value1) * parseInt(value2))/(parseInt(value4) * parseInt(1920))) * (parseInt(value3) * parseInt(value4) * parseInt(48)))
+ (parseInt(value5) * parseInt(13500)) - parseInt(183600);
}
Can anybody give me a hint?
Thank you!
Your equation can be simplified, you added too many brackets (I removed the parseInt() function to make it more readable).
It is equivalent to:
value4 is canceled:
You may have made an error in your equation.
The code is very difficult to read. I suggest simplifying the code by first, shortening the variable names. Then apply parseInt at an early stage to reduce clutter afterwards.
Plus, there is no need to parseInt(123) since 123 is already Integer.
function output(){
var v1 = parseInt(document.getElementById('NumberOfEmployees_input').value);
var v2 = parseInt(document.getElementById('AverageSalary_input').value);
var v3 = parseInt(document.getElementById('AverageTime_input').value);
var v4 = parseInt(document.getElementById('WorkdaysWeek_input').value);
var v5 = parseInt(document.getElementById('AccountingHours_input').value);
var n = v1 * v2; // nominator
var d = v4 * 1920 * v3 * v4 * 48; // denominator
document.getElementById('saving').innerHTML = (n/d) + (v5 * 13500) - 183600;
}
Here is your equation
(
(
(parseInt(value1) * parseInt(value2))
/
(parseInt(value4) * parseInt(1920))
) *
(parseInt(value3) * parseInt(value4) * parseInt(48))
)
+ (parseInt(value5) * parseInt(13500))
- parseInt(183600);
v1 • v2
(----------- • v3 • v4 • 48) + (v5 • 13500) - 183600
v4 • 1920
// valueN has been substituted with vN
By observation, v4 cancels out.
This reduces your chain of math to
( (parseInt(value1)*parseInt(value2)*parseInt(value3)*48) / 1920 )
+ (parseInt(value5) * 13500)
- 183600;
Note that originally, v4 = 0 would fail. This may or may not be intended.
To make your code more readable you can separate the numerator and denominator as so
n = parseInt(value1) * parseInt(value2) * parseInt(value3) * 48
document.getElementById('saving').innerHTML = (n/1920) + (v5 * 13500) - 183600;
While this might not answer your question of using 2 input values, this provides a workaround in your situation. You didn't seem to realise this when you posted your question. Perhaps you misplaced a bracket or made an error in your calculations?

Does this code work when comparing a floating point number to a string?

I was reading code in a library from Adobe (snap.svg.js) and I saw this code, which confused me:
function curveDim(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x),
b = 2 * (c1x - p1x) - 2 * (c2x - c1x),
c = p1x - c1x,
t1 = (-b + Math.sqrt(b * b - 4 * a * c)) / 2 / a,
t2 = (-b - Math.sqrt(b * b - 4 * a * c)) / 2 / a;
Math.abs(t1) > "1e12" && (t1 = .5);
Math.abs(t2) > "1e12" && (t2 = .5);
Since the formula is pretty complicated, I couldn't come up with values to test it, so I wanted to ask the general question: why can you compare Math.abs(t1) to a string '1e12'? Wouldn't that convert the floating point number to a string and then just do lexical comparison? What if the variable a is zero? Is this good code? Any explanation of what the author is trying to do and if it is correct would be great.
No, the > operator converts both operands to numbers (http://es5.github.io/#x11.8.2, http://es5.github.io/#x11.8.5).
See what happens when I convert the string to a number:
> +"1e12"
1000000000000
1e12 is actually a valid number literal and means 1 * 1012. No idea why they used strings instead, Math.abs(t1) > 1e12 would work just as fine.
You can easily test this yourself
var t1 = 10000000000000;
if (Math.abs(t1) > "1e12")
console.log('t1 is greater');
else
console.log('t1 is less or equal');
See JSFiddle

Javascript Brainteaser - Reverse Number Determining

Lets say I have a list of numbers in the following form(Ignore the | they are there for formating help).
00|00|xx
00|xx|00
xx|00|00
etc.
Rules: XX can be any number between 1 and 50. No XX values can be identical.
Now I select a random set of numbers(no duplicates) from a list qualifying the above format, and randomly add and subtract them. For example
000011 - 002400 - 230000 = -232389
How can I determine the original numbers and if they were added or subtracted solely from -232389? I'm stumped.
Thanks!
EDIT:
I was looking for a function so I ended up having to make one. Its just a proof of concept function so variables names are ugly http://jsfiddle.net/jPW8A/.
There are bugs in the following implementation, and it fails to work in a dozen of scenarios. Check the selected answer below.
function reverse_add_subtract(num){
var nums = [];
while(num != 0){
var str = num.toString(),
L = Math.abs(num).toString().length,
MA = str.match(/^(-?[0-9]?[0-9])([0-9][0-9])([0-9][0-9])*$/);
if(MA){
var num1 = MA[1],
num2 = MA[2];
}else{
var num1 = num,
num2 = 0;
}
if(L%2)L++;
if( num2 > 50){
if(num < 0) num1--;
else num1++;
}
nums.push(num1);
var add = parseInt(num1 + Array(--L).join(0),10);
num = (num-add);
}
return nums;
}
reverse_add_subtract(-122436);
First note that each xx group is constrained from [1, 50). This implies that each associated pair in the number that is in the range [50, 99) is really 100 - xx and this means that it "borrowed from" the group to the left. (It also means that there is only one set of normalized numbers and one solution, if any.)
So given the input 23|23|89 (the initial xx spots from -232389), normalize it -- that is, starting from the right, if the value is >= 50, get 100 - value and carry the 100 rightward (must balance). Example: (23 * 100) + 89 = 2300 * 89 = 2400 - 11 = 2389. And example that shows that it doesn't matter if it's negative as the only things that change is the signs: (-23 * 100) - 89 = -2300 - 89 = -2400 + 11 = -2389
(Notes: Remember, 1 is added to the 23 group to make it 24: the sign of the groups is not actually considered in this step, the math is just to show an example that it's okay to do! It may be possible to use this step to determine the sign and avoid extra math below, but this solution just tries to find the candidate numbers at this step. If there are any repeats of the number groups after this step then there is no solution; otherwise a solution exists.)
The candidate numbers after the normalization are then 23|24|11 (let's say this is aa|bb|cc, for below). All the xx values are now known and it is just a matter of finding the combination such that e * (aa * 10000) + f * (bb * 100) + g * (cc * 1) = -232389. The values aa, bb, cc are known from above and e, f, and g will be either 1 or -1, respectively.
Solution Warning: A method of finding the addition or subtraction given the determined numbers (determined above) is provided below the horizontal separator. Take a break and reflect on the above sections before deciding if the extra "hints" are required.
This can then be solved by utilizing the fact that all the xx groups are not dependent after the normalization. (At each step, try to make the input number for the next step approach zero.)
Example:
-232389 + (23 * 10000) = -2389 (e is -1 because that undoes the + we just did)
-2389 + (24 * 100) = 11 (likewise, f is -1)
11 - (11 * 1) = 0 (0 = win! g is 1 and solution is (-1 * 23 * 10000) + (-1 * 24 * 100) + (1 * 11 * 1) = -232389)
Happy homeworking.
First, your math is wrong. Your leading zeros are converting the first two numbers to octal. If that is the intent, the rest of this post doesn't exactly apply but may be able to be adapted.
11-2400-230000 = -232389
Now the last number is easy, it's always the first two digits, 23 in this case. Remove that:
-232389 + 230000 = -2389
Your 2nd number is the next 100 below this, -2400 in this case. And your final number is simply:
-2389 + 2400 = 11
Aww! Someone posted an answer saying "brute force it" that I was about to respond to with:
function find(num){for(var i=1;i<50;i++){for(var o1=0;o1<2;o1++){for(var j=1;j<50;j++){for(var o2=0;o2<2;o2++){for(var k=1;k<50;k++){var eq;if(eval(eq=(i+(o1?'+':'-')+j+'00'+(o2?'+':'-')+k+'0000'))==num){ return eq; }}}}}}}
they deleted it... :(
It was going to go in the comment, but here's a cleaner format:
function find(num){
for(var i=1;i<50;i++){
for(var o1=0;o1<2;o1++){
for(var j=1;j<50;j++){
for(var o2=0;o2<2;o2++){
for(var k=1;k<50;k++){
var eq;
if(eval(eq=(i+(o1?'+':'-')+j+'00'+(o2?'+':'-')+k+'0000'))==num){ return eq; }
}
}
}
}
}
}

Categories

Resources