Accessing local JSON data in function on Global Scope - javascript

I am trying to access JSON data retrieved from JSON-Server within a function outside the function scope for the past 3 hours with no luck, below is my Code:
http.get(`http://localhost:3000/${depairport}`)
.then(data => airportNav(data))
.catch(err => console.log(err));
var number1 = 1.0;
var number2 = 2.0;
var airportNav = function calculateDepNav(depNav){
number1 = depNav.lat;
number2 = depNav.lon;
return number1, number2;
}
console.log(number1, number2);
How should I access depNav outside of this scope?

Got it, was able to do it with the below, used a for loop for html requests then used an if statement to calculate the distance when the html responses were done.
for(let i=0; i<urls.length; i++){
http.get(urls[i])
.then(data => {
responses.push(data);
if(responses.length == 2){
distance(responses[0].lat, responses[0].lon, responses[1].lat, responses[1].lon);
function distance(lat1, lon1, lat2, lon2) {
var p = 0.017453292519943295; // Math.PI / 180
var c = Math.cos;
var a = 0.5 - c((lat2 - lat1) * p)/2 +
c(lat1 * p) * c(lat2 * p) *
(1 - c((lon2 - lon1) * p))/2;
console.log(12742 * Math.asin(Math.sqrt(a)));
return 12742 * Math.asin(Math.sqrt(a)); // 2 * R; R = 6371 km
}
}
})
.catch(err => console.log(err));
}

Related

How to use big.js?

From the examples of big.js they show this example
0.3 - 0.1 // 0.19999999999999998
x = new Big(0.3)
x.minus(0.1) // "0.2"
x // "0.3"
x.div(y).plus(z).times(9).minus('1.234567801234567e+8').plus(976.54321).div('2598.11772')
Which is a very simple example. In my case I would like to calculate
res = a + (b / c) + (d + 1) / (e * f * g);
I cannot see how that can be calculated without introducing 7 temporary variables, which doesn't seam correct.
Question
Does anyone know how to calculate the above with big.js?
You can do this "inside-out", i.e. first convert the parts in the inner parentheses.
For example:
const temp1 = b.div(c),
temp2 = d.plus(1),
temp3 = e.times(f).times(g),
temp4 = temp2.div(temp3),
result = a.plus(temp1).plus(temp4);
But you don't actually need those temporary variables. Just take that last expression and inject the definition of the temporary variables, so your expression expands to this:
const res = a.plus(b.div(c)).plus(d.plus(1).div(e.times(f).times(g)));
// a + (b / c ) + (d + 1) / (e * f * g )
Demo:
const params = [1, 100, 5, 99, 2, 5, 2];
{ // First with native types:
const [a,b,c,d,e,f,g] = params;
const res = a + (b / c) + (d + 1) / (e * f * g);
console.log(res);
}
{ // Then with big.js
const [a,b,c,d,e,f,g] = params.map(Big);
const res = a.plus(b.div(c)).plus(d.plus(1).div(e.times(f).times(g)));
console.log(res.toNumber());
}
<script src='https://cdn.jsdelivr.net/npm/big.js#6.2.1/big.min.js'></script>

Google Sheets NORMDIST( x, mean, standard deviation, cumulative T/F) to JavaScript

Google Sheets has the NORMDIST( x, mean, standard deviation, cumulative T/F) function. I have not been able to find something equivalent in JavaScript. The examples I've found do not allow for all the variables that are in the Google function or I don't have the understanding to implement them.
I am trying to write a reiterative JavaScript function to replace a set of reiterative Google Sheets calculations and need something like this;
x = NORMDIST(x,0,1, TRUE);
y = NORMDIST(x,0,1, FALSE);
At a high-level, there's two things that the NORMDIST function can do: calculate the Normal Distribution's PDF when false is supplied as the last parameter and CDF when true is supplied.
The PDF part is easy: just follow the formula given on Wikipedia for Normal Distribution.
The CDF part is less trivial as it's a non-elementary integral. Your best shot is to find some open-source implementation and translate it into JS. (Preferably a non-iterative one.) It won't be 100% exact due to roundoff errors, but it can get you extremely close. I found one here.
Here's what I came up with:
function _getNDistPDF(x, mean, stdev)
{
const sqrt2PI = Math.SQRT2 * Math.sqrt(Math.PI);
let frac = (x - mean) / stdev;
return Math.exp(-.5 * frac * frac) / (sqrt2PI * stdev);
}
// Adapted from https://people.sc.fsu.edu/~jburkardt/c_src/asa066/alnorm.c
function _getNDistCDF(x, mean, stdev)
{
const a1 = 5.75885480458;
const a2 = 2.62433121679;
const a3 = 5.92885724438;
const b1 = -29.8213557807;
const b2 = 48.6959930692;
const c1 = -0.000000038052;
const c2 = 0.000398064794;
const c3 = -0.151679116635;
const c4 = 4.8385912808;
const c5 = 0.742380924027;
const c6 = 3.99019417011;
const con = 1.28;
const d1 = 1.00000615302;
const d2 = 1.98615381364;
const d3 = 5.29330324926;
const d4 = -15.1508972451;
const d5 = 30.789933034;
const ltone = 7.0;
const p = 0.398942280444;
const q = 0.39990348504;
const r = 0.398942280385;
const utzero = 18.66;
let up = false;
let value;
let y;
// For non-standard NDist
let z = (x - mean) / stdev;
if (z < 0)
{
up = true;
z = -z;
}
if (ltone < z && (!up || utzero < z))
{
value = !up * 1;
return value;
}
y = 0.5 * z * z;
if (z <= con)
{
value = 0.5 - z * (p - q * y
/ (y + a1 + b1
/ (y + a2 + b2
/ (y + a3))));
}
else
{
value = r * Math.exp(-y)
/ (z + c1 + d1
/ (z + c2 + d2
/ (z + c3 + d3
/ (z + c4 + d4
/ (z + c5 + d5
/ (z + c6))))));
}
if (!up)
value = 1 - value;
return value;
}
function NDistJS(x, mean, stdev, cumulative)
{
return cumulative
? _getNDistCDF(x, mean, stdev)
: _getNDistPDF(x, mean, stdev);
}
This gives you a function NDistJS that takes the exact same parameters as NORMDIST.
The PDF is 100% accurate to the Sheets formula.
The CDF is 99.9999992% accurate to the Sheets formula for (x=1, m=0, s=1).

How to get a random value from truncated normal distribution with mean and std in JavaScript?

What is a JS alternative to the same Python implementation?
import matplotlib.pyplot as plt
from scipy.stats import truncnorm
import numpy as np
mean = 1
std = 2
clip_a = -4
clip_b = 3
a, b = (clip_a - mean) / std, (clip_b - mean) / std
x_range = np.linspace(-3 * std, 3 * std, 1000)
plt.plot(x_range, truncnorm.pdf(x_range, a, b, loc = mean, scale = std));
I'd like to get a random value according to the distribution (in JS the same code with size=1):
dist = truncnorm.rvs(a, b, loc = mean, scale = std, size=1000000)
plt.hist(dist);
Here is a JS function that implements a truncated, skew-normal pseudo random number generator (PRNG). It is based on this blog post by Tom Liao and has been extended to consider lower and upper bounds (truncation).
Essentially, the function is called recursively until a variate within the desired bounds is found.
You can pass your own random number generator using the rng property, though Math.random will be used by default. Also, as you didn't ask for a skew-normal distribution, you can just ignore the skew property as it defaults to 0. This will leave you with a truncated normal PRNG, just as you asked for.
function randomTruncSkewNormal({
rng = Math.random,
range = [-Infinity, Infinity],
mean,
stdDev,
skew = 0
}) {
// Box-Muller transform
function randomNormals(rng) {
let u1 = 0,
u2 = 0;
//Convert [0,1) to (0,1)
while (u1 === 0) u1 = rng();
while (u2 === 0) u2 = rng();
const R = Math.sqrt(-2.0 * Math.log(u1));
const Θ = 2.0 * Math.PI * u2;
return [R * Math.cos(Θ), R * Math.sin(Θ)];
}
// Skew-normal transform
// If a variate is either below or above the desired range,
// we recursively call the randomSkewNormal function until
// a value within the desired range is drawn
function randomSkewNormal(rng, mean, stdDev, skew = 0) {
const [u0, v] = randomNormals(rng);
if (skew === 0) {
const value = mean + stdDev * u0;
if (value < range[0] || value > range[1])
return randomSkewNormal(rng, mean, stdDev, skew);
return value;
}
const sig = skew / Math.sqrt(1 + skew * skew);
const u1 = sig * u0 + Math.sqrt(1 - sig * sig) * v;
const z = u0 >= 0 ? u1 : -u1;
const value = mean + stdDev * z;
if (value < range[0] || value > range[1])
return randomSkewNormal(rng, mean, stdDev, skew);
return value;
}
return randomSkewNormal(rng, mean, stdDev, skew);
}
Calling this function in the following manner
const data = [];
for (let i = 0; i < 50000; i++) {
data.push({
x: i,
y: randomTruncSkewNormal({
range: [-4,3],
mean: 1,
stdDev: 2
})
});
}
and plotting the data using your charting library of choice should give your the desired output.
I also made a small Observable notebook interactively demonstrating the function which you might want to check out as well.

How to use Javascript class for xirr formula

Hello I have found a javascript class for some excel functions but i dont know how to use it. I need to use XIRR function but i dont know the type and format of parameters and the syntax.
Here is the code:
/* Based on
* - EGM Mathematical Finance class by Enrique Garcia M. <egarcia#egm.co>
* - A Guide to the PMT, FV, IPMT and PPMT Functions by Kevin (aka MWVisa1)
*/
var ExcelFormulas = {
PVIF: function(rate, nper) {
return Math.pow(1 + rate, nper);
},
FVIFA: function(rate, nper) {
return rate == 0? nper: (this.PVIF(rate, nper) - 1) / rate;
},
PMT: function(rate, nper, pv, fv, type) {
if (!fv) fv = 0;
if (!type) type = 0;
if (rate == 0) return -(pv + fv)/nper;
var pvif = Math.pow(1 + rate, nper);
var pmt = rate / (pvif - 1) * -(pv * pvif + fv);
if (type == 1) {
pmt /= (1 + rate);
};
return pmt;
},
IPMT: function(pv, pmt, rate, per) {
var tmp = Math.pow(1 + rate, per);
return 0 - (pv * tmp * rate + pmt * (tmp - 1));
},
PPMT: function(rate, per, nper, pv, fv, type) {
if (per < 1 || (per >= nper + 1)) return null;
var pmt = this.PMT(rate, nper, pv, fv, type);
var ipmt = this.IPMT(pv, pmt, rate, per - 1);
return pmt - ipmt;
},
DaysBetween: function(date1, date2) {
var oneDay = 24*60*60*1000;
return Math.round(Math.abs((date1.getTime() - date2.getTime())/oneDay));
},
// Change Date and Flow to date and value fields you use
XNPV: function(rate, values) {
var xnpv = 0.0;
var firstDate = new Date(values[0].Date);
for (var key in values) {
var tmp = values[key];
var value = tmp.Flow;
var date = new Date(tmp.Date);
xnpv += value / Math.pow(1 + rate, this.DaysBetween(firstDate, date)/365);
};
return xnpv;
},
XIRR: function(values, guess) {
if (!guess) guess = 0.1;
var x1 = 0.0;
var x2 = guess;
var f1 = this.XNPV(x1, values);
var f2 = this.XNPV(x2, values);
for (var i = 0; i < 100; i++) {
if ((f1 * f2) < 0.0) break;
if (Math.abs(f1) < Math.abs(f2)) {
f1 = this.XNPV(x1 += 1.6 * (x1 - x2), values);
}
else {
f2 = this.XNPV(x2 += 1.6 * (x2 - x1), values);
}
};
if ((f1 * f2) > 0.0) return null;
var f = this.XNPV(x1, values);
if (f < 0.0) {
var rtb = x1;
var dx = x2 - x1;
}
else {
var rtb = x2;
var dx = x1 - x2;
};
for (var i = 0; i < 100; i++) {
dx *= 0.5;
var x_mid = rtb + dx;
var f_mid = this.XNPV(x_mid, values);
if (f_mid <= 0.0) rtb = x_mid;
if ((Math.abs(f_mid) < 1.0e-6) || (Math.abs(dx) < 1.0e-6)) return x_mid;
};
return null;
}
};
You want to use XIRR, so let's look at its signature:
XIRR: function(values, guess)
What does it do with values?
var f1 = this.XNPV(x1, values);
So values must be whatever XNPV is expecting. It has this chunk at its core:
for (var key in values) {
var tmp = values[key];
var value = tmp.Flow;
var date = new Date(tmp.Date);
xnpv += value / Math.pow(1 + rate, this.DaysBetween(firstDate, date)/365);
};
So it is expecting values to be a dictionary (associative array), where the value part of the key-value pair has members .Flow and .Date. I assume .Flow is the cashflow, and from the DaysBetween method I can see that .Date is a javascript Date. The key is ignored, so it can be a numeric if we want. So let's make one of those:
var myInstrument = { 0: {Flow: 5, Date: new Date(2015, 7, 6)},
1: {Flow: 105, Date: new Date(2016, 7, 6)} };
(That is a dictionary (or array) declaration).
The other input to XIRR is guess, which it will use to solve something, but it will default to using 0.1 (10% !) if given a falsy input value. So we can call it with our myInstrument thus:
var myInternalReturn = XIRR(myInstrument, false);
NB: The XIRR function is implementing the Actual/365 Fixed day count convention for Annual payment frequency, which may not be appropriate for the instrument you are valuing. Maybe it won't make much difference, but it will be incorrect for semi-annual or 30/360, with particular problems around month-end dates, simple interest instruments and so on

I am trying something with javascript closure

I got 2 functions:
var number1 = 9
var number2 = 17;
//Get Percent of a the number1
function getPercent(x, y) {
return x * 100 / y;
}
var percentOfNumber1 = getPercent(number1, number2);
//Get rid of remainder
function getRemain(t) {
var remainder = t % 2;
t = t - remainder;
return t;
}
alert(getRemain(percentOfNumber1));
That works..but I want to close the getRemain function in the first function.
so What I did and I dont' get result with:
function getPercent(x, y) {
return x * 100 / y;
function getRemain(t) {
var remainder = t % 2;
t = t - remainder;
return t;
}
var numberClear = getRemain(result);
}
var result = getPercent(number1, number2);
alert(numberClear);
Can anyone explain the wrong approach to this?
"this is the first time I try closures I read couple of good explanations but didin't get the calling functions part really good I guess.."
Thnx.
You need to declare numberClear outside if you want to access it outside:
var numberClear;
function getPercent(x, y) {
function getRemain(t) {
return t - t % 2;
}
var result = x * 100 / y;
numberClear = getRemain(result);
return result;
}
var result = getPercent(number1, number2);
alert(numberClear);
Why not this?
Return both the values at once
function getPercentage(a, b){
function getRemain(t)
{
var remainder = t % 2;
t = t - remainder;
return t;
}
return {
percentage: a / b * 100,
remain: getRemain(a / b * 100)
}
};
var result = getPercentage(9, 17);
alert(result.percentage);
alert(result.remain);
You simply didn't return the result properly:
function getPercent(x,y)
{
function getRemain(t)
{
var remainder = t % 2;
t = t - remainder;
return t;
}
return getRemain(x * 100 / y); // <-- return what getRemain() gives you!
}
var result = getPercent(number1, number2);
There is no way to access a variable declared inside a function from outside it.
You could try this:
var getPercent = (function() {
function getRemain(t)
{
var remainder = t % 2;
t = t - remainder;
return t;
}
return function (x,y)
{
var percent = x * 100 / y;
return {
percent: percent,
remainder: getRemain(percent)
};
}
})();
In this way the getRemain function is not accessible and the getPercent function will return both the percent and remainder values.
try this
var numberClear;
function getPercent(x, y) {
var percentange = x * 100 / y;
numberClear = getRemain(result); // set your numberClear Variable here
return percentange;
}
function getRemain(t) {
return t - t % 2;
}
var result = getPercent(number1, number2);
alert(numberClear);

Categories