Calculating factorial exceeds max integer limit in Javascript - javascript

I am trying to create a function for calculating factorial of a given number. It works fine until I pass a number greater than 21 to the function. I understand that 21! exceeds the max limit of integer, But then is there a solution for that ! Or I am doing something wrong here ! Please help ! Given below is my function for factorial calculation.
function calculateFactorial(number)
{
var counter = 1;
var factorial = number;
if (number == 1) {
factorial = number;
}
else {
while(counter < number)
{
factorial = factorial * (number - counter);
counter++;
}
}
return factorial;
}

You should use a BigInteger library for javascript.
You can write it by your own (if you don't need advanced operations, it's quite easy and funny to write), or you can search online. There are tons of those libraries out there:
What JavaScript library can I use to manipulate big integers?

You can:
Use BigInteger
Use floats with the Stirling formula
http://en.wikipedia.org/wiki/Stirling%27s_approximation

Related

JavaScript factorial prevent infinity

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
}

Convert A Large Integer To a Hex String In Javascript

I need to find a way to convert a large number into a hex string in javascript. Straight off the bat, I tried myBigNumber.toString(16) but if myBigNumber has a very large value (eg 1298925419114529174706173) then myBigNumber.toString(16) will return an erroneous result, which is just brilliant. I tried writing by own function as follows:
function (integer) {
var result = '';
while (integer) {
result = (integer % 16).toString(16) + result;
integer = Math.floor(integer / 16);
}
}
However, large numbers modulo 16 all return 0 (I think this fundamental issue is what is causing the problem with toString. I also tried replacing (integer % 16) with (integer - 16 * Math.floor(integer/16)) but that had the same issue.
I have also looked at the Big Integer Javascript library but that is a huge plugin for one, hopefully relatively straightforward problem.
Any thoughts as to how I can get a valid result? Maybe some sort of divide and conquer approach? I am really rather stuck here.
Assuming you have your integer stored as a decimal string like '1298925419114529174706173':
function dec2hex(str){ // .toString(16) only works up to 2^53
var dec = str.toString().split(''), sum = [], hex = [], i, s
while(dec.length){
s = 1 * dec.shift()
for(i = 0; s || i < sum.length; i++){
s += (sum[i] || 0) * 10
sum[i] = s % 16
s = (s - sum[i]) / 16
}
}
while(sum.length){
hex.push(sum.pop().toString(16))
}
return hex.join('')
}
The numbers in question are above javascript's largest integer. However, you can work with such large numbers by strings and there are some plugins which can help you do this. An example which is particularly useful in this circumstance is hex2dec
The approach I took was to use the bignumber.js library and create a BigNumber passing in the value as a string then just use toString to convert to hex:
const BigNumber = require('bignumber.js');
const lrgIntStr = '1298925419114529174706173';
const bn = new BigNumber(lrgIntStr);
const hex = bn.toString(16);

Total Price variable limit to 2 decimals using ajax with php

I am using the following code snippet to calculate a total price. This works great except #totalPrice on some occasions expands out to for example $267.9999999999. How do I reformat #totalPrice within this function to just round to two decimals as is standard in dealing with price.
function getTotalCost(inventory) {
if(inventory) {
getTotalParts(inventory);
getTotalMarkup(inventory);
}
var labor = $('#labor').val() * 1;
var totals = 0;
for(i in totalMarkup) {
totals += totalMarkup[i];
}
totalCost = totals+labor;
/*if(totals == 0) {
totalCost = 0;
}*/
$('#totalPrice').html(totalCost);
}
You can have:
$('#totalPrice').html(totalCost.toFixed(2));
See:
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Number/toFixed
Notice that toFixed method returns a formatted number, therefore converts the number to a string. It's not a problem here because html wants a string, but it's keep it in mind that in order to avoid concatenation of string when you expects sum of numbers. I believe you use $('#labor').val() * 1; for this very reason. However it's not necessary, it's better use method like parseFloat or the unary plus operator:
var labor = +$('#labor').val();
When working with javascript the floating points are always a bad. Best you can do is, round it up.
But in this case you can do
(totalCost).toFixed(2);
You can use Math.round function in JavaScript like this.
totalCost = Math.round(totalCost*100)/100;
$('#totalPrice').html(totalCost);

Javascript Convert numbers to different formats or string alternative

UPDATED:
Using javascript or jQuery, how can I convert a number into it's different variations:
eg:
1000000
to...
1,000,000 or 1000K
OR
1000
to...
1,000 or 1K
OR
1934 and 1234
to...
1,934 or -2K (under 2000 but over 1500)
or
1,234 or 1k+ (over 1000 but under 1500)
Can this is done in a function?
Hope this make sense.
C
You can add methods to Number.prototype, so for example:
Number.prototype.addCommas = function () {
var intPart = Math.round(this).toString();
var decimalPart = (this - Math.round(this)).toString();
// Remove the "0." if it exists
if (decimalPart.length > 2) {
decimalPart = decimalPart.substring(2);
} else {
// Otherwise remove it altogether
decimalPart = '';
}
// Work through the digits three at a time
var i = intPart.length - 3;
while (i > 0) {
intPart = intPart.substring(0, i) + ',' + intPart.substring(i);
i = i - 3;
}
return intPart + decimalPart;
};
Now you can call this as var num = 1000; num.addCommas() and it will return "1,000". That's just an example, but you'll find that all the functions create will involve converting the numbers to strings early in the process then processing and returning the strings. (The separating integer and decimal part will probably be particularly useful so you might want to refactor that out into its own method.) Hopefully this is enough to get you started.
Edit: Here's how to do the K thing... this one's a bit simpler:
Number.prototype.k = function () {
// We don't want any thousands processing if the number is less than 1000.
if (this < 1000) {
// edit 2 May 2013: make sure it's a string for consistency
return this.toString();
}
// Round to 100s first so that we can get the decimal point in there
// then divide by 10 for thousands
var thousands = Math.round(this / 100) / 10;
// Now convert it to a string and add the k
return thousands.toString() + 'K';
};
Call this in the same way: var num = 2000; num.k()
Theoretically, yes.
As TimWolla points out, it requires a lot of logic.
Ruby on Rails have a helper for presenting time with words. Have a look at the documentation. The implementation for that code is found on GitHub, and could give you some hint as how to go about implementing this.
I agree with the comment to reduce the complexity by choosing one format.
Hope you find some help in my answer.

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