factorial numbers in java script

  • Thread starter patrick_woflian
  • Start date
D

Dr John Stockton

JRS: In article <[email protected]>, dated Sat, 10 Dec
2005 12:55:36 local, seen in Thomas
'PointedEars' Lahn said:
Dr said:
[...] Thomas 'PointedEars' Lahn [...] posted :
There are two approaches: iterative and recursive; the former
will allow you to calculate factorials of greater integers, of
course still with increasing loss of precision.

Why do you say that? [...]

Because how many recursive calls are possible, thus which is the greatest
factorial that can be calculated through that approach, is limited by the
range for IEEE doubles and the stack size; the greatest factorial that can
be calculated through the iterative approach is only limited by the range
for IEEE doubles.

You meant "... might allow your readers ...".

function Fac(m) { return m<2 ? 1 : m*Fac(--m) }

My small system will currently calculate (as Infinity) Fac(357) but not
Fac(358).
 
D

Dr John Stockton

JRS: In article <[email protected]>, dated Sat, 10
Dec 2005 10:30:30 local, seen in Jasen Betts
**** SENDING othernet.fidonet.nz.games *****
...
???


8.263931688330718e5565708

was the approximation I got using this script.
...

That and the other answer are both quite different methods, and ISTM
that they agree as well as can be expected since two of them have a
million rounding errors and the third is nominally approximate.

Thanks to both.
 
J

John G Harris

RobG said:
No, I don't - factorials are only defined for positive integers and
zero, where 0! = 1.

That's the school-book definition. In a serious text-book x! is defined
as an integral, for any real x. The book then goes on to prove that
(x+1)! = (x+1)*x and that 0! = 1. From this you can use a for loop to
calculate 1!, 2!, 3!, ..., just as in a school text-book.

Yes (see above).



Exactly, and you didn't state what that was. My intention was to raise
the issue so that you thought about it, I didn't want to guess at a
solution that may not be appropriate (for you or your client).

I'm not the original poster so I don't know what's needed. My intention
was to point out that the answer depends on the context.

For instance, if the context is statistical tests of significance then
0.5! is likely to crop up. On the other hand, if the context is
combinations then both 0.5 and 0 are very likely to be errors.

But not very elegant. Your code should ensure negative numbers are
never passed to the factorial function by checking the data input, not
by barfing at some later stage that may be several steps away from
where the actual error occurred.

Obviously, silly values should be trapped as close to the input as
possible. Then you have to choose what the factorial function should do.
One choice is to ignore the problem as it's not going to happen. The
other is to check the parameter and return a special value if it's bad.
This has the disadvantage that you have to check the function with
several silly values, not just sensible ones.

John
 
T

Thomas 'PointedEars' Lahn

Dr said:
[...] Thomas 'PointedEars' Lahn [...] posted :
Dr said:
[...] Thomas 'PointedEars' Lahn [...] posted :
There are two approaches: iterative and recursive; the former
will allow you to calculate factorials of greater integers, of
course still with increasing loss of precision.
Why do you say that? [...]
Because how many recursive calls are possible, thus which is the greatest
factorial that can be calculated through that approach, is limited by the
range for IEEE doubles and the stack size; the greatest factorial that can
be calculated through the iterative approach is only limited by the range
for IEEE doubles.

You meant "... might allow your readers ...".
Pardon?

function Fac(m) { return m<2 ? 1 : m*Fac(--m) }

Negative arguments should not return 1, and I would not want to rely on
automatic semicolon insertion here.
My small system will currently calculate (as Infinity) Fac(357) but not
Fac(358).

That's nice for you.


PointedEars
 
R

RobG

John said:
That's the school-book definition. In a serious text-book x! is defined
as an integral, for any real x. The book then goes on to prove that
(x+1)! = (x+1)*x and that 0! = 1. From this you can use a for loop to
calculate 1!, 2!, 3!, ..., just as in a school text-book.

The 'school-book' definition is the formal definition of the factorial
for natural numbers (including zero) which I think can be assumed unless
something more complex is indicated.

The basic factorial function can be modified to estimate factorials for
fractions, but I don't think that alters the above. I'd bee keen to see
a JavaScript implementation of the factorial function for non-integers. ;-)

The modified function can be used to determine values for negative
fractions but their behaviour is bizarre and as far as I can tell have
no useful purpose - exactly what is complex negative infinity?

Every formal definition of a factorial I can find only relates to
numbers greater than or equal to zero, so I'll continue to believe that
n! is undefined where n<0.

The Wolfram Research page probably has more than any of us wishes to know:

<URL: http://mathworld.wolfram.com/Factorial.html >


[...]
I'm not the original poster so I don't know what's needed. My intention
was to point out that the answer depends on the context.

Ooops, sorry. I got my threads crossed. :-x

For instance, if the context is statistical tests of significance then
0.5! is likely to crop up. On the other hand, if the context is
combinations then both 0.5 and 0 are very likely to be errors.

In that case I'd try to avoid non-integers, which should be possible in
most cases.

Simplified functions can be defined for specific non-integer cases - a
function that calculates half-integer factorials is below (the error
message could be more useful :) ):

function halfFactorial(n)
{
if ( n < 0 || (n-0.5) % 1) {
return 'Only +ve half-integers will do, e.g. 0.5, 3.5, etc.';
}

var rtPI = Math.sqrt(Math.atan(1)*4);
var x=1;
while (n>0){
x *= n--;
}
return (rtPI*x).toFixed(2);
}


Which gives:

0.5! = 0.89
1.5! = 1.33
2.5! = 3.32
3.5! = 11.63
4.5! = 52.34


But it should only be used for halves, not whole numbers and I have no
idea what it would be useful for. A general solution for non-integer
factorials written in JavaScript might be useful. :)


[...]
Obviously, silly values should be trapped as close to the input as
possible. Then you have to choose what the factorial function should do.
One choice is to ignore the problem as it's not going to happen. The
other is to check the parameter and return a special value if it's bad.
This has the disadvantage that you have to check the function with
several silly values, not just sensible ones.

Yes, I presumed the OP's post was just an example. Hopefully we've
provided food for thought - I've had some fun! :p
 
J

John G Harris

RobG said:
The 'school-book' definition is the formal definition of the factorial
for natural numbers (including zero) which I think can be assumed
unless something more complex is indicated.

As I said, 0.5! crops up in statistics when you want to know if your
experimental results support your case (or contradict someone else's
case).

The basic factorial function can be modified to estimate factorials for
fractions, but I don't think that alters the above. I'd bee keen to
see a JavaScript implementation of the factorial function for non-
integers. ;-)

The modified function can be used to determine values for negative
fractions but their behaviour is bizarre and as far as I can tell have
no useful purpose - exactly what is complex negative infinity?

Every formal definition of a factorial I can find only relates to
numbers greater than or equal to zero, so I'll continue to believe that
n! is undefined where n<0.

The mathematics works, even if you don't have a use for it (yet).

The Wolfram Research page probably has more than any of us wishes to know:

<URL: http://mathworld.wolfram.com/Factorial.html >

Beware of the Wolfram web site. They concentrate on the definitions used
in their programming language. They don't always tell you about wider or
different definitions used elsewhere.

[...]
I'm not the original poster so I don't know what's needed. My intention
was to point out that the answer depends on the context.

Ooops, sorry. I got my threads crossed. :-x

For instance, if the context is statistical tests of significance
then
0.5! is likely to crop up. On the other hand, if the context is
combinations then both 0.5 and 0 are very likely to be errors.

In that case I'd try to avoid non-integers, which should be possible in
most cases.

Simplified functions can be defined for specific non-integer cases - a
function that calculates half-integer factorials is below (the error
message could be more useful :) ):

function halfFactorial(n)
{
if ( n < 0 || (n-0.5) % 1) {
return 'Only +ve half-integers will do, e.g. 0.5, 3.5, etc.';
}

var rtPI = Math.sqrt(Math.atan(1)*4);

rtPI = Math.sqrt(Math.PI) is better. It uses a constant so is faster and
could well be more accurate.

var x=1;
while (n>0){
x *= n--;
}
return (rtPI*x).toFixed(2);
}


Which gives:

0.5! = 0.89
1.5! = 1.33
2.5! = 3.32
3.5! = 11.63
4.5! = 52.34


But it should only be used for halves, not whole numbers and I have no
idea what it would be useful for. A general solution for non-integer
factorials written in JavaScript might be useful. :)

You need to find out how calculators do it, but the designers probably
don't want to tell you.

[...]
Obviously, silly values should be trapped as close to the input as
possible. Then you have to choose what the factorial function should do.
One choice is to ignore the problem as it's not going to happen. The
other is to check the parameter and return a special value if it's bad.
This has the disadvantage that you have to check the function with
several silly values, not just sensible ones.

Yes, I presumed the OP's post was just an example. Hopefully we've
provided food for thought - I've had some fun! :p

John
 
J

John G Harris

Dr John Stockton said:
JRS: In article <[email protected]>, dated Sat, 10
Dec 2005 09:02:54 local, seen in Evertjan.


(a) ISTM that 1 should NOT be the result for an out-of-range argument.

0 is available to indicate error as x! is non-zero for any real x.


function Factorial(n) {
if (isNaN(n)) return NaN
if (n<0) return NaN
if (n>170) return Infinity
if (n%1) return NaN
return Fac(n) }
<snip>

This is javascript. Don't forget to test for no parameter, >1
parameters, and for the parameter type not being Number.

John
 
D

Dr John Stockton

JRS: In article <[email protected]>, dated Mon, 12 Dec
2005 02:08:37 local, seen in Thomas
'PointedEars' Lahn said:
Dr said:
[...] Thomas 'PointedEars' Lahn [...] posted :
Dr John Stockton wrote:
[...] Thomas 'PointedEars' Lahn [...] posted :
There are two approaches: iterative and recursive; the former
will allow you to calculate factorials of greater integers, of
course still with increasing loss of precision.
Why do you say that? [...]
Because how many recursive calls are possible, thus which is the greatest
factorial that can be calculated through that approach, is limited by the
range for IEEE doubles and the stack size; the greatest factorial that can
be calculated through the iterative approach is only limited by the range
for IEEE doubles.

You meant "... might allow your readers ...".
Pardon?

function Fac(m) { return m<2 ? 1 : m*Fac(--m) }

Negative arguments should not return 1, and I would not want to rely on
automatic semicolon insertion here.

You should have read my post dated Date: Sun, 11 Dec 2005 18:13:37 +0000
*before* considering my post dated Date: Sun, 11 Dec 2005 18:22:39 +0000

You might then have realised that Fac is not my suggested Factorial
function, but merely the recursive portion; I gave it to show exactly
what I tested on my system for recursion depth.

PKUATBT/KETFOB.
 
T

Thomas 'PointedEars' Lahn

Dr said:
[...] Thomas 'PointedEars' Lahn [...] posted :
Dr said:
[...] Thomas 'PointedEars' Lahn [...] posted :
Dr John Stockton wrote:
[...] Thomas 'PointedEars' Lahn [...] posted :
There are two approaches: iterative and recursive; the former
will allow you to calculate factorials of greater integers, of
course still with increasing loss of precision.
Why do you say that? [...]
Because how many recursive calls are possible, thus which is the
greatest factorial that can be calculated through that approach, is
limited by the range for IEEE doubles and the stack size; the greatest
factorial that can be calculated through the iterative approach is only
limited by the range for IEEE doubles.
[1]
You meant "... might allow your readers ...". Pardon?

function Fac(m) { return m<2 ? 1 : m*Fac(--m) }

Negative arguments should not return 1, and I would not want to rely on
automatic semicolon insertion here.

You should have read my post dated Date: Sun, 11 Dec 2005 18:13:37 +0000
*before* considering my post dated Date: Sun, 11 Dec 2005 18:22:39 +0000

I have.
You might then have realised that Fac is not my suggested Factorial
function, but merely the recursive portion; I gave it to show exactly
what I tested on my system for recursion depth.

OK, but that still does not explain what you mean with [1].
PKUATBT/KETFOB.

Whatever.


PointedEars
 
R

RobG

John said:
The mathematics works, even if you don't have a use for it (yet).

Spoken like a mathematician... :p


[...]
rtPI = Math.sqrt(Math.PI) is better. It uses a constant so is faster and
could well be more accurate.

Yes [ACK to JRS too], hangover from some ported code from may old Sony
Pocket Computer - its BASIC didn't have PI.


[...]
You need to find out how calculators do it, but the designers probably
don't want to tell you.

Here's one based on a version of Stirling's formula (wrapped for
posting) that seems good if rounded to an integer when n<6 or to 3 or 4
significant figures after that:

// n! = [(2*n + 1/3)*pi)^1/2] * (n/e)^n
function fractionFactorial(n)
{
return (Math.sqrt((2*n + 1/3)*Math.PI) *
Math.pow((n/Math.E),n)).toFixed(4);
}


[...]
 
D

Dr John Stockton

JRS: In article <[email protected]>, dated Mon, 12
Dec 2005 20:52:06 local, seen in John G
Harris said:
0 is available to indicate error as x! is non-zero for any real x.


Using 0 is OK if one is going to test the returned value (or a multiple
of it) each time; but it will not necessarily result in an obvious
effect in a general calculation. NaN is better for non-valid values, or
possibly undefined - though I'd prefer to reserve that for variables
that have had nothing assigned to them.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,058
Latest member
QQXCharlot

Latest Threads

Top