Ravi Kumar
Ravi Kumar

Reputation: 11

C - Problem in finding sum of consecutive numbers

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

int main() {
    int start, end, i, sum = 0, temp, x, y, z;
    puts("Please enter the starting number: ");
    scanf("%d", &start);
    temp = start;
    x = start; y = start + 1;
    puts("Please enter the last number till you want to add: ");
    scanf("%d", &end);
    for (i = start; i < end; i++) {
        z = x + y;
        x = z;
        y = y + 1;
    }
    printf("The sum of the numbers starting from %d to %d is %d", temp, end, z);
}

Can anyone find what's wrong with this code?

It is working fine for less numbers but when I assign large numbers like 1 to 1000000, it doesn't work i.e. it returns strange values.

Case 1:

Please enter the starting number:
1

Please enter the last number till you want to add:
100

The sum of the numbers starting from 1 to 100 is 5050

But in this case -

Case 2:

Please enter the starting number:
1


Please enter the last number till you want to add:
1000000


The sum of the numbers starting from 1 to 1000000 is 1784293664

What's wrong in this case? Thanks in advance.

Upvotes: 1

Views: 4320

Answers (7)

user14526699
user14526699

Reputation:

In the second case, you have used a number that is greater than the allowed range for integer data type(it's from -32768 to 32767 for a 16-bit architecture and from -2,147,483,648 to 2,147,483,647 for a 32-bit architecture.) and that's why it leads to integer overflow issue. To fix this problem, you could use other bigger data types such as long int or long long int but I recommend you use their unsigned data types i.e unsigned long int or unsigned long long int if you're not going to use negative numbers because the range of unsigned data types begins from 0.

Upvotes: 0

Luis Colorado
Luis Colorado

Reputation: 12668

Sorry, but don't you know the following way to compute the sum?

long sum_from_a_to_b(long a, long b)
{
    int n;
    int acc = 0;
    for (n = a; n <= b; n++)
        acc += n;
    return  acc;
}

by the way, there's a better formula, which requires no loop:

#include <assert.h>
/* assumed that a <= b */
long sum_from_a_to_b(long a, long b)
{
    assert(a <= b);
    return b*(b + 1)/2 - a*(a - 1)/2;
}

Upvotes: 0

chqrlie
chqrlie

Reputation: 144780

The range of type int is not sufficient to represent the value of the sum for large values of start and stop (for example the sum for 0 to 65536 exceeds 2147483647). The variables x, y and z should be defined with type long long which is guaranteed to represent values up to 9223372036854775807 (9.22E18) or unsigned long up to 18446744073709551615 (1.84E19).

Furthermore your algorithm to compute the sum is convoluted, with unnecessary or unused intermediary variables. Simplicity is king!

Here is a modified version:

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

int main() {
    int start, end, i;
    long long sum;

    puts("Please enter the starting number: ");
    if (scanf("%d", &start) != 1)
        return 1;

    puts("Please enter the last number till you want to add: ");
    if (scanf("%d", &end) != 1)
        return 1;

    sum = 0;
    for (i = start; i <= end; i++) {
        sum = sum + i;
    }
    printf("The sum of the numbers from %d to %d is %lld\n", start, end, sum);
    return 0;
}

For positive start and stop values, there is a direct formula to compute the result. You could replace the for loop with this expression:

    if (start <= stop) {
        // take the sum of integers from 0 to stop: stop * (stop + 1) / 2
        sum = (long long)stop * (stop + 1) / 2;
        // subtract the sum of integers from 0 to start - 1: (start - 1) * start / 2
        sum -= (long long)start * (start - 1) / 2;
    } else {
        sum = 0;
    }

which simplifies as:

    if (start <= stop) {
        sum = ((long long)stop + start)(stop - start + 1) / 2;
    } else {
        sum = 0;
    }

If start and/or stop can be negative, the sum can still be computed directly as:

    if (start <= stop) {
        // take the sum of integers from 0 to stop - start:
        sum = (long long)(start - stop) * ((long long)stop - start + 1) / 2;
        // add the initial value (stop - start + 1) times
        sum += ((long long)stop - start + 1) * start;
    } else {
        sum = 0;
    }

Which simplifies as:

    if (start <= stop) {
        sum = ((long long)stop + start)((long long)stop - start + 1) / 2;
    } else {
        sum = 0;
    }

Upvotes: 1

chux
chux

Reputation: 153582

Problem in finding sum of consecutive numbers

OP's code repeatedly adds and attempts a sum greater than INT_MAX leading to incorrect results.

  1. Use a wider type for the computation of the sum such as long long or intmax_t.

  2. Performance: Do not use a loop. The sum of integers [0...N] is N*(N+1)/2

Instead:

//for (i = start; i < end; i++) {
//    z = x + y;
//    x = z;
//    y = y + 1;
//}

// Sum 0 to start
long long sum_start = ((long long) start + 1) * start / 2; // or (start + 1LL)*start/2;
// Sum 0 to end
long long sum_end   = ((long long) end + 1) * end / 2;

//                                                       vvvv specifier change
printf("The sum of the numbers starting from %d to %d is %lld", 
  temp, end, sum_end - (sum_start - start));

Upvotes: 1

Dakshayani Yadavalli
Dakshayani Yadavalli

Reputation: 11

For large numbers you must use unsigned long long int instead of int. Here int means integer which is up to 3 or 4 digit numbers but when you enter 5 digit numbers or more digit numbers it gives you strange values.

Upvotes: 1

Kinxil
Kinxil

Reputation: 321

It's a case of data overflow.

For your example of computing from 1 to 1000000, the sum of consecutive numbers from 1 to x is x(x+1)/2, which is 500.000.500.000, a value largely above the range of an int (2.147.483 647).

Consider using long long int, and don't forget that regardless of the byte size of your variable up to a certain value you'll overflow anyway.

Upvotes: 1

itsDV7
itsDV7

Reputation: 854

You are using int which only have value range -32,768 to 32,767 or -2,147,483,648 to 2,147,483,647 for 2 byte and 4 byte respectively.

You should use unsigned long long for your code which have a value range 0 to 18,446,744,073,709,551,615.

Upvotes: 1

Related Questions