find the "string length" of an int - c

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.

Related

How to handle Integer overflow when calculating factorial > 31

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;
}

Converting integer to integer array in c [duplicate]

This question already has answers here:
How do I split an int into its digits?
(16 answers)
Closed 6 years ago.
How do I convert an integer value to integer array format?
For example:
int answer = 140;
and expected value that I wish to get is:
int arr_answer[] = { 1, 4, 0};
If you know the number of digits ahead of time (in this case 3), you can do it like this:
#include <stdio.h>
int main()
{
const int numDigits = 3;
int answer = 140;
int digits[numDigits];
int i = numDigits - 1;
while (answer > 0)
{
int digit = answer % 10;
answer /= 10;
digits[i] = digit;
printf("digits[%d] = %d\n", i, digits[i]);
i--;
}
return 0;
}
Output:
digits[2] = 0
digits[1] = 4
digits[0] = 1
One option is to count the digits and use a variable length array1:
#include <stdio.h>
int main(void){
int ans = 140;
int x = ans;
size_t i, size = 0;
while ( x ) {
x=x/10;
size++;
}
int arr_answer[size];
for ( i = size - 1, x = ans ; x ; x = x/10, i-- ) {
arr_answer[i] = x % 10;
}
for ( i=0 ; i < size ; i++ ) {
printf("%d ", arr_answer[i]);
}
}
Obviously, if you can use fixed size array which is sufficiently large, you don't need to calculate size and thus avoid the first loop.
But this is probably the only to make an exact size array. Alternatively, you can also use malloc() (if you don't need to use an array) to allocate a block of memory if the number of digits are potentially huge (and you'd need to store them differently as well - an int can hold limited range of values).
1 VLAs, which are available since C99, are optional feature in C11.
I'm not a C programmer, so I can't give specific code, but I'd try 1) integer to string conversion (Google says try sprintf()), 2) run a for loop for the length of your integer/string and assign to an array. I'd end up doing something like this:
integer_String = convertToString(integer)
for (integer_String.length()) {assign to array}
Probably nice to wrap it up in a function that returns the array.
EDIT: Disregard haha other answer is way better.

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);

Converting an int array to an int value in c

I have an integer array
int number[] = {1,2,3,4};
What can I do to get int x = 1234?
I need to have a c version of it.
x = 1000*number[0] + 100*number[1] + 10*number[2] + number[3];
This is basically how decimal numbers work. A more general version (when you don't know how long 'number' is) would be:
int x = 0;
int base = 10;
for(int ii = 0; ii < sizeof(number); ii++) x = base*x + number[ii];
Note - if base is something other than 10, the above code will still work. Of course, if you printed out x with the usual cout<<x, you would get a confusing answer. But it might serve you at some other time. Of course you would really want to check that number[ii] is between 0 and 9, inclusive - but that's pretty much implied by your question. Still - good programming requires checking, checking, and checking. I'm sure you can add that bit yourself, though.
You can think of how to "shift over" a number to the left by multiplying by ten. You can think of appending a digit by adding after a shift.
So you effectively end up with a loop where you do total *= 10 and then total += number[i]
Of course this only works if your array is digits, if it is characters you'll want to do number[i] - '0' and if it is in a different base you'll want to multiply by a different number (8 for instance if it is octal).
int i = 0, x = 0;
for(; i < arrSize; i++)
x = x * 10 + number[i];
x is the result.
int i;
int x = 0;
for ( i = 0; i < 4; i++ )
x = ( 10 * x + number[i] );
int number[]={1,2,3,4}
int x=0,temp;
temp=10;
for(i=0;i<number.length;i++)
{
x=x*temp+number[i];
}
cout>>x;
You could do something with a for loop and powers of 10
int tens = 1;
int final = 0;
for (int i = arrSize - 1; i <= 0; ++i)
{
final += tens*number[i];
tens*=10;
}
return final;
Answer is quite easy.Just list a complete function here.
int toNumber(int number[],arraySize)
{
int i;
int value = 0;
for(i = 0;i < arraySize;i++)
{
value *=10;
value += number[i];
}
return value;
}

Resources