Factorial in C family languages - c#

I've been trying to make a factorial function in C++, and I just found that inputs which are greater than 10 are not calculated correctly. I tried C# but I faced the same problem.
using this recursive function :
int Factorial(int Number) {
if (Number == 0) return 1;
return Number * Factorial(Number - 1);
}
The program returns 0 for large numbers, and even small inputs such 15 or 16 are wrongly calculated, I mean the result differs from what I get in windows calculator.

That's because int is limited to 32 bits, and results of 10! much beyond 10 will give you a bigger result. For larger values, you can get an approximate result using double as the result. If you want more than about 16 digits precision, you need to use a multiprecision math library.
Using uint64_t would allow a larger number, but still fairly limited.

This is because factorials are big numbers and the don't fit in an int variable. It overflows. If You use unsigned long long instead of int, You can compute greater factorials.
If the result doesn't need to be precise, You can use double as well. In the other case, You can implement the multiplication on arrays and You can compute as big factorials as You want.
In C/C++, I recommend the GMP library
And because you asked for C family languages: Java has a BigInteger type which is also useful.

Variables cannot hold an infinite number of values. On a 32-bit machine, the maximum value an int can represent is 2^31-1, or 2147483647. You can use another type, such as unsigned int, long, unsigned long, long long, or the largest one, unsigned long long. Factorials are big numbers, and can easily overflow! If you want arbitrary precision, you should use a bignum library, such as GNU GMP.

Reason for You problem in simple.In C++ biggest in Long Long int. it has range of ~10^18. so you can't store numbers greater than that. and 100! have 158 digits in it so there is no way you can store that number in C++/C unless you can use vector/Array
You are a new Programmer and you are using Only C++/C .
Then i will not recommend for using GMP library for programming purpose(Algorithm or Programming contest Purpose) unless you are programming for some software.
I think you can implement your own and use it.. I use this one for my own purpose in Programming contest and Algorithm problem.
// Shashank Jain
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#define LL long long int
using namespace std;
vector<int> fact;
void do_it(int num)
{
int temp,carry;
vector<int>:: iterator it;
carry=0;
for(it=fact.begin();it!=fact.end();it++)
{
temp=(*it)*num;
temp+=carry;
*it=temp%10;
carry=temp/10;
}
if(carry!=0)
{
while(carry>0)
{
temp=carry%10;
fact.push_back(temp);
carry/=10;
}
}
}
int main()
{
int num,i,l;
cin>>num; // enter number for which you want to get factorial
fact.push_back(1);
for(i=2;i<=num;i++)
do_it(i);
l=fact.size();
cout<<"The Length of factorial is: "<<l<<endl;
for(i=l-1;i>=0;i--)
{
cout<<fact[i];
}
cout<<endl;
return 0;
}
Running Code link On Ideone
This can easily get the factorial of 2000 in less than 1 sec. Or else You can use GMP library. But Those are not allowed for Programming Contest like Google Code jam or Facebook Hacker Cup. or topcoder or anyother standard programming contest

Related

Calculators working with larger numbers than 18446744073709551615

When I Initialize a ulong with the value 18446744073709551615 and then add a 1 to It and display to the Console It displays a 0 which is totally expected.
I know this question sounds stupid but I have to ask It. if my Computer has a 64-bit architecture CPU how is my calculator able to work with larger numbers than 18446744073709551615?
I suppose floating-point has a lot to do here.
I would like to know exactly how this happens.
Thank you.
working with larger numbers than 18446744073709551615
"if my Computer has a 64-bit architecture CPU" --> The architecture bit size is largely irrelevant.
Consider how you are able to add 2 decimal digits whose sum is more than 9. There is a carry generated and then used when adding the next most significant decimal place.
The CPU can do the same but with base 18446744073709551616 instead of base 10. It uses a carry bit as well as a sign and overflow bit to perform extended math.
I suppose floating-point has a lot to do here.
This is nothing to do with floating point.
; you say you're using ulong, which means your using unsigned 64-but arithmetic. The largest value you can store is therefore "all ones", for 64 bits - aka UInt64.MaxValue, which as you've discovered: https://learn.microsoft.com/en-us/dotnet/api/system.uint64.maxvalue
If you want to store arbitrarily large numbers: there are APIs for that - for example BigInteger. However, arbitrary size cones at a cost, so it isn't the default, and certainly isn't what you get when you use ulong (or double, or decimal, etc - all the compiler-level numeric types have fixed size).
So: consider using BigInteger
You either way have a 64 bits architecture processor and limited to doing 64 bits math - your problem is a bit hard to explain without taking an explicit example of how this is solved with BigInteger in System.Numerics namespace, available in .NET Framework 4.8 for example. The basis is to 'decompose' the number into an array representation.
mathematical expression 'decompose' here meaning :
"express (a number or function) as a combination of simpler components."
Internally BigInteger uses an internal array (actually multiple internal constructs) and a helper class called BigIntegerBuilder. In can implicitly convert an UInt64 integer without problem, for even bigger numbers you can use the + operator for example.
BigInteger bignum = new BigInteger(18446744073709551615);
bignum += 1;
You can read about the implicit operator here:
https://referencesource.microsoft.com/#System.Numerics/System/Numerics/BigInteger.cs
public static BigInteger operator +(BigInteger left, BigInteger right)
{
left.AssertValid();
right.AssertValid();
if (right.IsZero) return left;
if (left.IsZero) return right;
int sign1 = +1;
int sign2 = +1;
BigIntegerBuilder reg1 = new BigIntegerBuilder(left, ref sign1);
BigIntegerBuilder reg2 = new BigIntegerBuilder(right, ref sign2);
if (sign1 == sign2)
reg1.Add(ref reg2);
else
reg1.Sub(ref sign1, ref reg2);
return reg1.GetInteger(sign1);
}
In the code above from ReferenceSource you can see that we use the BigIntegerBuilder to add the left and right parts, which are also BigInteger constructs.
Interesting, it seems to keep its internal structure into an private array called "_bits", so that is the answer to your question. BigInteger keeps track of an array of 32-bits valued integer array and is therefore able to handle big integers, even beyond 64 bits.
You can drop this code into a console application or Linqpad (which has the .Dump() method I use here) and inspect :
BigInteger bignum = new BigInteger(18446744073709551615);
bignum.GetType().GetField("_bits",
BindingFlags.NonPublic | BindingFlags.Instance).GetValue(bignum).Dump();
A detail about BigInteger is revealed in a comment in the source code of BigInteger on Reference Source. So for integer values, BigInteger stores the value in the _sign field, for other values the field _bits is used.
Obviously, the internal array needs to be able to be converted into a representation in the decimal system (base-10) so humans can read it, the ToString() method converts the BigInteger to a string representation.
For a better in-depth understanding here, consider doing .NET source stepping to step way into the code how you carry out the mathematics here. But for a basic understanding, the BigInteger uses an internal representation of which is composed with 32 bits array which is transformed into a readable format which allows bigger numbers, bigger than even Int64.
// For values int.MinValue < n <= int.MaxValue, the value is stored in sign
// and _bits is null. For all other values, sign is +1 or -1 and the bits are in _bits

How can i get precision up-to 128 decimal places in C#?

I have tried BigInteger, decimal, float and long but no luck.
Screenshot of required output example
It is a fairly easy task to write your own rational class; remember, rationals are just pairs of integers, and you already have BigInteger.
In this series of articles I show how to devise your own big integer and big rational classes starting from absolutely nothing, not even integers. Note that this is not fast and not intended to be fast; it is intended to be educational. You can use the techniques I describe in this series to help you when designing your arithmetic class.
https://ericlippert.com/2013/09/16/math-from-scratch-part-one/
Or, if you don't want to write it yourself, you can always use the one from Microsoft:
http://bcl.codeplex.com/wikipage?title=BigRational&referringTitle=Home
But that said...
I need a minimum of 128 decimal places to calculate precise probabilities of events between different time steps
Do you need 128 decimal places to represent 128 digits of precision, or of magnitude? Because if it is just magnitude, then simply do a transformation of your probability math into logarithms and do the math in doubles.
The easiest way to achieve arbitrary precision numbers is to combine the BigInteger class from System.Numerics with an int exponent. You could use BigInteger for your exponent, but this is likely overkill as the numbers would be well beyong meaningful in scale.
So if you create a class along these lines:
public class ArbDecimal
{
BigInteger value;
int exponent;
public override string ToString()
{
StringBuilder sb = new StringBuilder();
int place;
foreach (char digit in value.ToString())
{
if (place++ == value.ToString().Length - exponent)
{
sb.Append('.');
}
sb.Append(digit);
}
return sb.ToString();
}
}
You should then be able to define your mathematical operations using the laws of indices with the value and exponent fields.
For instance, to achieve addition, you would scale the larger value to have the same exponent as the smaller one by multiplying it by 10^(largerExp-smallerExp) then adding the two values and rescaling.
In your class, the number 0.01 would be represented like:
value = 1
exponent = -2
Due to the fact that 1*10^-2 = 0.01.
Utilising this method, you can store arbitrarily precise (and large) numbers limited only by the available ram and the .NET framework's object size limit.

Efficient bit remapping algorithm

I have a use case where I need to scramble an input in such a way that:
Each specific input always maps to a specific pseudo-random output.
The output must shuffle the input sufficiently so that an incrementing input maps to a pseudo-random output.
For example, if the input is 64 bits, there must be exactly 2^64 unique outputs, and these must break incrementing inputs as much as possible (arbitrary requirement).
I will code this in C#, but can translate from Java or C, so long as there are not SIMD intrinsics. What I am looking for is some already existing code, rather than reinventing the wheel.
I have looked on Google, but haven't found anything that does a 1:1 mapping.
This seems to work fairly well:
const long multiplier = 6364136223846793005;
const long mulinv_multiplier = -4568919932995229531;
const long offset = 1442695040888963407;
static long Forward(long x)
{
return x * multiplier + offset;
}
static long Reverse(long x)
{
return (x - offset) * mulinv_multiplier;
}
You can change the constants to whatever as long as multiplier is odd and mulinv_multiplier is the modular multiplicative inverse (see wiki:modular multiplicative inverse or Hackers Delight 10-15 Exact Division by Constants) of multiplier (modulo 2^64, obviously - and that's why multiplier has to be odd, otherwise it has no inverse).
The offset can be anything, but make it relatively prime with 2^64 just to be on the safe side.
These specific constants come from Knuths linear congruential generator.
There's one small thing: it puts the complement of the LSB of the input in the LSB of the result. If that's a problem, you could just rotate it by any nonzero amount.
For 32 bits, the constants can be multiplier = 0x4c957f2d, offset = 0xf767814f, mulinv_multiplier = 0x329e28a5.
For 64 bits, multiplier = 12790229573962758597, mulinv_multiplier = 16500474117902441741 may work better.
Or, you could use a CRC, which is reversible for this use (ie the input is the same size as the CRC) for CRC64 it requires some modifications of course.
Just from the top of my head:
Shift the input: Make sure you keep every bit, i.e. use two shift operations in different directions and OR the result together.
Apply an static XOR.
Everything else that comes to my mind won't be bijective. However, a search for bijective might bring up something useful ;D

factorial method resulting in error

I'm trying to get the factorial value of number 66, but my method resulting me an output 0. But whenever I try to get the factorial of 5, it is resulting me an output 120. Could anyone please tell me why?
public static int factorial(int n)
{
if (n == 1)
return n;
return n * factorial(n - 1);
}
Sure - factorials get very big, very fast. You're overflowing the bounds of int very quickly... and at some point you'll have multiplied by enough factors to get an overflow to 0, which will then keep the value at 0 forever.
According to a quick Google search, 66 factorial is 5.44344939 × 1092 - which is considerably more than int can handle, or even long or decimal. You could get double to handle it - you'd lose a huge amount of precision, and that would accumulate really quickly too, but at least it wouldn't overflow...
Your method overflows. See the following example:
static void Main(string[] args)
{
Console.WriteLine(factorial(66));
}
public static int factorial(int n)
{
if (n == 1)
return n;
var result = n * factorial(n - 1);
Console.WriteLine("{0} : {1}", n, result);
return result;
}
With this example, the results of each iteration is printed.
You see that at one point, result becomes 0 and this means that every iteration from that point on becomes n * 0.
You can try using BigInteger. This will give the correct result. Calculate factorials in C# contains more information on this.
66! does not fit into an int. Use BigInteger.
The problem is that the factorial of 66 is way to large to fit into an int. I think it will also we way to large to fit into a long.
As an example, factorial(20) will return 2432902008176640000
The factorial of 50 is 3.0414093202×1064 which exeeds already what a int can contain.
Use long or BigInteger for this.
You get numeric overflow, 66! ~= 5e92 which is way larger than an int can handle. Also, factorials are better calculated using a for loop.
Approximately 13 or 14 is the largest number whose factorial fits in an int... If you switch to long, it'll be aroung 18 or 19 if I recall correctly. If you wish arbitraty big numbers you'd have to write your own big arithmetic library or use an existing one :)
You need to use the appropriate data type.
In this case the Big Integer data type is probably best seeing as how fast the numbers get real big.
Here is the way you use this data type.
Right click on your project, choose the add reference menu.
Look for the system.numerics library and add it.
You then add the using clause in your code.
And then you can initialise variable with the keyword as usual.

convert double value to binary value

How can i convert double value to binary value.
i have some value like this below 125252525235558554452221545332224587265 i want to convert this to binary format..so i am keeping it in double and then trying to convert to binary (1 & 0's).. i am using C#.net
Well, you haven't specified a platform or what sort of binary value you're interested in, but in .NET there's BitConverter.DoubleToInt64Bits which lets you get at the IEEE 754 bits making up the value very easily.
In Java there's Double.doubleToLongBits which does the same thing.
Note that if you have a value such as "125252525235558554452221545332224587265" then you've got more information than a double can store accurately in the first place.
In C, you can do it for instance this way, which is a classic use of the union construct:
int i;
union {
double x;
unsigned char byte[sizeof (double)];
} converter;
converter.x = 5.5555555555556e18;
for(i = 0; i < sizeof converter.byte; i++)
printf("%02x", converter.byte[i]);
If you stick this in a main() and run it, it might print something like this:
~/src> gcc -o floatbits floatbits.c
~/src> ./floatbits
ba b5 f6 15 53 46 d3 43
Note though that this, of course, is platform-dependent in its endianness. The above is from a Linux system running on a Sempron CPU, i.e. it's little endian.
A decade late but hopefully this will help someone:
// Converts a double value to a string in base 2 for display.
// Example: 123.5 --> "0:10000000101:1110111000000000000000000000000000000000000000000000"
// Created by Ryan S. White in 2020, Released under the MIT license.
string DoubleToBinaryString(double val)
{
long v = BitConverter.DoubleToInt64Bits(val);
string binary = Convert.ToString(v, 2);
return binary.PadLeft(64, '0').Insert(12, ":").Insert(1, ":");
}
If you mean you want to do it yourself, then this is not a programming question.
If you want to make a computer do it, the easiest way is to use a floating point input routine and then display the result in its hex form. In C++:
double f = atof ("5.5555555555556E18");
unsigned char *b = (unsigned char *) &f;
for (int j = 0; j < 8; ++j)
printf (" %02x", b [j]);
A double value already IS a binary value. It is just a matter of the representation that you wish it to have. In a programming language when you call it a double, then the language that you use will interpret it in one way. If you happen to call the same chunk of memory an int, then it is not the same number.
So it depends what you really want... If you need to write it to disk or to network, then you need to think about BigEndian/LittleEndian.
For these huge numbers (who cannot be presented accurately using a double) you need to use some specialized class to hold the information needed.
C# provides the Decimal class:
The Decimal value type represents decimal numbers ranging from positive 79,228,162,514,264,337,593,543,950,335 to negative 79,228,162,514,264,337,593,543,950,335. The Decimal value type is appropriate for financial calculations requiring large numbers of significant integral and fractional digits and no round-off errors. The Decimal type does not eliminate the need for rounding. Rather, it minimizes errors due to rounding. For example, the following code produces a result of 0.9999999999999999999999999999 rather than 1.
If you need bigger precision than this, you need to make your own class I guess. There is one here for ints: http://sourceforge.net/projects/cpp-bigint/ although it seems to be for c++.

Categories

Resources