JavaScript factorial prevent infinity - javascript

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.

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

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.

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.

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>

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.

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
}

Related

Javascript - Error when calculating sine of complex numbers with a high magnitude

I am making a sine calculator that will be able to evaluate the sine of complex numbers by using polar coordinates and calculating part of the infinite series that defines the sine function. The calculator seems to work fine if the magnitude of the inputted complex number is small. However, when the magnitude of the inputted complex number becomes large (over 40) the calculator stops working, as the system seems to be outputting the real and imaginary portions of the final result as NaN. Please may you help me make my calculator work for all complex inputs? Any help would be greatly appreciated. Here is my HTML and JS code:
var arr=[];
var result=[0,0];
function calc(){
var input=document.querySelector("input").value;
try{if(input.split("+").length == 1){
arr[0]=Number(input.split("-")[0])
arr[1]=-1*Number(input.split("-")[1].split("i").join(""))
if(input.split("-")[1].split("i").join("") === ""){
arr[1] = -1;
}
}else{
arr[0]=Number(input.split("+")[0])
arr[1]=Number(input.split("+")[1].split("i").join(""))
if(input.split("+")[1].split("i").join("") === ""){
arr[1] = 1;
}
}
}catch(e){if(input.split("i").length == 1){arr[0] = Number(input);arr[1]=0}}
for(var i=0;i<100;i++){
result[0] += ((-1)**i)*calcPower(2*i+1)[0]/factorialize(2*i+1)
result[1] += ((-1)**i)*calcPower(2*i+1)[1]/factorialize(2*i+1)
}
document.querySelector("div").innerText=result[0]+sign(result[1])+Math.abs(result[1])+"i";
result[0]=0;
result[1]=0;
}
function calcPower(pow){
var r=(arr[0]**2+arr[1]**2)**0.5;
if(Math.sign(arr[0])+Math.sign(arr[1]) == -2){
r *= -1}
r **= pow;
var real=Math.cos(Math.atan(arr[1]/arr[0])*pow)*r;
var imag=Math.sin(Math.atan(arr[1]/arr[0])*pow)*r;
return [real,imag];
}
function factorialize(factorial){
var result=1;
for(var i=1;i<=factorial;i++){result *= i};return result}
function sign(num){if(Math.sign(num) == -1){return "-"}else{return "+"}}
<input></input>
<button onclick=calc()>Take the sine of the complex number</button>
<br>
<div id=output style=font-size:20px></div>
I ran your code and the problem occurred on this line:
r **= pow;
When I used "54" as an input, the last iteration it could handle was r=54 & pow = 177, which produced 4.3022484685528774e+306. In the next iteration pow became 179, which produced Infinity, because it had exceeded the limits of 64 bit floats.
One way to deal with this issue is to use BigInt for the portions of your code that don't require the data after the decimal point. I made a fiddle here where you can see that BigInt can handle 54**179. https://jsfiddle.net/afyk6rbu/
const big = BigInt(54)**BigInt(179)
console.log(big.toString())
console.log(Number(big))
The toString shows that it has successfully calculated the values, but Number(big) shows that the number is too large to fit in a normal number. It must be brought back into the range of a 64 bit float before it can be used for trig.

How to Factorial only 5 numbers?

I have a factorial code but when it will find the result of the factorial it will get the result of the whole factorial.
Im looking for a code that finds the factorial of the last 5 factorials of a number? For example, 10! ? I need only the result of 10 x 9 x 8 x 7 x 6 = 30240? How do I do that?
<html>
<body>
<script type = "text/javascript">
var n = parseInt(window.prompt("Enter the Number:"));
var result = fact(n);
window.alert("Factorial of the given number " + result);
function fact(n)
{
if(n == 0)
return 1;
else
return (n*fact(n-1));
}
</script>
</body>
As MinusFour already noted: you want 10!/5!. You can do it that way and compute both values and divide. They divide exactly, no worry about fractions (proof omitted). But it is size-restricted, you cannot do e.g. 100!95! in JavaScript without a big-integer library and even with a big-integer library things like 1000000!/999998! will need a lot of computation time (both are numbers with over 5 million decimal digits).
My suggestion: no tricks, just compute it linearly like you would do it by hand:
function fact(n,k){
var t = 1;
for(var i = n;i>k;i--){
t *= i;
}
return t;
}
console.log(fact(10,5));
The first one must be the bigger one, both must be positive, all other checks and balances are omitted, too.

Exponents without Math.pow() JavaScript

I need to write a program that takes two integers base and exponents and compute the exponents without using Math.Pow(). I have created the code using the Math.pow() method I can't figure out how to make it work without it. I have tried base^exp but it doesn't give me the right answer. Thanks in advance!
/* Write a JavaScript function named intPow that reads two numbers named base and exp from two text fields. Assume that the second number will always be an integer greater than or equal to 1. Your function should not use any of the built in Math functions such as Math.pow. Your function should use a loop to compute the value of baseexp meaning base raised to the power of exp. Your function must output the result of baseexp to a div. Hint: write your function to compute 1 multiplied by base exp times. */
<!DOCTYPE HTML>
<html lang="en-us">
<head>
<meta charset="utf-8">
<title>Integer Power</title>
<script type="text/javascript">
/* Write a JavaScript function named intPow that reads two numbers named base and exp from two text fields. Assume that the second number will always be an integer greater than or equal to 1. Your function should not use any of the built in Math functions such as Math.pow. Your function should use a loop to compute the value of baseexp meaning base raised to the power of exp. Your function must output the result of baseexp to a div. Hint: write your function to compute 1 multiplied by base exp times. */
function intPow() {
var base = parseFloat(document.getElementById("baseBox").value);
var exp = parseFloat(document.getElementById("expBox").value);
var output = "";
var i = 0;
for (i = 1; i <= exp; i++) {
output = Math.pow(base, exp);
}
document.getElementById("outputDiv").innerHTML = output;
}
</script>
</head>
<body>
<h1>Find the power of <i>Base</i> by entering an integer in the <i>base</i> box, and an integer in the <i>exponent</i> box.</h1> Base:
<input type="text" id="baseBox" size="15"> Exponents:
<input type="text" id="expBox" size="15">
<button type="button" onclick="intPow()">Compute Exponents</button>
<div id="outputDiv"></div>
</body>
</html>`
For anyone looking this up in the future, such as me just now, this is a solid solution:
function computePower(num, exponent) {
var result = 1;
for (i = 0; i < exponent; i++) {
result *= num;
}
return result;
}
Given a number and an exponent, "computePower" returns the given number, raised to the given exponent.
#user5500799,
output = (1 * base ) * exp;
won't work, because you are not raising the base to the exponent, just multiplying it. Starting with a multiplication with 1 is great though: in my code, that ensures that, for example, 2 to the power of 0 is 1 (everything to the power of 0 is one, which is something that is defined)
with ES2016 you can use the exponentiation operator.
2 ** 8 // 256
I was able to figure it out by changint output to:
output = (1 * base ) * exp;

Math.random() returns value greater than one?

While playing around with random numbers in JavaScript I discovered a surprising bug, presumably in the V8 JavaScript engine in Google Chrome. Consider:
// Generate a random number [1,5].
var rand5 = function() {
return parseInt(Math.random() * 5) + 1;
};
// Return a sample distribution over MAX times.
var testRand5 = function(dist, max) {
if (!dist) { dist = {}; }
if (!max) { max = 5000000; }
for (var i=0; i<max; i++) {
var r = rand5();
dist[r] = (dist[r] || 0) + 1;
}
return dist;
};
Now when I run testRand5() I get the following results (of course, differing slightly with each run, you might need to set "max" to a higher value to reveal the bug):
var d = testRand5();
d = {
1: 1002797,
2: 998803,
3: 999541,
4: 1000851,
5: 998007,
10: 1 // XXX: Math.random() returned 4.5?!
}
Interestingly, I see comparable results in node.js, leading me to believe it's not specific to Chrome. Sometimes there are different or multiple mystery values (7, 9, etc).
Can anyone explain why I might be getting the results I see? I'm guessing it has something to do with using parseInt (instead of Math.floor()) but I'm still not sure why it could happen.
The edge case occurs when you happen to generate a very small number, expressed with an exponent, like this for example 9.546056389808655e-8.
Combined with parseInt, which interprets the argument as a string, hell breaks loose. And as suggested before me, it can be solved using Math.floor.
Try it yourself with this piece of code:
var test = 9.546056389808655e-8;
console.log(test); // prints 9.546056389808655e-8
console.log(parseInt(test)); // prints 9 - oh noes!
console.log(Math.floor(test)) // prints 0 - this is better
Of course, it's a parseInt() gotcha. It converts its argument to a string first, and that can force scientific notation which will cause parseInt to do something like this:
var x = 0.000000004;
(x).toString(); // => "4e-9"
parseInt(x); // => 4
Silly me...
I would suggest changing your random number function to this:
var rand5 = function() {
return(Math.floor(Math.random() * 5) + 1);
};
This will reliably generate an integer value between 1 and 5 inclusive.
You can see your test function in action here: http://jsfiddle.net/jfriend00/FCzjF/.
In this case, parseInt isn't the best choice because it's going to convert your float to a string which can be a number of different formats (including scientific notation) and then try to parse an integer out of it. Much better to just operate on the float directly with Math.floor().

Javascript Number Formatting

Certainly a stupid question, please forgive me. My customer wants decimal numbers to display with five digits. For example: 100.34 or 37.459. I was accomplishing this with val.toPrecision (5);; however, when my numbers get really small, I stop getting what I want. For example, if my number is 0.000347, it displays 0.00034700. Now, I understand why it's doing this, but what I don't know is how to get it to display 0.0003. Any thoughts?
Math.round(0.000347 * 1e4) / 1e4
Or with toFixed:
Number.prototype.toNDigits = function (n) {
return (Math.abs(this) < 1) ?
this.toFixed(n - 1) :
this.toPrecision(n);
};
http://jsfiddle.net/HeQtH/6/
Our problem is with numbers less than 1 obviously. So catch them and deal them separately
function SetPrecisionToFive(n){
return (n > 1) ? n.toPrecision (5) : (Math.round(n * 1e4) / 1e4).toString();
}
You can use the toFixed method to accomplish this. For example: (0.000347).toFixed(4)
The Javascript toFixed() function will truncate small numbers to a fixed decimal precision, eg:
var num = .0000350;
var result = num.toFixed(5); // result will equal .00003

Categories