7race
7race

Reputation: 21

Overflow when adding unsigned int with unsigned int

I am trying to find a solution for this one (codewars cata, 6 kyu):

Create a function that returns the sum of the two lowest positive numbers given an array of minimum 4 positive integers. No floats or non-positive integers will be passed. For example, when an array is passed like [19, 5, 42, 2, 77], the output should be 7. [10, 343445353, 3453445, 3453545353453] should return 3453455.

And i've almost found it. But obviously i have some misunderstanding about types mechanics here. For the test case

numbers = {2000000000, 2000000000, 2000000000, 2000000000, 2000000000}

I obtain overflow. And this is totally strange for me. I've read that in C int type size depends on compiling system. I have 64bit system, so my int is very large. Moreover, in this task we have only unsigned integers, so it seems that 32 bits <-> 4*10^9 could be enough. I've tried to use uint_32t and uint_64t types. Right now i am trying to cast all variables i have and this is not handy way. What else i need to understand to find the solution?

Here is my current code:

#include <stddef.h>
#include <stdio.h>
long sum_two_smallest_numbers(size_t n, const int numbers[n]) {
  int current_low1;//suppose first 2 ones are the lowest
  int current_low2;//and current_low1 is reserved for the lowest one

  int delta1;//variables for comparations
  int delta2;
  //every new value in array to be compared with 
  //current_low1 and current_low2.
  //then define - if new values are lesser
  //and if so - find out is new value the lowest
  if (numbers[0] < numbers[1]){
    current_low1 = numbers[0];
    current_low2 = numbers[1];
  } else {
    current_low1 = numbers[1];
    current_low2 = numbers[0];
  }
  int ind;
  for (ind = 2; (unsigned long) ind < n; ind++){
    if ((numbers[ind] < current_low1) && (numbers[ind] < current_low2)){
      delta1 = current_low1 - numbers[ind];
      delta2 = current_low2 - numbers[ind];
      if (delta1 > delta2){
        current_low1 = numbers[ind];
      } else{
        current_low2 = numbers[ind];
      }
    } else if ((numbers[ind] >= current_low1) && (numbers[ind] < current_low2)){
      current_low2 = numbers[ind];
    } else if ((numbers[ind] < current_low1) && (numbers[ind] >= current_low2)){
      current_low1 = numbers[ind];
    }
    }

  return (unsigned long)(current_low1 + current_low2);
}

Many thanks for your answers. I've found the solution after reading all your posts and after some pondering... So, i've used signed integers. Because the int declaration invoke signed integer by default. Then i've changed the first 4 variable's declarations to unsigned int. And now it works! I do not even need anymore to typacast the return sentence to long.

Thanks to you all, especially @Adrian Mole!

Upvotes: 2

Views: 830

Answers (2)

jacob galam
jacob galam

Reputation: 811

I change the types to uint64_t and call it.

#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

uint64_t sum_two_smallest_numbers(size_t n, const uint64_t  numbers[n]) {
  uint64_t  current_low1;//suppose first 2 ones are the lowest
  uint64_t  current_low2;//and current_low1 is reserved for the lowest one

  uint64_t  delta1;//variables for comparations
  uint64_t  delta2;
  //every new value in array to be compared with 
  //current_low1 and current_low2.
  //then define - if new values are lesser
  //and if so - find out is new value the lowest
  if (numbers[0] < numbers[1]){
    current_low1 = numbers[0];
    current_low2 = numbers[1];
  } else {
    current_low1 = numbers[1];
    current_low2 = numbers[0];
  }
  size_t ind;
  for (ind = 2; ind < n; ind++){
    if ((numbers[ind] < current_low1) && (numbers[ind] < current_low2)){
      delta1 = current_low1 - numbers[ind];
      delta2 = current_low2 - numbers[ind];
      if (delta1 > delta2){
        current_low1 = numbers[ind];
      } else{
        current_low2 = numbers[ind];
      }
    } else if ((numbers[ind] >= current_low1) && (numbers[ind] < current_low2)){
      current_low2 = numbers[ind];
    } else if ((numbers[ind] < current_low1) && (numbers[ind] >= current_low2)){
      current_low1 = numbers[ind];
    }
    }

  return (current_low1 + current_low2);
}

#define SIZE 5

int main()
{
    
    uint64_t  balance[SIZE] = {2000000000, 2000000000, 2000000000, 2000000000, 2000000000};

    printf("%" PRIu64, sum_two_smallest_numbers(SIZE, balance));

    return 0;
}

It print 4000000000

printf("%" PRIu64... and #include <inttypes.h> it for printing uint64_t

Upvotes: 2

Adrian Mole
Adrian Mole

Reputation: 51845

Don't assume, just because your operating system or platform is 64-bits, that your C compiler has a 64-bit int type. In fact, many/most such systems (e.g. MSVC on 64-bit Windows) do not.

If your base int type is 32-bits, then the sum of two 2000000000 signed integers will overflow (but unsigned should not).

So, declare your numbers argument as const int64_t numbers[n]; and, similarly, use that int64_t type in the declaration of the array in the calling module. You can probably also use long long int, as this should also be at least 64 bits wide.

You should also change the relevant local int variables in the sum_two_smallest_numbers function (and that function's return type) to 'explicit' 64-bit (or long long) integers.

Upvotes: 1

Related Questions