Is there an algorithm for calculating a factorial without using System.Numerics library? We receive an int number and we need to return factorial of this number as string(if n = 30, we should return "265252859812191058636308480000000", if n = 70, we should return "11978571669969891796072783721689098736458938142546425857555362864628009582789845319680000000000000000" ect. Numbers are very big)
I tried to find out, did anyone already write an article about that, but I didn't find anything.
It suffices to implement multiplication of a large number as a string by a small integer.
Illustration: 12! = 11! x 12 is obtained by multiplying every digit by 12 and summing (with shifts):
39916800
36
108
108
12
72
96
0
0
---------
479001600
A lazy solution. It is possible to evaluate the factorial with just BigNum addition, replacing the multiplications by successive additions. (For n!, we will perform 1+2+3+...n-1 additions. This is acceptable for moderate n.)
The computation uses two pre-allocated string (arrays of char), which are initially filled with null bytes (Writeline skips them). When adding from right to left, we stop when we meet a null.
int n = 20;
// Factorial and temporary string; 100! fits in 158 digits
const int N = 158;
char[] f = new char[N], t = new char[N];
f[N - 1] = '1'; // 1!
// Product up to n by successive additions
for (int i = 2; i <= n; i++)
{
// t= f
f.CopyTo(t, 0);
for (int j = 0; j < i - 1; j++)
{
// f+= t, repeated i-1 times
int c = 0; // Carry
for (int k = N - 1; k >= 0; k--)
{
if (t[k] == 0 && c == 0) break; // Significant part exhausted
int d = Math.Max(0, t[k] - '0') + Math.Max(0, f[k] - '0') + c;
c= d / 10; d = d % 10; f[k] = (char)(d + '0'); // Next carry/digit
}
}
Console.WriteLine(f);
}
Output:
2
6
24
120
720
5040
40320
362880
3628800
39916800
479001600
6227020800
87178291200
1307674368000
20922789888000
355687428096000
6402373705728000
121645100408832000
2432902008176640000
static string FindFactorial(int n)
{
int[] result = new int[500000];
result[0] = 1;
int resultSize = 1;
for (int x = 2; x <= n; x++)
resultSize = Multiply(x, result, resultSize);
string factorial = "";
for (int i = resultSize - 1; i >= 0; i--)
factorial += result[i].ToString();
return factorial;
}
static int Multiply(int x, int[] result, int resultSize)
{
int carry = 0;
for (int i = 0; i < resultSize; i++)
{
int product = result[i] * x + carry;
result[i] = product % 10;
carry = product / 10;
}
while (carry != 0)
{
result[resultSize] = carry % 10;
carry /= 10;
resultSize++;
}
return resultSize;
}
This will work
Related
I have problem with solution in this example Say Me Please Operations(codeKata):
You have a string with N numbers, every 2 numbers after an operation(?) return next number in this string.
Write a function who return new string with respective operations :
1)addition,
2)subtraction,
3)multiplication,
4)division.
example: for string stringNumbers = "9 4 5 20 25"
your function must return:
"subtraction, multiplication, addition"
because,
9 - 4 = 5 - substraction,
4 * 5 = 20 - multiplication,
5 + 20 = 25 - addition,
My Code:
int x = 0,add = 0, multi = 0, sub = 0, divi = 0, z = 0;
var v = stringNumbers.Split(' ').ToArray();
string s = "";
if (v.Length >= 3)
{
for (int i = 0; i < v.Length; i++)
for (int j = i + 1; j < v.Length; j++)
for (int k = j + 1; k < v.Length; k++)
{
Console.WriteLine(k);
x = int.Parse(v[i]);
z = int.Parse(v[j]);
add = x + z;
multi = x * z;
sub = x - z;
divi = x / z;
if (add == int.Parse(v[k]))
{
s += "addition, ";
}
else if (sub == int.Parse(v[k]))
{
s += "subtraction, ";
}
else if (multi == int.Parse(v[k]))
{
s += "multiplication, ";
}
else if (divi == int.Parse(v[k]))
{
if (int.Parse(v[i]) != 0)
s += "division, ";
}
else
{
break;
}
}
}
else
return "";
s = s.Remove(s.Length - 2, 2);
return s;
I passed sample test, but no this one.I dont know where is issue.
Thanks for help!
This is my third post sorry for the mistakes.
Something like this is a lot simpler and will accomplish the same without the layers of loops you are using:
public static string ProcessOperations(string numbers)
{
string[] numberArray;
string returnValue = string.Empty;
numberArray = numbers.Split(' ');
for (int i = 0; i < numberArray.Length - 2; i++)
{
if (int.TryParse(numberArray[i], out int a) &&
int.TryParse(numberArray[i + 1], out int b) &&
int.TryParse(numberArray[i + 2], out int c))
{
if (a + b == c)
returnValue += "addition, ";
else if (a - b == c)
returnValue += "subtraction, ";
else if (a * b == c)
returnValue += "multiplication, ";
else if (a / b == c)
returnValue += "division, ";
}
}
returnValue = returnValue.TrimEnd(new[] { ',', ' ' });
return returnValue;
}
Testing with the only value you supplied:
?ProcessOperations("9 4 5 20 25");
subtraction, multiplication, addition
This uses a single loop that operates up until the end position - 2. It then parses the items at position i, i + 1, and i + 2 (into a, b, and c). Following that, it checks which arithmatic operation is used to calculate c from a and b.
There's a TrimEnd just before the return to remove any spurious commas and spaces.
Notes: There's no error checking is no arithmatic operation will give the result. The division is integer division so will not work with floating point numbers.
Let's say v.length is 5.
You want to execute the following loops passes:
i=0, j=1, k=2
i=1, j=2, k=3
i=2, j=3, k=4
But that's not what you're doing. You have j and k change semi-independently of i.
i=0, j=1, k=2
i=0, j=1, k=3
i=0, j=1, k=4
i=0, j=2, k=3
i=0, j=2, k=4
i=0, j=3, k=4
i=1, j=2, k=3
i=1, j=2, k=4
i=1, j=3, k=4
i=2, j=3, k=4
To get the desired outcome, you should only have one loop. You can derive the other values from the loop variable.
You could derive j and k from i as follows:
for (int i = 0; i < v.Length - 2; ++i) {
int j = i + 1;
int k = i + 2;
...
}
Or you could could derive i and j from k as follows:
for (int k = 2; k < v.Length; ++k) {
int i = k - 2;
int j = k - 1;
...
}
Either way, the if (v.Length >= 3) check is useless. The for already performs an equivalent check. I also recommend parsing the elements of v once each (before the main loop) rather than parsing them repeatedly.
What I want to know is how many numbers can be set if N bits are set to 1 out of 32bits.
Example lets try with 4 bits
//HowMany(1) = 4
//1000
//0100
//0010
//0001
//
//HowMany(2) = 6
//1001
//1010
//1100
//0110
//0101
//0011
public int HowMany(int bits)
{
....
}
I am trying to compute a precompute a dictionary for this but it takes ages:
var dict = new Dictionary<int, int>();
for (int i = 0; i <= Int32.MaxValue; i++)
{
var str = Convert.ToString(i, 2);
var count = str.Count(x => x == '1');
if (!dict .ContainsKey(count))
dict .Add(count, 0);
dict [count] += 1;
}
Easily: if size is n (32 in case of Int32) and we have exactly k bits set, we can represent
C(k, n) = n! / (k! * (n - k)!)
numbers, where C(k, n) stands for a binomial coefficient.
Edit: As dasblinkenlight's mentioned in the comments, 32! is a huge number which exceeds even long.MaxValue so, probably, a more practical formula is
C(k, n) = n * (n - 1) * ... * (n - k + 1) / k!
Possible C# implementation:
private static long HowMany(int k, int n = 32) {
long result = 1;
for (int i = 0; i < k; ++i)
result *= (n - i);
for (int i = 1; i <= k; ++i)
result /= i;
return result;
}
I am trying to calculate the nth digit of Pi without using Math.Pi which can be specified as a parameter.
I modified an existing algorithm, since I like to find the Nth digit without using string conversions or default classes.
This is how my algorithm currently looks like:
static int CalculatePi(int pos)
{
List<int> result = new List<int>();
int digits = 102;
int[] x = new int[digits * 3 + 2];
int[] r = new int[digits * 3 + 2];
for (int j = 0; j < x.Length; j++)
x[j] = 20;
for (int i = 0; i < digits; i++)
{
int carry = 0;
for (int j = 0; j < x.Length; j++)
{
int num = (int)(x.Length - j - 1);
int dem = num * 2 + 1;
x[j] += carry;
int q = x[j] / dem;
r[j] = x[j] % dem;
carry = q * num;
}
if (i < digits - 1)
result.Add((int)(x[x.Length - 1] / 10));
r[x.Length - 1] = x[x.Length - 1] % 10; ;
for (int j = 0; j < x.Length; j++)
x[j] = r[j] * 10;
}
return result[pos];
}
So far its working till digit 32, and then, an error occurs.
When I try to print the digits like so:
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine("{0} digit of Pi is : {1}", i, CalculatePi(i));
}
Console.ReadKey();
}
This I get 10 for the 32rd digit and the 85rd digit and some others as well, which is obviously incorrect.
The original digits from 27 look like so:
...3279502884.....
but I get
...32794102884....
Whats wrong with the algorithm, how can I fix this problem?
And can the algorithm still be tweaked to improve the speed?
So far it works right up until the cursor reaches digit 32. Upon which, an exception is thrown.
Rules are as follows:
Digit 31 is incorrect, because it should be 5 not a 4.
Digit 32 should be a 0.
When you get a 10 digit result you need to carry 1 over to the previous digit to change the 10 to a 0.
The code changes below will work up to ~ digit 361 when 362 = 10.
Once the program enters the 900's then there are a lot of wrong numbers.
Inside your loop you can do this by keeping track of the previous digit, only adding it to the list after the succeeding digit has been computed.
Overflows need to be handled as they occur, as follows:
int prev = 0;
for (int i = 0; i < digits; i++)
{
int carry = 0;
for (int j = 0; j < x.Length; j++)
{
int num = (int)(x.Length - j - 1);
int dem = num * 2 + 1;
x[j] += carry;
int q = x[j] / dem;
r[j] = x[j] % dem;
carry = q * num;
}
// calculate the digit, but don't add to the list right away:
int digit = (int)(x[x.Length - 1] / 10);
// handle overflow:
if(digit >= 10)
{
digit -= 10;
prev++;
}
if (i > 0)
result.Add(prev);
// Store the digit for next time, when it will be the prev value:
prev = digit;
r[x.Length - 1] = x[x.Length - 1] % 10;
for (int j = 0; j < x.Length; j++)
x[j] = r[j] * 10;
}
Since the digits are being updated sequentially one-by-one, one whole iteration later than previously, the if (i < digits - 1) check can be removed.
However, you need to add a new one to replace it: if (i > 0), because you don't have a valid prev value on the first pass through the loop.
The happy coincidence of computing only the first 100 digits means the above will work.
However, what do you suppose will happen when a 10 digit result follows a 9 digit one? Not good news I'm afraid, because the 1 with need carrying over to the 9 (the previous value), which will make it 10.
A more robust solution is to finish your calculation, then do a loop over your list going backwards, carrying any 10s you encounter over to the previous digits, and propagating any carries.
Consider the following:
for (int pos = digits - 2; pos >= 1; pos--)
{
if(result[pos] >= 10)
{
result[pos] -= 10;
result[pos - 1] += 1;
}
}
I want to ask how I can reorder the digits in an Int32 so they result in the biggest possible number.
Here is an example which visualizes what I am trying to do:
2927466 -> 9766422
12492771 -> 97742211
I want to perform the ordering of the digits without using the System.Linq namespace and without converting the integer into a string value.
This is what I got so far:
public static int ReorderInt32Digits(int v)
{
int n = Math.Abs(v);
int l = ((int)Math.Log10(n > 0 ? n : 1)) + 1;
int[] d = new int[l];
for (int i = 0; i < l; i++)
{
d[(l - i) - 1] = n % 10;
n /= 10;
}
if (v < 0)
d[0] *= -1;
Array.Sort(d);
Array.Reverse(d);
int h = 0;
for (int i = 0; i < d.Length; i++)
{
int index = d.Length - i - 1;
h += ((int)Math.Pow(10, index)) * d[i];
}
return h;
}
This algorithm works flawlessly but I think it is not very efficient.
I would like to know if there is a way to do the same thing more efficiently and how I could improve my algorithm.
You can use this code:
var digit = 2927466;
String.Join("", digit.ToString().ToCharArray().OrderBy(x => x));
Or
var res = String.Join("", digit.ToString().ToCharArray().OrderByDescending(x => x) );
Not that my answer may or may not be more "efficient", but when I read your code you calculated how many digits there are in your number so you can determine how large to make your array, and then you calculated how to turn your array back into a sorted integer.
It would seem to me that you would want to write your own code that did the sorting part without using built in functionality, which is what my sample does. Plus, I've added the ability to sort in ascending or descending order, which is easy to add in your code too.
UPDATED
The original algorithm sorted the digits, now it sorts the digits so that the end result is the largest or smallest depending on the second parameter passed in. However, when dealing with a negative number the second parameter is treated as opposite.
using System;
public class Program
{
public static void Main()
{
int number1 = 2927466;
int number2 = 12492771;
int number3 = -39284925;
Console.WriteLine(OrderDigits(number1, false));
Console.WriteLine(OrderDigits(number2, true));
Console.WriteLine(OrderDigits(number3, false));
}
private static int OrderDigits(int number, bool asc)
{
// Extract each digit into an array
int[] digits = new int[(int)Math.Floor(Math.Log10(Math.Abs(number)) + 1)];
for (int i = 0; i < digits.Length; i++)
{
digits[i] = number % 10;
number /= 10;
}
// Order the digits
for (int i = 0; i < digits.Length; i++)
{
for (int j = i + 1; j < digits.Length; j++)
{
if ((!asc && digits[j] > digits[i]) ||
(asc && digits[j] < digits[i]))
{
int temp = digits[i];
digits[i] = digits[j];
digits[j] = temp;
}
}
}
// Turn the array of digits back into an integer
int result = 0;
for (int i = digits.Length - 1; i >= 0; i--)
{
result += digits[i] * (int)Math.Pow(10, digits.Length - 1 - i);
}
return result;
}
}
Results:
9766422
11224779
-22345899
See working example here... https://dotnetfiddle.net/RWA4XV
public static int ReorderInt32Digits(int v)
{
var nums = Math.Abs(v).ToString().ToCharArray();
Array.Sort(nums);
bool neg = (v < 0);
if(!neg)
{
Array.Reverse(nums);
}
return int.Parse(new string(nums)) * (neg ? -1 : 1);
}
This code fragment below extracts the digits from variable v. You can modify it to store the digits in an array and sort/reverse.
int v = 2345;
while (v > 0) {
int digit = v % 10;
v = v / 10;
Console.WriteLine(digit);
}
You can use similar logic to reconstruct the number from (sorted) digits: Multiply by 10 and add next digit.
I'm posting this second answer because I think I got the most efficient algorithm of all (thanks for the help Atul) :)
void Main()
{
Console.WriteLine (ReorderInt32Digits2(2927466));
Console.WriteLine (ReorderInt32Digits2(12492771));
Console.WriteLine (ReorderInt32Digits2(-1024));
}
public static int ReorderInt32Digits2(int v)
{
bool neg = (v < 0);
int mult = neg ? -1 : 1;
int result = 0;
var counts = GetDigitCounts(v);
for (int i = 0; i < 10; i++)
{
int idx = neg ? 9 - i : i;
for (int j = 0; j < counts[idx]; j++)
{
result += idx * mult;
mult *= 10;
}
}
return result;
}
// From Atul Sikaria's answer
public static int[] GetDigitCounts(int n)
{
int v = Math.Abs(n);
var result = new int[10];
while (v > 0) {
int digit = v % 10;
v = v / 10;
result[digit]++;
}
return result;
}
How might I go about calculating PI in C# to a certain number of decimal places?
I want to be able to pass a number into a method and get back PI calculated to that number of decimal places.
public decimal CalculatePi(int places)
{
// magic
return pi;
}
Console.WriteLine(CalculatePi(5)); // Would print 3.14159
Console.WriteLine(CalculatePi(10)); // Would print 3.1415926535
etc...
I don't care about the speed of the program. I just want it to be as simple and easy to understand as it can be. Thanks in advance for the help.
First, assuming you want some arbitrary number of digits of pi, and we do not want to be confined with the precision of any of the various floating point numbers out there, let us define a Pi function as a string rather than any number type.
One of the coolest algorithms I found while searching for this technique is the Stanley Rabinowitz and Stan Wagon - Spigot Algorithm. It requires no floating point math, and is mostly an iterative method. It does require some memory for storing integer arrays in the intermediate calculations.
Without taking the time to streamline or clean the code here is an implementation of the algorithm (note the result does not add the decimal point).
Please be sure to cite the algorithm and this site if you intend to use this code for anything other than personal use.
C# Code
public static string CalculatePi(int digits)
{
digits++;
uint[] x = new uint[digits*10/3+2];
uint[] r = new uint[digits*10/3+2];
uint[] pi = new uint[digits];
for (int j = 0; j < x.Length; j++)
x[j] = 20;
for (int i = 0; i < digits; i++)
{
uint carry = 0;
for (int j = 0; j < x.Length; j++)
{
uint num = (uint)(x.Length - j - 1);
uint dem = num * 2 + 1;
x[j] += carry;
uint q = x[j] / dem;
r[j] = x[j] % dem;
carry = q * num;
}
pi[i] = (x[x.Length-1] / 10);
r[x.Length - 1] = x[x.Length - 1] % 10; ;
for (int j = 0; j < x.Length; j++)
x[j] = r[j] * 10;
}
var result = "";
uint c = 0;
for(int i = pi.Length - 1; i >=0; i--)
{
pi[i] += c;
c = pi[i] / 10;
result = (pi[i] % 10).ToString() + result;
}
return result;
}
Update
I finally got around to fixing the "carry error" that happens after 35 digits. Page 6 of the linked document, in fact, specifically talks about what is going on here. I have tested the final version good to 1000 digits.
Math.Round(Math.PI, places)
If you need more precision you will have trouble using the double data type as it supports a certain max. precision (which is provided by Math.PI).
After much searching I found this little snippet:
public static class BigMath
{
// digits = number of digits to calculate;
// iterations = accuracy (higher the number the more accurate it will be and the longer it will take.)
public static BigInteger GetPi(int digits, int iterations)
{
return 16 * ArcTan1OverX(5, digits).ElementAt(iterations)
- 4 * ArcTan1OverX(239, digits).ElementAt(iterations);
}
//arctan(x) = x - x^3/3 + x^5/5 - x^7/7 + x^9/9 - ...
public static IEnumerable<BigInteger> ArcTan1OverX(int x, int digits)
{
var mag = BigInteger.Pow(10, digits);
var sum = BigInteger.Zero;
bool sign = true;
for (int i = 1; true; i += 2)
{
var cur = mag / (BigInteger.Pow(x, i) * i);
if (sign)
{
sum += cur;
}
else
{
sum -= cur;
}
yield return sum;
sign = !sign;
}
}
}
It is working like a charm so far. You just have to add the System.Numerics library from the GAC to resolve the BigInteger type.
Same algorithm as nicholas but uses yield for lazy evaluation
static public IEnumerable<uint> Pi()
{
uint[] x = new uint[short.MaxValue];
uint[] r = new uint[short.MaxValue];
for (int j = 0; j < short.MaxValue; j++)
x[j] = 20;
for (int i = 0; i < short.MaxValue; i++)
{
uint carry = 0;
for (int j = 0; j < x.Length; j++)
{
uint num = (uint)(x.Length - j - 1);
uint dem = num * 2 + 1;
x[j] += carry;
uint q = x[j] / dem;
r[j] = x[j] % dem;
carry = q * num;
}
yield return (x[x.Length - 1] / 10);
r[x.Length - 1] = x[x.Length - 1] % 10; ;
for (int j = 0; j < x.Length; j++)
{
x[j] = r[j] * 10;
}
}
}
I used short.MaxValue as the upper bound for the number of places but that is because my machine is low on virtual memory. A better machine should be able to accommodate up to int.MaxValue.
The function can be called like so:
class Program
{
static void Main(string[] args)
{
foreach (uint digit in Calculator.Pi().Take(100))
{
Console.WriteLine(digit);
}
Console.Read();
}
}
If you are satisfied with the number of digits provided by the native math library, then it is simple; just round to the desired number of digits. If you need more digits (dozens, or hundreds, or thousands), you need a spigot algorithm that spits out the digits one at a time. Jeremy Gibbons gives an algorithm which I implement twice at my blog, where you will find code in Scheme, C, Python, Haskell, Perl and Forth (but not C#, sorry).
The easiest way is to store a large number of digits pi in a String constant. Then whenever you need n digits of precision, you just take a substring from 0 to n+2.