Reputation: 3490
I have been using this function for calculating factorial numbers in JavaScript:
var f = [];
function factorial (n) {
if (n == 0 || n == 1)
return 1;
if (f[n] > 0)
return f[n];
return f[n] = factorial(n-1) * n;
}
All seemed to be going well until I tried the number 500
. It returned infinity
.
Is there a way that I can prevent infinity
as an answer?
Thank you.
Upvotes: 6
Views: 10201
Reputation: 51
Hi this is due to the nature of java script as it can't represents number above 253-1 reference so to solve this either wrap the number with BigInt(n) or add to the number >> 3n
const factorial = (n) => {
n = BigInt(n)
if ( n < 1 ) return 1n
return factorial(n - 1n) * n
}
Upvotes: 0
Reputation: 1
Javascript numbers can only get so big before they just become "Infinity". If you want to support bigger numbers, you'll have to use BigInt.
Examples:
// Without BigInt
console.log(100 ** 1000) // Infinity
// With BigInt
// (stackOverflow doesn't seem to print the result,
// unless I turn it into a string first)
console.log(String(100n ** 1000n)) // A really big number
So, for your specific bit of code, all you need to do is turn your numeric literals into BigInt literals, like this:
var f = [];
function factorial (n) {
if (n == 0n || n == 1n)
return 1n;
if (f[n] > 0n)
return f[n];
return f[n] = factorial(n-1n) * n;
}
console.log(String(factorial(500n)));
You'll find that you computer can run that piece of code in a snap.
Upvotes: 0
Reputation: 6819
You indeed need to use bignumbers. With math.js you can do:
// configure math.js to work with enough precision to do our calculation
math.config({precision: 2000});
// evaluate the factorial using a bignumber value
var value = math.bignumber(500);
var result = math.factorial(value);
// output the results
console.log(math.format(result, {notation: 'fixed'}));
This will output:
1220136825991110068701238785423046926253574342803192842192413588385845373153881997605496447502203281863013616477148203584163378722078177200480785205159329285477907571939330603772960859086270429174547882424912726344305670173270769461062802310452644218878789465754777149863494367781037644274033827365397471386477878495438489595537537990423241061271326984327745715546309977202781014561081188373709531016356324432987029563896628911658974769572087926928871281780070265174507768410719624390394322536422605234945850129918571501248706961568141625359056693423813008856249246891564126775654481886506593847951775360894005745238940335798476363944905313062323749066445048824665075946735862074637925184200459369692981022263971952597190945217823331756934581508552332820762820023402626907898342451712006207714640979456116127629145951237229913340169552363850942885592018727433795173014586357570828355780158735432768888680120399882384702151467605445407663535984174430480128938313896881639487469658817504506926365338175055478128640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Upvotes: 7
Reputation: 107
I dont know if anyone has solved this elsewise... I'm a novice beginner in coding and dont know all the aspects. But after I faced this factorial problem myself, i came here when searching for the answer. I solved the 'infinity' display problem in another way. I dont know if its very efficient or not. But it does show the results of even verry high intergers.
Sorry for any redundancy or untidiness in the code.
<!DOCTYPE html>
<html>
<head>
<title>Factorial</title>
<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js'></script>
</head>
<body>
<input type='text' id='number' />
<input type='button' value='!Factorial!' id='btn' />
<script>
var reslt=1;
var counter=0;
var mantissa=0; //stores the seperated matissa
var exponent=0; //stores the seperated exponent
$(document).ready(function (){
$('#btn').click(function (){
var num=parseFloat($('#number').val()); //number input by user
for(i=1;i<=num;i++){
reslt=reslt*i;
//when the result becomes so high that the exponent reaches 306, the number is divided by 1e300
if((parseFloat(reslt.toExponential().toString().split("e")[1]))>=300){
reslt=reslt/1e300; //the result becomes small again to be able to be iterated without becoming infinity
counter+=1; //the number of times that the number is divided in such manner is recorded by counter
}
}
//the mantissa of the final result is seperated first
mantissa=parseFloat(reslt.toExponential().toString().split("e")[0]);
//the exponent of the final result is obtained by adding the remaining exponent with the previously dropped exponents (1e300)
exponent=parseFloat(reslt.toExponential().toString().split("e")[1])+300*counter;
alert(mantissa+"e+"+exponent); //displays the result as a string by concatenating
//resets the variables and fields for the next input if any
$('#number').val('');
reslt=1;
mantissa=0;
exponent=0;
counter=0;
});
});
</script>
</body>
</html>
Upvotes: 1
Reputation: 324750
500! is, for lack of a better term, "[bleep]ing huge".
It is far, far beyond what can be stored in a double-precision float, which is what JavaScript uses for numbers.
There's no way to prevent this, other than use numbers that are reasonable :p
EDIT: To show you just how huge it is, here's the answer:
500! = 1220136825991110068701238785423046926253574342803192842192413588385845373153881997605496447502203281863013616477148203584163378722078177200480785205159329285477907571939330603772960859086270429174547882424912726344305670173270769461062802310452644218878789465754777149863494367781037644274033827365397471386477878495438489595537537990423241061271326984327745715546309977202781014561081188373709531016356324432987029563896628911658974769572087926928871281780070265174507768410719624390394322536422605234945850129918571501248706961568141625359056693423813008856249246891564126775654481886506593847951775360894005745238940335798476363944905313062323749066445048824665075946735862074637925184200459369692981022263971952597190945217823331756934581508552332820762820023402626907898342451712006207714640979456116127629145951237229913340169552363850942885592018727433795173014586357570828355780158735432768888680120399882384702151467605445407663535984174430480128938313896881639487469658817504506926365338175055478128640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
That right there is a 1,135-digit number. For comparison, double-precision floats can handle about 15 digits of precision.
Upvotes: 2
Reputation: 42397
You could consider using an arbitrary precision numeric library. This is a question of its own, though. Here's one related question: https://stackoverflow.com/questions/744099/is-there-a-good-javascript-bigdecimal-library.
Upvotes: 1