I'm trying to write a JavaScript fractal generation algorithm from first principles. I'm aware that there are many examples out there but I wanted to incorporate additional functionality to support both Mandelbrot and 'spinning' Julia with variants such as 'Burning Ship' and 'Tricorn'. With this in mind I implemented a lightweight Complex maths library (again, I'm aware there are standard Complex js libraries out there but I wanted to build one from scratch as a learning exercise).
I tested two alternate functions, one fractal using standard maths functions and the other fractalComplex using my Complex library methods. They both work fine, but I was surprised to find that the standard version is almost twice as fast as the Complex version. I was expecting some additional overhead but not that much!
Can anyone explain why? The Complex library is using the same maths constructs 'under the covers'. Is the additional overhead purely down to object creation?
The code is reproduced below (the input parms z and c are objects of the form {re, im}).
function fractal(z, c, maxiter) {
var i, za, re, im, re2, im2;
c = (settype === JULIA ? c : z);
// Iterate until abs(z) exceeds escape radius
for (i = 0; i < maxiter; i += 1) {
if (setvar === BURNING_SHIP) {
re = Math.abs(z.re);
im = -Math.abs(z.im);
}
else if (setvar === TRICORN) {
re = z.re
im = -z.im; // conjugate z
}
else { // Mandelbrot
re = z.re;
im = z.im;
}
re2 = re * re;
im2 = im * im;
z = { // z = z² + c
re: re2 - im2 + c.re,
im: 2 * im * re + c.im
};
za = re2 + im2 // abs(z)²
if (za > 4) { // abs(z)² > radius²
break;
}
}
za = Math.sqrt(za); // abs(z)
return { i, za };
}
function fractalComplex(z, c, maxiter, n, radius) {
var i, za;
c = (settype === JULIA ? c : z);
// Iterate until abs(z) exceeds escape radius
for (i = 0; i < maxiter; i += 1) {
if (setvar === BURNING_SHIP) {
z = new Complex(Math.abs(z.re), -Math.abs(z.im))
}
if (setvar === TRICORN) {
z = z.conjugate()
}
z = z.quad(n, c); // z = zⁿ + c
za = z.abs();
if (za > radius) {
break;
}
}
return { i, za };
}
My "Complex lite" library is as follows:
// ------------------------------------------------------------------------
// A basic complex number library which implements the methods used for
// Mandelbrot and Julia Set generation.
// ------------------------------------------------------------------------
'use strict';
// Instantiate complex number object.
function Complex(re, im) {
this.re = re; // real
this.im = im; // imaginary
}
Complex.prototype = {
're': 0,
'im': 0,
// Set value.
'set': function (re, im) {
this.re = re;
this.im = im;
},
// Get magnitude.
'abs': function () {
return Math.sqrt(this.re * this.re + this.im * this.im);
},
// Get polar representation (r, θ); angle in radians.
'polar': function () {
return { r: this.abs(), θ: Math.atan2(this.im, this.re) };
},
// Get square.
'sqr': function () {
var re2 = this.re * this.re - this.im * this.im;
var im2 = 2 * this.im * this.re;
return new Complex(re2, im2);
},
// Get complex number to the real power n.
'pow': function (n) {
if (n === 0) { return new Complex(1, 0); }
if (n === 1) { return this; }
if (n === 2) { return this.sqr(); }
var pol = this.polar();
var rn = Math.pow(pol.r, n);
var θn = n * pol.θ;
return cart(rn, θn);
},
// Get conjugate.
'conjugate': function () {
return new Complex(this.re, -this.im);
},
// Get quadratic zⁿ + c.
'quad': function (n, c) {
var zn = this.pow(n);
return new Complex(zn.re + c.re, zn.im + c.im);
},
// Rotate by angle in radians.
'rotate': function (angle) {
var pol = this.polar();
angle += pol.θ;
return new Complex(pol.r * Math.cos(angle), pol.r * Math.sin(angle));
},
// String in exponent format to specified significant figures.
'toString': function (sig = 9) {
return this.re.toExponential(sig) + " + " + this.im.toExponential(sig) + "i";
},
}
// Convert polar (r, θ) to cartesian representation (re, im).
function cart(r, θ) {
var re = r * Math.cos(θ);
var im = r * Math.sin(θ);
return new Complex(re, im);
}
Additional edit 22/12/2021 11:52:
For what it's worth, this is what I eventually settled on...
function fractal(p, c, n, maxiter, radius) {
var i, za, zre, zim, tre, cre, cim, r, θ;
var lastre = 0;
var lastim = 0;
var per = 0;
if (setmode === JULIA) {
cre = c.re;
cim = c.im;
zre = p.re;
zim = p.im;
}
else { // Mandelbrot mode
cre = p.re;
cim = p.im;
zre = 0;
zim = 0;
}
// Iterate until abs(z) exceeds escape radius
for (i = 0; i < maxiter; i += 1) {
if (setvar === BURNING_SHIP) {
zre = Math.abs(zre);
zim = -Math.abs(zim);
}
else if (setvar === TRICORN) {
zim = -zim; // conjugate z
}
// z = z² + c
if (n == 2) {
tre = zre * zre - zim * zim + cre;
zim = 2 * zre * zim + cim;
zre = tre;
}
else { // z = zⁿ + c, where n is integer > 2
r = powi(Math.sqrt(zre * zre + zim * zim), n); // radiusⁿ
//r = Math.pow(Math.sqrt(zre * zre + zim * zim), n); // radiusⁿ
θ = n * Math.atan2(zim, zre); // angleⁿ
zre = r * Math.cos(θ) + cre;
zim = r * Math.sin(θ) + cim;
}
// Optimisation - periodicity check speeds
// up processing of points within set
if (PERIODCHECK) {
if (zre === lastre && zim === lastim) {
i = maxiter;
break;
}
per += 1;
if (per > 20) {
per = 0;
lastre = zre;
lastim = zim;
}
}
// ... end of optimisation
za = zre * zre + zim * zim // abs(z)²
if (za > radius) { // abs(z)² > radius²
break;
}
}
return { i, za };
}
// Optimised pow() function for integer exponents
// using 'halving and squaring'.
function powi(base, n) {
var res = 1;
while (n) {
if (n & 1) { // if n is odd
res *= base;
}
n >>= 1; // n * 2
base *= base;
}
return res;
}
The following class might satisfy both performance concerns and proper encapsulation of the Complex object...
Notables:
Where applicable, always return the this Complex object (ie, the instantiated object), which facilitates chaining. Eg,
x = new Complex( 10, 5 ).sqrThis().powThis( 1 );
For every Complex method that returns a Complex object, configure two (2) methods:
A method, dubbed <method>This that operates directly on the this object and contains the function logic.
A method, dubbed <method> that clones a new Complex object from the this object, and then calls <method>This to execute the function logic on the clone.
This provides the developer the choice of methods that either updates the existing object or returns a new object.
Internal calls to other Complex methods generally should use the <method>This version, as the initial call establishes whether to use the existing this object in-place, or to clone it. From there, all internal calls to the other Complex methods will either continue to operate on the this object or the clone.
// ------------------------------------------------------------------------
// A basic complex number library which implements the methods used for
// Mandelbrot and Julia Set generation.
// ------------------------------------------------------------------------
'use strict';
class Complex {
constructor( reOrComplex, im ) {
this.set( reOrComplex, im );
}
set( reOrComplex, im ) {
if ( reOrComplex instanceof Complex ) {
this.re = reOrComplex.re;
this.im = reOrComplex.im;
} else {
this.re = reOrComplex;
this.im = im;
}
return this;
}
abs() {
return Math.sqrt(this.re * this.re + this.im * this.im);
}
toPolar() {
return { r: this.abs(), θ: Math.atan2(this.im, this.re) };
}
sqrThis() {
return this.set( this.re * this.re - this.im * this.im, 2 * this.im * this.re );
}
sqr() {
return new Complex( this ).sqrThis();
}
powThis( n ) {
if ( n === 0 ) { return this.set( 1, 0 ) };
if ( n === 1 ) { return this; }
if ( n === 2 ) { return this.sqrThis(); }
let polar = this.toPolar();
return this.toCartesianThis( Math.pow(polar.r, n), n * polar.θ );
}
pow( n ) {
return new Complex( this ).powThis( n );
}
conjugateThis() {
return this.set( this.re, -this.im);
}
conjugate() {
return new Complex( this ).conjugateThis();
}
quadraticThis( n, c ) {
let zn = this.powThis( n );
return this.set( zn.re + c.re, zn.im + c.im );
}
quadratic( n, c ) {
return new Complex( this ).quadraticThis( n, c );
}
rotateThis( deltaAngle ) {
let polar = this.toPolar();
let angle = polar.θ + deltaAngle;
return this.set( polar.r * Math.cos(angle), polar.r * Math.sin(angle) );
}
rotate( deltaAngle ) {
return new Complex( this ).rotateThis( deltaAngle );
}
toString( sig = 9 ) {
return this.re.toExponential( sig ) + " + " + this.im.toExponential( sig ) + "i";
}
toCartesianThis( r, θ ) {
return this.set( r * Math.cos( θ ), r * Math.sin( θ ) );
}
}
// Convert polar (r, θ) to cartesian representation (re, im).
Complex.toCartesian = function ( r, θ ) {
return new Complex().toCartesianThis( r, θ );
}
let x = new Complex( 10, 5 ).sqrThis();
console.log( 'x = new Complex( 10, 5 ).sqrThis()' );
console.log( 'x is ', x );
let y = x.pow( 3 );
console.log ( 'y = x.pow( 3 )' );
console.log ( 'y is ', y );
x.sqr();
console.log ( 'x.sqr()' );
console.log ( 'x is still', x );
x.sqrThis();
console.log ( 'x.sqrThis()' );
console.log ( 'x is now', x );
In short, structuring a class this way provides two versions of the same method:
One method which embodies the function logic and directly mutates the instantiated this object.
And the other method which simply clones the instantiated this object, and then calls the associated method containing the function logic.
I am trying to solve below problem ,my one test case fail why ?
Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.
Note: You can only move either down or right at any point in time.
Input:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
Output: 7
Explanation: Because the path 1→3→1→1→1 minimizes the sum.
/**
* #param {number[][]} grid
* #return {number}
*/
var minPathSum = function(grid) {
let firstRow = 0,
firstColumn = 0,
endColumn = 0,
endRow = 0;
if(grid.length === 1){
return grid[0][0]
}
let firstArray = grid[0];
let endArray = grid[grid.length - 1];
firstArray.forEach((i) => firstRow += i);
endArray.forEach((i) => endRow += i);
for (let i = 1; i < grid.length - 1; i++) {
firstColumn += grid[i].shift();
endColumn += grid[i].pop()
}
let cornEdge = grid[grid.length - 1].pop();
let firstElemt = grid[0].shift();
if (firstRow + endColumn + cornEdge> firstElemt + firstColumn + endRow) {
return firstElemt+ firstColumn + endRow
} else {
return firstRow + endColumn +cornEdge
}
};
failed test case
Input
[[1,2,5],[3,2,1]]
Output
7
Expected
6
from my point of view above expectation is wrong ? it should be 7 using 1->3->2->1 but how it is six
This is a brute force solution to the problem. It will recursively iterate every possible path through the array, and return the minimum found.
Unfortunately, whilst it works with the two test cases presented in the question, it exceeds the runtime execution limits on Leetcode for the more complex cases; although it does still yield an answer. For example:
minPathSum([
[3,8,6,0,5,9,9,6,3,4,0,5,7,3,9,3],
[0,9,2,5,5,4,9,1,4,6,9,5,6,7,3,2],
[8,2,2,3,3,3,1,6,9,1,1,6,6,2,1,9],
[1,3,6,9,9,5,0,3,4,9,1,0,9,6,2,7],
[8,6,2,2,1,3,0,0,7,2,7,5,4,8,4,8],
[4,1,9,5,8,9,9,2,0,2,5,1,8,7,0,9],
[6,2,1,7,8,1,8,5,5,7,0,2,5,7,2,1],
[8,1,7,6,2,8,1,2,2,6,4,0,5,4,1,3],
[9,2,1,7,6,1,4,3,8,6,5,5,3,9,7,3],
[0,6,0,2,4,3,7,6,1,3,8,6,9,0,0,8],
[4,3,7,2,4,3,6,4,0,3,9,5,3,6,9,3],
[2,1,8,8,4,5,6,5,8,7,3,7,7,5,8,3],
[0,7,6,6,1,2,0,3,5,0,8,0,8,7,4,3],
[0,4,3,4,9,0,1,9,7,7,8,6,4,6,9,5],
[6,5,1,9,9,2,2,7,4,2,7,2,2,3,7,2],
[7,1,9,6,1,2,7,0,9,6,6,4,4,5,1,0],
[3,4,9,2,8,3,1,2,6,9,7,0,2,4,2,0],
[5,1,8,8,4,6,8,5,2,4,1,6,2,2,9,7]
]);
// 83 = 3+0+8+2+2+3+3+3+1+0+0+0+2+0+2+5+0+2+0+5+4+1+3+3+8+3+3+3+5+2+0+0+7
const minPathSum = function(grid) {
let maxX = grid[0].length - 1;
let maxY = grid.length - 1;
return mapPath(grid, 0, 0, maxX, maxY, 0);
};
const mapPath = function(grid, x, y, maxX, maxY, length) {
const value = grid[y][x];
if (x === maxX && y === maxY) {
return length + value;
}
const minX = (x < maxX)
? mapPath(grid, x + 1, y, maxX, maxY, length + value)
: Infinity;
const minY = (y < maxY)
? mapPath(grid, x, y + 1, maxX, maxY, length + value)
: Infinity;
return Math.min(minX, minY);
};
console.log(minPathSum([[1,3,1],[1,5,1],[4,2,1]]));
console.log(minPathSum([[1,2,5],[3,2,1]]));
You should do like:
function min(array){
return Math.min(...array);
}
function sum(array){
return array.reduce((a, c)=>a+=c);
}
function sumsMin(arrayOfArrays){
const sums = [];
arrayOfArrays.forEach(a=>{
sums.push(sum(a));
});
return min(sums);
}
console.log(sumsMin([[1,2,5],[3,2,1]]));
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
How can I make a function that calculates the factorial (or the gamma function) of decimal numbers in JavaScript? For example, how could I calculate 2.33!?
I might have found an existing solution...
It's an implementation of Lanczos method, I found it at the swedish wikipedia (http://sv.wikipedia.org/wiki/Gammafunktionen). It was written in python and says to be correct up to 15 decimals. I ported it to js, cross checked some random values against (http://www.efunda.com/math/gamma/findgamma.cfm).
http://jsfiddle.net/Fzy9C/
var g = 7;
var C = [0.99999999999980993, 676.5203681218851, -1259.1392167224028,771.32342877765313, -176.61502916214059, 12.507343278686905, -0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7];
function gamma(z) {
if (z < 0.5) return Math.PI / (Math.sin(Math.PI * z) * gamma(1 - z));
else {
z -= 1;
var x = C[0];
for (var i = 1; i < g + 2; i++)
x += C[i] / (z + i);
var t = z + g + 0.5;
return Math.sqrt(2 * Math.PI) * Math.pow(t, (z + 0.5)) * Math.exp(-t) * x;
}
}
(and ofcourse it does not support imaginary numbers, since js does not)
As an alternative to the other answers here, here's a much simpler approximation for the gamma function, proposed in 2007 by Gergő Nemes. (See the wikipedia page on Stirling's approximation).
This can be implemented directly in JavaScript in a single line:
function gamma(z) {
return Math.sqrt(2 * Math.PI / z) * Math.pow((1 / Math.E) * (z + 1 / (12 * z - 1 / (10 * z))), z);
}
You can see this in action on jsFiddle.
This is accurate to 8 digits for z > 8, but it is still accurate to a handful of digits for smaller z. It is not quite as accurate as Lanczos approximation, but it is simpler and also slightly faster.
Note that the gamma function and the factorial function are slightly different. The factorial function can be defined in terms of the gamma function thus:
function factorial(n) {
return gamma(n + 1);
}
This is not a trivial problem. There is not a simple closed-form formula for the gamma function. That said, there are some numerical approximations that should suit your needs.
The following answer will be using a technique called Lanczos approximation. The formula is as follows:
where g is an arbitrarily chosen constant that controls how accurate the approximation will be. For larger g, the approximation will be more accurate. Ag(z) is defined thus:
The hardest part is finding Ag(z), since pn is also defined with a complicated formula dependent on g.
I can't take too much credit for the following code, since I am just writing a port of the Python program on the wikipedia page.
function gamma(n) { // accurate to about 15 decimal places
//some magic constants
var g = 7, // g represents the precision desired, p is the values of p[i] to plug into Lanczos' formula
p = [0.99999999999980993, 676.5203681218851, -1259.1392167224028, 771.32342877765313, -176.61502916214059, 12.507343278686905, -0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7];
if(n < 0.5) {
return Math.PI / Math.sin(n * Math.PI) / gamma(1 - n);
}
else {
n--;
var x = p[0];
for(var i = 1; i < g + 2; i++) {
x += p[i] / (n + i);
}
var t = n + g + 0.5;
return Math.sqrt(2 * Math.PI) * Math.pow(t, (n + 0.5)) * Math.exp(-t) * x;
}
}
and of course, by definition of the gamma function:
function factorial(n) {
return gamma(n + 1);
}
You can see this in action on jsFiddle.
Just to complete #apelsinapa answer to correct the calculation for an integer (we didn't get an integer solution when inputing an integer number).
#apelsinapa's great solution:
var g = 7;
var C = [0.99999999999980993, 676.5203681218851, -1259.1392167224028,771.32342877765313, -176.61502916214059, 12.507343278686905, -0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7];
function gamma(z) {
if (z < 0.5) return Math.PI / (Math.sin(Math.PI * z) * gamma(1 - z));
else {
z -= 1;
var x = C[0];
for (var i = 1; i < g + 2; i++)
x += C[i] / (z + i);
var t = z + g + 0.5;
return Math.sqrt(2 * Math.PI) * Math.pow(t, (z + 0.5)) * Math.exp(-t) * x;
}
}
And to get a correct answer for integer:
function factorialOfNumber(number) {
if (number % 1 != 0 || number<0){
return gamma(number + 1);
}
else {
if(number == 0) {
return 1;
}
for(var i = number; --i; ) {
number *= i;
}
return number;
}
}
Here's a version I wrote a few years ago ... a bit messy but tested :)
var
M_GAMMA = [76.18009172947146, -86.50532032941677, 24.01409824083091, -1.231739572450155, 0.1208650973866179e-2, -0.5395239384953e-5],
M_GAMMAS = 6;
function gammaFn(x) // Modified to JavaScript from "Numerical Recipies in C" by P. Mainwaring
{
var i = 0, n = ++x, tmp = x + 5.5, ser = 1.000000000190015;
for (tmp -= (x + 0.5) * Math.log(tmp); i < M_GAMMAS; ++i) ser += M_GAMMA [i] / ++n;
return Math.log(2.5066282746310005 * ser / x) - tmp;
}
function fact(x) { return x > 1 ? Math.exp(gammaFn(x)) : 1 }
function combin(n, k) { return (Math.exp(gammaFn(n) - gammaFn(n - k) - gammaFn(k)) + 0.5) | 0 } // Ms Excel COMBIN() n! / k!(n - k)!
n = 49; k = 6; alert(fact(n) + ' ' + fact(k) + ' ' + combin(n, k)); // Lottery odds! (13,983,816)
The gamma and gammaLn functions are then:
function gammaLn(x) { return gammaFn(--x) }
function gamma(x) { return Math.exp(gammaLn(x)) }
:-)
If you're just looking for the function to compute factorials of real numbers then you only need this bit of code from Lanczos approximation:
function = factorial(z) {
var g = 7;
var C = [0.99999999999980993, 676.5203681218851, -1259.1392167224028, 771.32342877765313, -176.61502916214059, 12.507343278686905, -0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7];
var x = C[0];
for (var i = 1; i < g + 2; i++)
x += C[i] / (z + i);
var t = z + g + 0.5;
return Math.sqrt(2 * Math.PI) * Math.pow(t, (z + 0.5)) * Math.exp(-t) * x;
}
Works great for negative numbers in addition to decimals.