Get the factorial of a number without using multiplication - c

I need to compute the factorial of a number without using the multiplication operator. Because of this restriction, I directly tried to use repeated addition. It kind of works. However, my program is struggling to get the factorial of larger numbers. Is there a better way to solve the problem?
Here is my code:
void main(){
unsigned long num = 0, ans = 1, temp = 1;
printf("Enter a number: ");
scanf("%lu", &num);
while (temp <= num){
int temp2 = 0, ctr = 0;
while (ctr != temp){
temp2 += ans;
ctr ++;
}
ans = temp2;
temp ++;
}
printf("%lu! is %lu\n", num, ans);
}

You can implement a faster (than repeated addition) multiply function using bit shifts and addition to perform "long multiplication" in binary.
unsigned long long mul_ull(unsigned long long a, unsigned long long b)
{
unsigned long long product = 0;
unsigned int shift = 0;
while (b)
{
if (b & 1)
{
product += a << shift;
}
shift++;
b >>= 1;
}
return product;
}
EDIT: Alternative implementation of the above using single bit shifts and addition:
unsigned long long mul_ull(unsigned long long a, unsigned long long b)
{
unsigned long long product = 0;
while (b)
{
if (b & 1)
{
product += a;
}
a <<= 1;
b >>= 1;
}
return product;
}
In practice, whether or not this is faster than repeated addition depends on any optimizations done by the compiler. An optimizing compiler could analyze the repeated addition and replace it with a multiplication. An optimizing compiler could also analyze the code of the mul_ull function above and replace it with a multiplication, but that may be harder for the optimizer to spot. So in practice, it is perfectly reasonable for the repeated addition algorithm to end up faster than the bit-shift and addition algorithm after optimization!
Also, the above implementations of the mul_ull functions will tend to perform better if the second parameter b is the smaller of the numbers being multiplied when the one of the numbers is much larger than the other (as is typical for a factorial calculation). The execution time is roughly proportional to the log of b (when b is non-zero) but also depends on the number of 1-bits in the binary value of b. So for the factorial calculation, put the old running product in the first parameter a and the new factor in the second parameter b.
A factorial function using the above multiplication function:
unsigned long long factorial(unsigned int n)
{
unsigned long long fac = 1;
unsigned int i;
for (i = 2; i <= n; i++)
{
fac = mul_ull(fac, i);
}
return fac;
}
The above factorial function is likely to produce an incorrect result for n > 20 due to arithmetic overflow. 66 bits are required to represent 21! but unsigned long long is only required to be 64 bits wide (and that is typically the actual width for most implementations).

For large values of n, a big format is needed.
As you cannot use multiplications, it seems logical that you must implement it yourself.
In practice, as only additions are needed, it is not so difficult to implement, if we are not looking for a high efficiency.
A little difficulty anyway : you have to convert the input integer in an array of digits.
As modulo is not allowed I guess, I implemented it with the help of snprintf function.
Result:
100! is 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
Note: this result is provided about instantaneously.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NDIGITS 1000 // maximum number of digits
struct MyBig {
int digits[NDIGITS + 2]; // "+2" to ease overflow control
int degree;
};
void reset (struct MyBig *big) {
big->degree = 0;
for (int i = 0; i <= NDIGITS; ++i) big->digits[i] = 0;
}
void create_with_div (struct MyBig *big, int n) { // not used here
reset (big);
while (n != 0) {
big->digits[big->degree++] = n%10;
n /= 10;
}
if (big->degree != 0) big->degree--;
}
void create (struct MyBig *big, int n) {
const int ND = 21;
char dig[ND];
snprintf (dig, ND, "%d", n);
int length = strlen (dig);
reset (big);
big->degree = length - 1;
for (int i = 0; i < length; i++) {
big->digits[i] = dig[length - 1 - i] - '0';
}
}
void print (struct MyBig *big) {
for (int i = big->degree; i >= 0; --i) {
printf ("%d", big->digits[i]);
}
}
void accumul (struct MyBig *a, struct MyBig *b) {
int carry_out = 0;
for (int i = 0; i <= b->degree; ++i) {
int sum = carry_out + a->digits[i] + b->digits[i];
if (sum >= 10) {
carry_out = 1;
a->digits[i] = sum - 10;
} else {
carry_out = 0;
a->digits[i] = sum;
}
}
int degree = b->degree;
while (carry_out != 0) {
degree++;
int sum = carry_out + a->digits[degree];
carry_out = sum/10;
a->digits[degree] = sum % 10;
}
if (a->degree < degree) a->degree = degree;
if (degree > NDIGITS) {
printf ("OVERFLOW!!\n");
exit (1);
}
}
void copy (struct MyBig *a, struct MyBig *b) {
reset (a);
a->degree = b->degree;
for (int i = 0; i <= a->degree; ++i) {
a->digits[i] = b->digits[i];
}
}
void fact_big (struct MyBig *ans, unsigned int num) {
create (ans, 1);
int temp = 1;
while (temp <= num){
int ctr = 0;
struct MyBig temp2;
reset (&temp2);
while (ctr != temp){
accumul (&temp2, ans);
ctr ++;
}
copy (ans, &temp2);
temp ++;
}
return;
}
unsigned long long int fact (unsigned int num) {
unsigned long long int ans = 1;
int temp = 1;
while (temp <= num){
int ctr = 0;
unsigned long long int temp2 = 0;
while (ctr != temp){
temp2 += ans;
ctr ++;
}
ans = temp2;
temp ++;
}
return ans;
}
void main(){
unsigned long long int ans;
unsigned int num;
printf("Enter a number: ");
scanf("%u", &num);
ans = fact (num);
printf("%u! is %llu\n", num, ans);
struct MyBig fact;
fact_big (&fact, num);
printf("%u! is ", num);
print (&fact);
printf ("\n");
}

Related

general method to adapt all tail recursive algorithm to an iterative (or the opposite)

During a functional programming course, the professor explains to us that tails recursions calls could be considered as while loops calls (in a functional programming language):
ex:
this while loop:
void loopWhile(long long unsigned int n) {
long long unsigned int i = 0;
while (i <= n) {
printf("%llu\n", i);
i++;
}
printf("\nFinish !!!\n");
}
could be equivalent to:
void loopWhileRec(long long unsigned int n, long long unsigned int acc) {
if (n == 0) {
printf("%llu\n", acc);
printf("\nFinish !!!\n");
}
else {
printf("%llu\n", acc);
loopWhileRec(n-1, acc+1);
}
}
with acc=0.
So, with this thinking, it's possible to adapt some recursive algorithms to iterative version:
e.g:
level 1: factorial:
long long unsigned int factRec(long long unsigned int n, long long unsigned int res) {
if (n == 0 || n == 1) {
return res;
}
else {
return factRec(n-1, n*res);
}
}
with res = 1
method: replace argument res as a variable to multiply by i (of the for or while loop) and return the result:
long long unsigned int factIter(long long unsigned int n) {
long long unsigned int res = 1;
for(int i = 2; i <= n; i++) {
res *= i;
}
return res;
}
level 2: fibonacci:
In these recursive version, there are more arguments:
unsigned int fiboRec(unsigned int n, unsigned int acc, unsigned int prev) {
if (n == 0) {
return acc;
}
else {
return fiboRec(n-1, prev+acc, acc);
}
}
with acc = 0 and prev = 1.
To realize the iterative version, we just need to replace arguments acc and prev by variables:
long long unsigned int fibo(long long unsigned int n) {
long long unsigned int acc = 0;
long long unsigned int prev = 1;
long long unsigned int temp = 0;
for(int i = 0; i < n; i++) {
temp = acc;
acc += prev;
prev = temp;
}
return acc;
}
the temp argument is used to get the previous content of acc, before the re-assignation to prev+acc. And we returns acc variable to get the result.
level 3: power function (my current problem):
In a functional programming book, I learned this function to compute x^n with a logarithmic time complexity:
unsigned int power(unsigned int x, unsigned int n, unsigned int acc) {
if (n == 0) {
return acc;
}
else if (n % 2 == 0) {
return power(x*x, n/2, acc);
}
else {
return power(x*x, (n-1)/2, x*acc);
}
}
with acc = 1 at the beginning.
I would like to find a way to implement this tail recursive version to an iterative algorithm,more specifically, I would like to know a more general method that could work here, not just an algorithm already written.
So, I know I should to declare res = 0 to start,
but in the for / loop while, I don't know exactly how I should to do because all variables during recursive process are modified (x = x*x, n = n/2 or (n-1)/2 ...).
For the moment, I realized that, but it's not working:
long long unsigned int powerIter(long long unsigned int x, long long unsigned int n) {
long long unsigned int acc = 1;
long long unsigned int i = 0;
long long unsigned int temp = 0;
while (i < n) {
if (i % 2 == 0) {
x *= x;
i /= 2;
}
else {
temp = x;
x *= x;
i = (i-1)/2;
acc *= temp;
}
i++;
}
return acc;
}
I just was wondering if I need to add different variables, or if it's possible to find an other way to code that.
This could be useful in languages with recursion limits.

How to switch 2nd and 4th digit(before comma) in a double? C programming

So lets say the input is 45392.56, the output has to be 49352.56.
How can i program this in C?
#include <stdio.h>
#include <stdlib.h>
int dotPos(char arr[]) {
int i = 0;
while (arr[++i] != '.');
return i;
}
int main() {
double d = 45392.56;
int MAX = 100;
char arr[MAX];
sprintf(arr, "%f", d);
if (dotPos(arr) > 3) {
char aux = arr[1];
arr[1] = arr[3];
arr[3] = aux;
}
d = atof(arr);
printf("%.2f\n", d);
}
Output:
49352.56
Convert the number to a character array. Look at the sprintf function.
Swap the positions of the characters.
Convert the character array to double. Look at the atof function.
Avoiding conversion to string and back, take the integral part of the number, find the two values in position 1 and 3 (in decimal notation), and compute the value to add or substract to/from the original double.
this is (a-b) *pow(10,hipos) - (a-b) * pow(10,lopos)
#include <stdio.h>
long finddiff(unsigned long val, unsigned lpos, unsigned rpos);
int main(void) {
double d = 45392.56;
unsigned long u;
long dif;
u = d;
dif = finddiff(u,3,1);
d += dif;
printf("%.2f\n", d);
return 0;
}
long finddiff(unsigned long val, unsigned lpos, unsigned rpos)
{
long res;
unsigned pos, ll, rr;
if (lpos < rpos) return finddiff(val, rpos,lpos);
for (pos=0; pos < rpos; pos++) { val /= 10; }
rr = val %10;
for (; pos < lpos; pos++) { val /= 10; }
ll = val %10;
// fprintf(stderr, "%u,%u\n", ll,rr);
res = rr-ll;
for (; pos > rpos; pos--) { res *= 10; }
res -= rr-ll;
for (; pos > 0; pos--) { res *= 10; }
// fprintf(stderr, "%u,%u,%ld\n", ll,rr, res);
if (ll > rr) res = -res;
else if (rr > ll) {;}
else res = 0;
return res;
}
BTW: this will fail miserably for values whose integer part is larger than the maximum log int, eg 6.3E23 .
For negative numbers some additional logic should be added.

What is the fastest way to list the elements of the unit group of a given size?

There are several fast algorithms to calculate prime numbers up to a given number n. But, what is the fastest implementation to list all the numbers r relatively prime to some number n in C? That is, find all the elements of the multiplicative group with n elements as efficiently as possible in C. In particular, I am interested in the case where n is a primorial.
The n primorial is like the factorial except only prime numbers are multiplied together and all other numbers are ignored. So, for example 12 primorial would be 12#=11*7*5*3*2.
My current implementation is very naive. I hard code the first 3 groups as arrays and use those to create the larger ones. Is there something faster?
#include "stdafx.h"
#include <stdio.h> /* printf, fgets */
#include <stdlib.h> /* atoi */
#include <math.h>
int IsPrime(unsigned int number)
{
if (number <= 1) return 0; // zero and one are not prime
unsigned int i;
unsigned int max=sqrt(number)+.5;
for (i = 2; i<= max; i++)
{
if (number % i == 0) return 0;
}
return 1;
}
unsigned long long primorial( int Primes[], int size)
{
unsigned long long answer = 1;
for (int k = 0;k < size;k++)
{
answer *= Primes[k];
}
return answer;
}
unsigned long long EulerPhi(int Primes[], int size)
{
unsigned long long answer = 1;
for (int k = 0;k < size;k++)
{
answer *= Primes[k]-1;
}
return answer;
}
int gcd( unsigned long long a, unsigned long long b)
{
while (b != 0)
{
a %= b;
a ^= b;
b ^= a;
a ^= b;
}
//Return whethere a is relatively prime to b
if (a > 1)
{
return false;
}
return true;
}
void gen( unsigned long long *Gx, unsigned int primor, int *G3)
{
//Get the magic numbers
register int Blocks = 30; //5 primorial=30.
unsigned long long indexTracker = 0;
//Find elements using G3
for (unsigned long long offset = 0; offset < primor; offset+=Blocks)
{
for (int j = 0; j < 8;j++) //The 8 comes from EulerPhi(2*3*5=30)
{
if (gcd(offset + G3[j], primor))
{
Gx[indexTracker] = offset + G3[j];
indexTracker++;
}
}
}
}
int main(int argc, char **argv)
{
//Hardcoded values
int G1[] = {1};
int G2[] = {1,5};
int G3[] = {1,7,11,13,17,19,23,29};
//Lazy input checking. The world might come to an end
//when unexpected parameters given. Its okey, we will live.
if (argc <= 1) {
printf("Nothing done.");
return 0;
}
//Convert argument to integer
unsigned int N = atoi(argv[1]);
//Known values
if (N <= 2 )
{
printf("{1}");
return 0;
}
else if (N<=4)
{
printf("{1,5}");
return 0;
}
else if (N <=6)
{
printf("{1,7,11,13,17,19,23,29}");
return 0;
}
//Hardcoded for simplicity, also this primorial is ginarmous as it is.
int Primes[50] = {0};
int counter = 0;
//Find all primes less than N.
for (int a = 2; a <= N; a++)
{
if (IsPrime(a))
{
Primes[counter] = a;
printf("\n Prime: : %i \n", a);
counter++;
}
}
//Get the group size
unsigned long long MAXELEMENT = primorial(Primes, counter);
unsigned long long Gsize = EulerPhi(Primes, counter);
printf("\n GSize: %llu \n", Gsize);
printf("\n GSize: %llu \n", Gsize);
//Create the list to hold the values
unsigned long long *GROUP = (unsigned long long *) calloc(Gsize, sizeof(unsigned long long));
//Populate the list
gen( GROUP, MAXELEMENT, G3);
//Print values
printf("{");
for (unsigned long long k = 0; k < Gsize;k++)
{
printf("%llu,", GROUP[k]);
}
printf("}");
return 0;
}
If you are looking for a faster prime number check, here is one that is reasonably fast and eliminates all calls to computationally intensive functions (e.g. sqrt, etc..)
int isprime (int v)
{
int i;
if (v < 0) v = -v; /* insure v non-negative */
if (v < 2 || !((unsigned)v & 1)) /* 0, 1 + even > 2 are not prime */
return 0;
for (i = 2; i * i <= v; i++)
if (v % i == 0)
return 0;
return 1;
}
(note: You can adjust the type as required if you are looking for numbers above the standard int range.)
Give it a try and let me know how it compares to the once you are currently using.

First time I have ever gotten a floating point exception and I have no idea what to do

I have to create a program that jumbles up numbers in a certain order, I know my code is probably not the greatest, but I have a floating point exception and I have no idea why, any help would be appreciated
#define DIV 10
long long int inputNum();
int checkLength(long long int);
int even(int, long long int);
int odd(int, long long int);
long long int calcNewNum(int, long long int);
void print(long long int, long long int);
int main()
{
long long int input = 0;
int length = 0;
int check = 0;
int finalNum = 0;
input = inputNum();
length = checkLength(input);
check = odd(length, input);
finalNum = calcNewNum(length, input);
print(input, finalNum);
return(0);
}
long long int inputNum()
{
long long int input = 0;
do{
printf("Enter your non-negative integer: ");
scanf("%lld", &input);
if(input < 0)
{
printf("Error! Non-negative integers only!!\n");
}
}while(input < 0);
return(input);
}
int checkLength(long long int input)
{
int ct = 0;
do{
input /= DIV;
ct++;
}while(input != 0);
return(ct);
}
int even(int length, long long int input)
{
int digitOne = 0;
int digitTwo = 0;
int i;
int divideOne = 0;
int firstNum = 0;
int secondNum = 0;
int finalNum = 0;
digitOne = length / 2;
digitTwo = (length / 2) + 1;
divideOne = length - digitTwo;
for(i = 0; i < divideOne; i++)
{
input /= DIV;
}
secondNum = input % DIV;
input /= DIV;
firstNum = input % DIV;
if(firstNum < secondNum)
{
finalNum = firstNum;
}
else
{
finalNum = secondNum;
}
return(finalNum);
}
int odd(int length, long long int input)
{
int digit = 0;
int i;
int divide = 0;
int midNum = 0;
digit = length / 2;
divide = length - digit;
for(i = 0; i < digit; i++)
{
input /= DIV;
}
midNum = input % DIV;
return(midNum);
}
long long int calcNewNum(int length, long long int input)
{
int finalNum = 0;
long long int holder = 0;
int ct = 0;
int singleNum = 0;
long long int temp = 0;
holder = input;
ct = length;
if(input == 0)
{
finalNum = 0;
}
if(input / 10 == 0)
{
finalNum = input;
}
holder = input;
while(holder > 0)
{
if(holder % 2 == 0)
{
singleNum = even(length, holder);
length--;
}
if(holder % 2 == 1)
{
singleNum = odd(length, holder);
length--;
}
temp = holder % (long long int)pow(DIV,ct - 1);
holder /= pow(DIV, ct - 1);
holder *= pow(DIV, ct - 2);
holder += temp;
ct--;
finalNum += singleNum;
printf("%lld", holder);
if(holder != 0)
{
finalNum *= DIV;
}
}
return(finalNum);
}
void print(long long int input, long long int finalNum)
{
printf("Original Input: %lld", input);
printf("Altered Number: %lld", finalNum);
}
Greg in the comments above was right - the error happens at line 164, it's a divide by zero error when the variable ct is 0. In that line, you're dividing by 10 to the power ct-1 which will be 10^(-1) there. So pow() returns .1 and since you cast it as long long int, the decimal is cut off and it tries to divide by 0.
Also this error seems to only occur when the sum of the digits in the input number is greater than or equal to ten. I didn't go over the whole program to figure out why that is. What exactly is the goal of the program?
OK, as others mentioned, for an input which sum of numbers is greater than or equal to 10, at line
temp = holder % (long long int)pow(DIV,ct - 1);
the right part of the modulo
(long long int)pow(DIV,ct - 1);
returns 0. Therefore the modulo operation overflows (divide by 0).
And by the way, it returns 0 because somehow your code reaches ct=0, that is, your are trying to calculate 10^{-1}; this corresponds to the decimal number 0.1 which is rounded to 0 in integer type.
I don't know what you're code's doing, but it has a bug :D
Problem is here
temp = holder % (long long int)pow(DIV,ct - 1);
Its always returning some negative value so temp will always be same as the number that you have entered. So this
holder /= pow(DIV, ct - 1);
will always make holder as 0 and holder += temp; will always make holder as the number tha tyou have entered.
while(holder > 0) will always be true and it will run infinitely.
Check pow(). Its signature is double pow(double x, double y) and you are using DIV. That could be the issue.

To find factorial of 500 and store it in a variable...and perform calculations...How to store such a huge number?

how do i store a huge number in a variable (i) and wont need to change much of the program ?
Is there a available datatype to store factorial of 100 for example ?
#include<stdio.h>
#include<conio.h>
void main()
{
long long int i = 1;
long long int sum = 0;
long long int j = 0;
long long int digit = 0;
for(j = 500; j >= 1; j--)
{
i = i * j;
}
printf("%lld", i);
while(i > 0)
{
digit = i%10;
i = i/10;
sum = sum + digit;
}
printf("\n%lld", sum);
getch();
}
There is no built-in language support for such large numbers. You have two options:
if you can, use existing library, like GMP
implement you own solution
If you decide to take the second path, you might want to consider storing digits (not necesserily decimal) in an array, and perform arithmetic operations using well known school algorithms. Keep in mind it will be (probably considerably) less efficient than heavily optimized library code.
#Marcin Łoś is on the money, no C solution without using a library or rolling your own functions.
Follows is a fun, but not imaginative solution where the large number is stored as a array of char (in reverse order).
#include <stdio.h>
#include <string.h>
#include <math.h>
void Mult(char *BigNum, unsigned Factor) {
unsigned Accumulator = 0;
char Digit;
while ((Digit = *BigNum) != '\0') {
Accumulator += ((unsigned)(Digit - '0')) * Factor;
*BigNum++ = Accumulator%10 + '0';
Accumulator /= 10;
}
while (Accumulator > 0) {
*BigNum++ = Accumulator%10 + '0';
Accumulator /= 10;
}
*BigNum = '\0';
}
int main(){
unsigned N = 500;
unsigned Factor;
char BigNum[(size_t) (N*log(N) + 2)]; // Form answer, in reverse order, as a string
strcpy(BigNum, "1");
for (Factor = 1; Factor <= N; Factor++) {
Mult(BigNum, Factor);
}
printf("%u! Length:%zu Reverse:\"%s\"\n", Factor - 1, strlen(BigNum), BigNum);
unsigned long Sum = 0;
size_t i;
for (i=0; BigNum[i]; i++) {
Sum += BigNum[i] - '0';
}
printf("Sum of digits:%lu\n", Sum);
return 0;
}
500! Length:1135 Reverse:"000...221"
Sum of digits:4599

Resources