1

I have hit a bit of a roadblock and I was hoping someone could help.

Suppose you have:

int A[]={156,23,212,4,12};

And you would like to append it to give a single integer n=15623212412

How can I fix my code to do so?

int p, n=0, size=5; 
for(i=1;i<size;i++){
    p=10;

    while(A[i]>=p)
        p*=10;

    n*=p;  
    n+=A[i];
}

It needs to be in C and it needs to create integer n through a loop as the integers in and size of the array will change.

9
  • 4
    15623212412 would not fit into an int on most systems. Commented Jun 7, 2014 at 7:10
  • What about itoa() and atoi()? Commented Jun 7, 2014 at 7:18
  • I would prefer itoa() and sprintf() Commented Jun 7, 2014 at 7:20
  • What is the purpose of all this? Do you want to implement a bignum library? Commented Jun 7, 2014 at 7:20
  • 1
    @Abhineet - Actually, iota() is not standard. So sprint() is the way to go both directions. Commented Jun 7, 2014 at 7:24

6 Answers 6

1

If the size of the array can be bigger you have to understand that a 32 bit integer is good for only nine decimal digits - log10(232), and that even a 64 bit integer is good for 19 decimal digits - log10(264). Either way, even your small example will not fit in a 32 bit int.

Also there is no real mathematical purpose or relationship in appending arbitrary integers in this way, especially as each has a variable number of decimal significant digits - any algorithm would have to take that into account.

So for the reasons given, attempting to solve the problem arithmetically is both over complex and inflexible; the simpler solution is to generate the result as a string.

int A[]={156,23,212,4,12};
int i = 0 ;
int index = 0 ;
const int length_A = sizeof(A) / sizeof(*A) ;
char astr[length_A * 10 ] ; // sized to accommodate worst case 
                            // string length for 32 bit int of INT_MAX.


for( i = 0; i < length_A; i++ )
{
    index += sprintf( &astr[index], "%d", A[i] ) ; 
}

printf( "%s", astr ) ;

If you really need an arithmetic solution and can work within the limits of the available integer data types, then I suggest that you use unsigned long long for the output and unsigned int for the input, then:

#include <stdio.h>
#include <math.h>

int main()
{
    unsigned int A[]={156,23,212,4,12};
    unsigned long long result = 0 ;
    int i = 0 ;
    const int length_A = sizeof(A) / sizeof(*A) ;

    for( i = 0; i < length_A; i++ )
    {
        result += A[i] ;
        if( i < length_A - 1)
        {
            int digits = (int)ceil( log10( (double)A[i+1] ) ) ;
            result *= (int)pow( 10, digits ) ;
        }
    }

    printf( "%llu\n", result ) ;

    return 0 ;
}
Sign up to request clarification or add additional context in comments.

6 Comments

I understand. I originally wanted to convert it to a string but then I was running into other issues in other parts of my program. While this is not the simplest solution it works for my purposes but I definitely keep in mind what you have taught me just now. Thank you!
I have a followup question to your method of converting A[] to a string. How could I then send this string of appended integers to an element spot in a new array?
@EMMERZOH : That string itself is an array, so your destination would have to be an array of strings, and without necessarily knowing the maximum lengths a priori, that might be expensive in memory terms. Neither strings nor arrays in C are first calss data types, so assignment does not work, strings can be copied with strcpy(), so you would use that to copy the result to some other destination. You might use an array of pointers and dynamically allocate the destination space after you have determined the actual length of the result.
Ohhh. Obviously I'm still learning haha. I will attempt using strcpy() in a second version of my program. So far the program is working as a whole with a small glitch that occurs with the first "big number" integer n when I try to create and input additional "big number" n's into a "big number" int array. I have a feeling it has to do with the data type being "overflowed" (I think that's the word I am looking for). Thank you greatly for all the help. You have been an amazing resource.
there are simpler ways to calculate log10 instead of going through floating-point arithmetics
|
0

I see couple of problems:

  1. You are starting the for loop with i=1. It should be i=0.

  2. 15623212412 could be too big to fit in an int. It is on my machine. Use long or a bigger integral type.

By the way, I was able to detect the problem by adding a printf.

#include <stdio.h>

int main()
{
   int A[]={156,23,212,4,12};
   int p, size=5; 
   long n = 0;
   int i;

   for(i=0;i<size;i++){
       p=10;

       while(A[i]>=p)
          p*=10;

       n*=p;  
       n+=A[i];
       printf("n: %ld\n", n);
   }

   return 0;
}

8 Comments

Thank you for the tidbit of info! Unfortunately this produced n= -1556656772. :(
On your platform, sizeof(long) must be equal to sizeof(int). I got the same answer when I used int for n. You can try long long or int64_t for n.
There was an error in the for loop. You were starting with i=1 instead of i=0.
The problem could be predicted from the outset - number of digits is greater than log10(2^32). Using long does not solve the problem, and long long is good for only 19 digits - if the number of elements and decimal digits in the input are unbounded, this answer will not work.
I'm sorry, that was a typo that wasn't actually in my program. Haha but thank you again. You have saved me from an allnighter!
|
0

I suggest this approach given that you know beforehand you're not going to overflow...

I'm using long as they are 64 bits on my architecture (they are treated as long long) If it's not your case use long long

long A[]={156,23,212,4,12};
long size = 5;

long i;
long j;
long n;
long k;

i = size;
j = 0;
n = 0;
k = 1;
while( true )
{
    if( j == 0 )
    {
        i--;
        if( i < 0 )
        {
            break;
        }
        j = A[ i ];
    }

    n += ( j % 10 ) * k;
    j /= 10;
    k *= 10;
}

printf("%ld\n", n); // <== final result printed

2 Comments

it's better if you add comments and use meaningful variable names. Also, long is only 32 bits on Windows so long long should be used instead, for more portability. And the OP most probably uses Windows since he gets overflow on long type
I agree for long long. As for variable names they are self-explanatory given the simplicity of the algorithm.
0

There are a lot of good answers here, but I also like converting to string, then to a long long int. That was mentioned above, but let me add an implementation. It is simpler than some alternatives:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    int A[] = {156, 23, 212, 4, 12};
    int length = 5;
    char a_as_num[length][4];
    char string[15] = "\0";
    long long number;
    int i;

    for (i = 0; i < length; i++) {
        sprintf(a_as_num[i], "%d", A[i]); 
        strcat(string, a_as_num[i]);
    }
    number = atoll(string);
    printf("%lli\n", number);
    return 0;
}

4 Comments

sprintf() returns the number of characters output; this can be used to simplify this code and avoid the strcat() (always a good idea) - see my answer. A long long may contain as many as 20 digits.
The issue with sprintf is that the resulting string can not be printed (yet). The string that is created must be stored as an element of a char array.
@Clifford If I want to create an int n with an unlimited amount of digits lets say, or have the option to create an integer n with say 30, or 50, or even as many as 100 digits what specifier would I need? The size of integer n could be as small as 1 digit or as large as 100 digits for the purpose of my program. Is that even possible?
@EMMERZOH : A string is a char array - it must be stored in an array of char arrays, or more efficiently perhaps an array of char pointers to dynamically allocated strings. I think the question you asked is answered - you should perhaps post a new question rather than get into lengthy discussion in the comments. That's not what comments are for on SO - this is not a traditional discussion forum.
0

You can try using a lookup table for powers of 10

const uint64_t powersOf10[] = { // use lookup to reduce multiplications
    1, 10,
    100, 1000,
    10000, 100000,
    1000000, 10000000,
    100000000, 1000000000, // the table can end here if A[i] is of type int
    10000000000, 100000000000,
    1000000000000, 10000000000000,
    100000000000000, 1000000000000000,
    10000000000000000, 100000000000000000,
    1000000000000000000, 10000000000000000000
};

int A[] = {156, 23, 212, 4, 12};
uint64_t *p10, n = 0; // or unsigned long long if uint64_t not available

for (int i = 0; i < sizeof(A)/sizeof(A[0]); i++)
{
    // get the length of A[i] by linear search
    p10 = powersOf10;
    while (*p10 < A[i]) p10++;

    n *= *p10;
    n += A[i];
}

You can change the linear search to a binary search, or using some optimized way to calculate log10 to get the index to powersOf10[]

If you just want to print then the simplest solution would be using sprintf. It'll work for arbitrarily long arrays

char output[MAX], *pos = output;
for (int i = 0; i < sizeof(A)/sizeof(A[0]); i++)
    pos += sprintf(pos, "%d", A[i]);

2 Comments

how do you know a lookup is (always) faster than a integer multipy?
@Paolo I didn't said that it's faster, I just said that it reduces the number of multiplications. In some cases a small lookup table is faster than a multiplication
0

You can first convert the integer array to string and then can convert it into a single integer, like this:

std::ostringstream os;
for (int i: res) {
    os << i;
}
std::string str(os.str());
stringstream geek(str);
int x = 0; 
geek >> x;

where res is an array.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.