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.

phuclv
  • 37,963
  • 15
  • 156
  • 475
EMMERZOH
  • 29
  • 2
  • 3
  • 7
  • 4
    `15623212412` would not fit into an `int` on most systems. – T.C. Jun 07 '14 at 07:10
  • What about `itoa()` and `atoi()`? – mouviciel Jun 07 '14 at 07:18
  • I would prefer `itoa()` and `sprintf()` – Abhineet Jun 07 '14 at 07:20
  • What is the purpose of all this? Do you want to implement a bignum library? – Jens Gustedt Jun 07 '14 at 07:20
  • 1
    @Abhineet - Actually, [`iota()` is not standard](http://stackoverflow.com/q/190229/45249). So `sprint()` is the way to go both directions. – mouviciel Jun 07 '14 at 07:24
  • 10 because as the program recognizes the number to be appended to the end of integer n it will multiply the integer n by the amount of spaces needed to append the integer of A[] without disturbing the already appended integers. For example 156*100=15600 so that when you add th next integer in th array (23) you will get 15623 and so on. If the next integer was 9 it will multiply 15623*10=156230 so you can add to get 156239. – EMMERZOH Jun 07 '14 at 07:27
  • Also this is part of a much larger program where I would prefer not to or can't use itoa() or sprintf(). Unfortunately, it has to produce an integer n that will then be used in another equation. Else, I would have to re-code some other things. – EMMERZOH Jun 07 '14 at 07:41
  • @Jens Gustedt The produced integer n will be fed into another int array and the original A[] elements and size will be changed. – EMMERZOH Jun 07 '14 at 07:55
  • @Abhineet [Why shouldn't I use atoi()?](https://stackoverflow.com/q/17710018/995714) – phuclv Jul 17 '18 at 05:21

6 Answers6

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 ;
}
Clifford
  • 88,407
  • 13
  • 85
  • 165
  • 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! – EMMERZOH Jun 07 '14 at 08:11
  • 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 Jun 07 '14 at 08:56
  • @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. – Clifford Jun 07 '14 at 19:47
  • 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. – EMMERZOH Jun 08 '14 at 01:54
  • [there are simpler ways to calculate log10](https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10) instead of going through floating-point arithmetics – phuclv Jul 25 '18 at 03:56
  • @phuclv that is irrelevant, I have not suggested _coding_ the bit width calculation, or using floating point at all. The mention of log10 was merely an explanation of how to determine the number of bits necessary, it is a design time calculation, not a run time one. – Clifford Jul 25 '18 at 07:09
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;
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Thank you for the tidbit of info! Unfortunately this produced n= -1556656772. :( – EMMERZOH Jun 07 '14 at 07:50
  • 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`. – R Sahu Jun 07 '14 at 07:52
  • There was an error in the `for` loop. You were starting with `i=1` instead of `i=0`. – R Sahu Jun 07 '14 at 08:01
  • 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. – Clifford Jun 07 '14 at 08:08
  • 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! – EMMERZOH Jun 07 '14 at 08:08
  • What then would suggest using other than long long? @Clifford – EMMERZOH Jun 07 '14 at 08:45
  • On 32/64-bit Windows long is 32 bits while on Unix/Linux long is a 64-bit type. `long long` is guaranteed to be at least 64 bits by the standard so it's recommended. But here the numbers should be negative so you should use `unsigned long long` – phuclv Jun 07 '14 at 09:30
  • @Clifford I'm currently reworking my program to see I can may a string output work. It was part of my original plan to convert the int array to a string and then store the produced string in one element of a char array but I ran into some complication that why I went the all integer method. I truly appreciate you help with everything so far. – EMMERZOH Jun 07 '14 at 20:30
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]);
phuclv
  • 37,963
  • 15
  • 156
  • 475
  • how do you know a lookup is (always) faster than a integer multipy? – Paolo Jun 07 '14 at 09:34
  • @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 – phuclv Jun 07 '14 at 09:36
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
Paolo
  • 15,233
  • 27
  • 70
  • 91
  • 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 – phuclv Jun 07 '14 at 09:34
  • I agree for `long long`. As for variable names they are self-explanatory given the simplicity of the algorithm. – Paolo Jun 07 '14 at 09:39
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;
}
  • sprintf() returns the number of characters output; this can be used to simplify this code and avoid the strcat() ([always a good idea](http://www.joelonsoftware.com/articles/fog0000000319.html)) - see my answer. A `long long` may contain as many as 20 digits. – Clifford Jun 07 '14 at 20:01
  • 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. – EMMERZOH Jun 07 '14 at 20:33
  • @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 Jun 07 '14 at 20:37
  • @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. – Clifford Jun 08 '14 at 08:10
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.

janw
  • 8,758
  • 11
  • 40
  • 62