How to handle Integer overflow when calculating factorial > 31 - c

The iterative function returns the result of a factorial operation. The code seems to break after I try to compute a number that will result in an integer overflow. How could I best handle this? Would it make sense and is it accurate? to store every iteration over the maximum limit as a power of and return the limit plus a character string describing the amount of times it can be multiplied by itself?
int ft_iterative_factorial(int nb)
{
int i;
int n;
int res;
i = 1;
n = nb;
res = nb;
while (i < nb)
{
if (nb == 1 || nb == 0)
{
res = 1;
break ;
}
res = res * (n - 1);
i++;
n--;
}
return ((nb < 0 || nb > 31) ? 0 : res);
}

Your function is really complicated.
Consider rather this implementation:
int ft_iterative_factorial(int nb)
{
int res = 1;
for (int i = 2; i <= nb; i++)
{
res = res * i;
}
return res;
}
Your test return ( nb < 0 ? 0 : res); doesn't make much sense after the loop, you should do it before the loop, and nor does if (nb == 1 || nb == 0) inside the loop. But these tests are pointless anyway in my code.
int is probably a 32 bit type and 32 bits is not enough to store 16!.
Either use long long (usually 64 bit) instead of int (but then you'd be limited at 21 or so), or handle cases where value >16 otherwise.
BTW: if you really want to be fast, don't calculate the factorial but use a lookup table, this is left as an exercise to the reader.

Either use a long long or try to optimise your computations if possible.
At last, an alternative is to search for big integer libraries.

You are using signed integers to compute and a signed integer overflow is undefined behaviour. So whatever your code returns it correct according to the C standard. What usually happens is that you simply get the lower bits of the right result. Which, since it's signed int, can be negative.
If you only want to get an approximate result for large numbers then why not change your code to use double? For small numbers like 3! you would still get 6 but past 17 or so you get something like 4.643+E8, meaning 4.643 * 10^8. The double type will eventually run out of exponents but it gets you a lot further than even unsigned long long.

For capable maximum factorial, you can use unsigned long long for return type of this function. And your function is recursive style, the running time is slower then non-recursive style.
I think here is a good solution
unsigned long long ft_iterative_factorial(int nb)
{
unsigned long long result = 1;
for (int i = 2; i <= nb; i++)
{
result = result * (unsigned long long)i;
}
return result;
}
int main()
{
cout << ft_iterative_factorial(17) << endl;
return 0;
}

Related

How often is a number divisible without a rest?

I am currently trying to write a method which checks how often a number is divisible by 5 with a rest of 0 (e.g. 25 is two times; 125 is three times).
I thought my code is correct but it always states that it is possible one more time than it actually is (e.g. 25 is three times; wrong).
My approach is the following:
int main()
{
div_t o;
int inp = 25, i = 0;
while(o.rem == 0){
o = div(inp, 5);
inp = o.quot;
i++
}
return 0;
}
I debugged the code already and figured that the issue is that it steps once more into the loop even though the rest is bigger 0. Why is that? I can't really wrap my head around it.
First: 25/5 = 5; Rest = 0;
Second: 5/5 = 1; Rest = 1; - Shouldn't it stop here?
Third: 1/5 = 0; Rest = 1;
Ah... got it. The point where the remainder is 0 is reached when the division is done with the number which results in a rest bigger zero which is after i got increased.
What is the cleanest approach to fix that? i -= 1 seems kinda like a workaround and I wanted to avoid using an if to break
You're using div() to do the division, which I had to look up to verify that it's part of the standard. I think it's kind of rarely used, and more suited for cases where you really care about performance. This doesn't seem like such a case, and so I think it's a bit obscure.
Anyhow, here's how I would expect it to look, without div():
#include <stdio.h>
unsigned int count_factors(unsigned int n, unsigned int factor)
{
unsigned int count = 0;
for(; n >= factor; ++count)
{
const int remainder = n % factor;
if(remainder != 0)
break;
n /= factor;
}
return count;
}
int main(void) {
printf("%u\n", count_factors(17, 5));
printf("%u\n", count_factors(25, 5));
printf("%u\n", count_factors(125, 5));
return 0;
}
This prints:
0
2
3
Change the while loop condition in :
while(o.rem == 0 && inp >= 5)
In this way your division will stop after that you are inspecting the number 5.
A suggestion: use a const variable to wrap the 5 ;)
As far as I understand you want to know whether the input is an integer power of 5 (or in general whether v == N^x) and if it is, you want to calculate and return the power (aka x). Otherwise return 0. This is more or less a logN function except that it requires integer results.
I would go for code like this:
#include <stdio.h>
unsigned int logN_special(unsigned int v, unsigned int n)
{
unsigned int r = 0;
if (n == 0) return 0; // Illegal
if (n == 1) return 0; // Illegal
if (v < n) return 0; // Will always give zero
if (n*(v/n) != v) return 0; // Make sure that v = n^x
// Find the x
while(v != 1)
{
v /= n;
++r;
}
return r;
}

number of digits common between 2 binary numbers

I was writing a program that counts the number of bits in common between the two binary representations of the given numbers. The code I have written is:
int common_bits(int a, int b) {
static long binaryNo1,binaryNo2,remainder1,remainder2,factor = 1;
if(a!= 0&&b!=0){
remainder1 = a % 2;
binaryNo1 = remainder1 * factor;
remainder2 = b % 2;
binaryNo2 = remainder2 * factor;
factor = factor * 10;
if (binaryNo2==binaryNo1)
{
int count=0;
count++;
}
common_bits(a/2,b/2);
}
return 0;
}
I have been facing error with this could anyone explain why and tell me how to correct it.
An example of how this works is: 13 (1101 in binary) and 7 (111 in binary) have 2 bits in common
thanks in advance.
First, let's fix your program: your code does not return anything after the recursive invocation, multiplies by a factor that is not necessary, uses a factor of 10k instead of 2k, and uses recursion that is not necessary. The fix is reasonably simple:
remainder1 = a % 2;
remainder2 = b % 2;
int count = 0;
if (remainder1 == remainder2) {
count++;
}
return count + common_bits(a/2, b/2);
You don't need to build the numeric value of treating the binary string of digits as if they were decimal digits, which is where just about all your problems are coming in. Well, it's not actually that idea causing your problems, but the poor style of the code you used to try to implement the idea. static variables are bad, particularly with recursion. Failing to return a value is bad too.
This is enough:
int common_bits(int a, int b)
{
if (a == 0) return 0;
if (b == 0) return 0;
return ((a&1) == (b&1)) + common_bits(a/2, b/2);
}
It works because a&1 gets the lowest bit of a, and == evaluates to one when the two operands are equal, zero otherwise.
Or you could use XNOR, sometimes also called bitwise EQV:
return ((a^~b)&1) + common_bits(a/2, b/2);

High-precision program that calculates 2^n

I'm building a program in C that can get powers of 2. The user inputs the value of n, and the program calculates 2^n.
Here's the code.
The problem comes when I input 100
What I am getting:
1,267,650,600,228,229,400,000,000,000,000
What I should get
1,267,650,600,228,229,401,496,703,205,376
It has to be coded entirely in ANSI C. Any ideas on how to increase the precision? The maximum value of N has to be 256 (256 bits, I imagine, which means the maximum output should be 2^256).
What I'm lacking here is precision, and I don't know how to fix that. Any ideas?
I think it's easiest if you work in base 10 from the start. This is because while calculating powers of 2 in binary is trivial, the conversion back to base 10 is a lot harder.
If you have an array of base 10 digits1, you only need to implement base 10 addition with carry to be able to multiply by 2 (by adding the number to itself). Do that n times in a loop and you have your answer.
If you wish to support higher exponents, you can also look into implementing exponentiation by squaring, but that's harder, since you'll need general multiplication, not just by 2 for that.
1 Tip: It's more convenient if you store the digits in reverse order.
Here is my quick and dirty implementation of hammar's approach., storing the decimal number as a C string with the digits in reverse order.
Run the code on ideone
void doubleDecimal(char * decimal)
{
char buffer[256] = "";
char c;
unsigned char d, carry = 0;
int i = 0;
while (c = decimal[i])
{
d = 2 * (c - '0') + carry;
buffer[i] = (d % 10) + '0';
carry = d / 10;
i++;
}
if (carry > 0)
buffer[i++] = (carry % 10) + '0';
buffer[i] = '\0';
strncpy(decimal, buffer, 256);
}
void reverse(char * str)
{
int i = 0;
int j = strlen(str) - 1;
while (j > i)
{
char tmp = str[i];
str[i] = str[j];
str[j] = tmp;
i++;
j--;
}
}
int main(void)
{
char decimal[256] = "1";
int i;
for (i = 0; i < 100; i++)
doubleDecimal(decimal);
reverse(decimal);
printf("%s", decimal);
return 0;
}
Output:
1267650600228229401496703205376
double is a (probably) 64bit value. You can't store 256 bits of precision in 64 bits. The reason that you are getting a number that is sort of close is because floating point numbers are stored with varying precision -- not all sequential numbers can be represented, but you can represent very large numbers. Pretty useless in this case.
What you want is either to use an arbitrary precision library or, since this is probably homework, you are expected to write your own.
A typical double, using 64-bit IEEE 754, has about 51 bits precision, IIRC.
Most probably the point of supporting exponents up to 256 is to exceed that precision, and also the precision of a long double or long long, so that you have to do things yourself.
As a homework exercise, then,
Store decimal digit values in an array + a digit count
Implement doubling of the value in such array + count
Start with 1 and double value appropriate number of times.
A few things you'll want to think about to solve this:
You are only dealing with integers so you should use an integer
representation (you will need to roll your own because you can't use
long long which is "only" 64 bits long).
Powers of 2 you say -how convenient - computers store numbers using powers of 2 (you'll
only need to use shift operations and bit fiddling .... no
multiplications will be needed).
How can you convert a base 2 number to a base 10 number for display purposes (think of division and outputting one number at a time (think about what a hardware divisor does in order to get the bit manipulations correct).
You can't the store 256 bits of precision in 64 bits. Reason that you are getting a number to close is because floating point numbers are stored with varying precision. To all sequential numbers can be represented, but you can represent very large numbers. Pretty useless in this case.
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//constants
#define MAX_DIGITS 1000
//big integer number struct
struct bigint {
char Digits[MAX_DIGITS];
};
//assign a value
void assign(struct bigint* Number,int Value) {
if (Value!=1) {
printf("Can not assign value other than 1\n");
exit(0);
}
memset(Number,0,sizeof(bigint));
Number->Digits[0] = Value;
}
//multiply the big integer number with value
void multiply(struct bigint* Number,int Value) {
int Digit,New_Digit;
int Carry = 0;
for (int Index=0; Index<MAX_DIGITS; Index++) {
Digit = Number->Digits[Index];
New_Digit = Digit*Value%10;
if (New_Digit+Carry<10) {
New_Digit = New_Digit+Carry;
Carry = Digit*Value/10;
}
else {
New_Digit = (New_Digit+Carry)%10;
Carry = (Digit*Value/10)+1;
}
//set the new digit
Number->Digits[Index] = New_Digit;
}//for loop
}
//print out the value of big integer type
void print(struct bigint* Number) {
int Index = MAX_DIGITS-1;
while (Number->Digits[Index]==0 && Index>=0)
Index--;
//the big integer value is zero
if (Index==-1) {
printf("0");
return;
}
while (Index>=0) {
printf("%u",Number->Digits[Index]);
Index--;
}
}
//main programme entry point
int main(int Argc,char** Args) {
int Power = 100;
struct bigint Number;
//assign the initial value
assign(&Number,1);
//do the multiplication
for (int Index=0; Index<Power; Index++)
multiply(&Number,2);
//print result
print(&Number);
getch();
}
//END-OF-FILE

Converting int to int[] in 'C'

I basically want to convert a given int number and store individual digits in an array for further processing.
I know I can use % and get each digit and store it. But the thing is if I do not know the number of digits of the int till runtime and hence I cannot allocate the size of the array. So, I cannot work backwards (from the units place).
I also do not want to first store the number backwords in an array and then again reverse the array.
Is there any other way of getting about doing this?
Eg: int num = 12345;
OUTPUT: ar[0] = 1, ar[1] = 2 and so on, where ar[] is an int array.
Convert is probably not the right word. You can take the int, dynamically allocate a new int[], and then store the digits of the int into the int[]. I'm using log base 10 to calculate how many digits num has. Include math.h to use it. The following code is untested, but will give you an idea of what to do.
int num = 12345;
int size = (int)(log10(num)+1);
// allocate array
int *digits = (int*)malloc(sizeof(int) * size);
// get digits
for(int i=size-1; i>=0; --i) {
digits[i] = num%10;
num=num/10; // integer division
}
The easiest way is to calculate number of digits to know the size of an array you need
int input = <input number>; // >= 0
int d, numdigits = 1;
int *arr;
d = input;
while (d /= 10)
numdigits++;
arr = malloc(sizeof(int) * numdigits);
There's even easier way: probably you pass a number to your program as an argument from command line. In this case you receive it as a string in argp[N], so you can just call strlen(argp[N]) to determine number of digits in your number.
If you have a 32-bit integer type, the maximum value will be comprised of 10 digits at the most (excluding the sign for negative numbers). That could be your upper limit.
If you need to dynamically determine the minimum sufficient size, you can determine that with normal comparisons (since calling a logarithmic function is probably more expensive, but a possibility):
size = 10;
if (myint < 1000000000) size--;
if (myint < 100000000) size--;
/* ... */
Declaring the array to be of a dynamic size depends on the C language standard you are using. In C89 dynamic array sizes (based on values calculated during run-time) is not possible. You may need to use dynamically allocated memory.
HTH,
Johan
The following complete program shows one way to do this. It uses unsigned integers so as to not have to worry about converting - you didn't state what should happen for negative numbers so, like any good consultant, I made the problem disappear for my own convenience :-)
It basically works out the required size of an array and allocates it. The array itself has one element at the start specifying how many elements are in the array (a length int).
Each subsequent element is a digit in sequence. The main code below shows how to process it.
If it can't create the array, it'll just give you back NULL - you should also remember to free the memory passed back once you're done with it.
#include <stdio.h>
#include <stdlib.h>
int *convert (unsigned int num) {
unsigned int *ptr;
unsigned int digits = 0;
unsigned int temp = num;
// Figure out how many digits in the number.
if (temp == 0) {
digits = 1;
} else {
while (temp > 0) {
temp /= 10;
digits++;
}
}
// Allocate enough memory for length and digits.
ptr = malloc ((digits + 1) * sizeof (unsigned int));
// Populate array if we got one.
if (ptr != NULL) {
ptr[0] = digits;
for (temp = 0; temp < digits; temp++) {
ptr[digits - temp] = num % 10;
num /= 10;
}
}
return ptr;
}
That convert function above is the "meat" - it allocates an integer array to place the length (index 0) and digits (indexes 1 through N where N is the number of digits). The following was the test program I used.
int main (void) {
int i;
unsigned int num = 12345;
unsigned int *arr = convert (num);
if (arr == NULL) {
printf ("No memory\n");
} else {
// Length is index 0, rest are digits.
for (i = 1; i <= arr[0]; i++)
printf ("arr[%d] = %u\n", i, arr[i]);
free (arr);
}
return 0;
}
The output of this is:
arr[1] = 1
arr[2] = 2
arr[3] = 3
arr[4] = 4
arr[5] = 5
You can find out the number of digits by taking the base-10 logarithm and adding one. For that, you could use the log10 or log10f functions from the standard math library. This may be a bit slower, but it's probably the most exact as long as double has enough bits to exactly represent your number:
int numdigits = 1 + log10(num);
Alternatively, you could repeatedly divide by ten until the result is zero and count the digits that way.
Still another option is just to allocate enough room for the maximum number of digits the type can have. For a 32-bit integer, that'd be 10; for 64-bit, 20 should be enough. You can just zero the extra digits. Since that's not a lot of wasted space even in the worst case, it might be the simplest and fastest option. You'd have to know how many bits are in an int in your setup, though.
You can also estimate fairly well by allocating 3 digits for each 10 bits used, plus one. That should be enough digits unless the number of bits is ridiculously large (way above the number of digits any of the usual int types could have).
int numdigits = 1
unsigned int n = num;
for (n = num; n & 0x03ff; n >>= 10)
numdigits += 3;
/* numdigits is at least the needed number of digits, maybe up to 3 more */
This last one won't work (directly) if the number is negative.
What you basically want to do is to transform your integer to an array of its decimal positions. The printf family of functions perfectly knows how to do this, no need to reinvent the wheel. I am changing the assignment a bit since you didn't say anything about signs, and it simply makes more sense for unsigned values.
unsigned* res = 0;
size_t len = 0;
{
/* temporary array, large enough to hold the representation of any unsigned */
char positions[20] = { 0 };
sprintf(position, "%u", number);
len = strlen(position);
res = malloc(sizeof(unsigned[len]));
for (size_t i = 0; i < len; ++i)
res[i] = position[i] - '0';
}

find the "string length" of an int

basically I want to return the number of digits in the int -> values like this:
(int)1 => 1
(int)123 => 3
(int)12345678 => 8
I know nothing about C, so please bear with me. I know objective c, but I use ints and floats instead of NSNumbers. I realise I could convert the ints into objective c objects, but this seems faffy, and if I can do it with C I'll know it for the future.
Thanks
use
int d = (value == 0 ? 1 : (int)(log10(value)+1));
Note that this doesnt work for negative numbers, you'll have to use
int d = (value == 0 ? 1 : ((int)(log10(fabs(value))+1) + (value < 0 ? 1 : 0)));
which adds 1 for the minus sign, if value is negative.
Probably much faster than using log or int-to-string conversion and without using any library functions is this:
int nDigits(int i)
{
if (i < 0) i = -i;
if (i < 10) return 1;
if (i < 100) return 2;
if (i < 1000) return 3;
if (i < 10000) return 4;
if (i < 100000) return 5;
if (i < 1000000) return 6;
if (i < 10000000) return 7;
if (i < 100000000) return 8;
if (i < 1000000000) return 9;
return 10;
}
EDIT after Jeff Yates concerns:
For those who worry about int sizes different from 32-bits
(similar to pmg's solution but still faster because multiplication is faster than division :-)
#include <limits.h>
#define PO10_LIMIT (INT_MAX/10)
int nDigits(int i)
{
int n,po10;
if (i < 0) i = -i;
n=1;
po10=10;
while(i>=po10)
{
n++;
if (po10 > PO10_LIMIT) break;
po10*=10;
}
return n;
}
Use logarithms base 10:
int length = (int)floor(log10((float)number)) + 1; // works for >0
Here's another option
int nDigits(unsigned i) {
int n = 1;
while (i > 9) {
n++;
i /= 10;
}
return n;
}
This is faster than using log10, but slower than Curd's option with the cascading tests. However it doesn't assume ints are 32 bits :-)
A more general solution, especially if you want to know the length for purposes of printing with printf() variants is:
snprintf(NULL, 0, "%d", myint);
The return value should tell you the length of the string that would be printed.
If your integer value (e.g. 12345678u) is a compile-time constant, you can let the compiler determine the length for you:
template<typename T>
constexpr unsigned int_decimal_digits(T value)
{
return ( value / 10
? int_decimal_digits<T>(value/10) + 1
: 1 );
}
Usage:
unsigned n = int_decimal_digits(1234);
// n = 4
#include <limits.h>
unsigned m = int_decimal_digits(ULLONG_MAX);
// m = maximum length of a "long long unsigned" on your platform
This way, the compiler will compute the number of decimal places automatically, and fill in the value as a constant. It should be the fastest possible solution, because there is no run-time computation involved and integer constants are usually put into the instruction opcodes. (This means that they travel by instruction pipeline, not by data memory/cache.) However, this requires a compiler that supports C++11.

Resources