When multiplying large positive numbers, why is the result negative? - c

Here is the snippets of my code and the output. Suggest the reason behind a negative result when large positive numbers are multiplied?
int printM(int v)
{
int g=v+5;
g=g*3344564*452346;
printf("The value of g is %d\n",g);
return g;
}
int main()
{
int f=0;
int a=45;
a=a+334;
a=a+534534;
a=a+939;
a=a+45345654645;
f=printM(a);
return 0;
}
output:
pravesh#pravesh-Aspire-4552:~/Desktop/c_d$ gcc -g linked_list.c
pravesh#pravesh-Aspire-4552:~/Desktop/c_d$ ./a.out
The value of g is -377042000
`

What you end up with when overflowing an int is undefined behaviour. INT_MAX is defined to be the largest value that an int can represent on your platform.
Note that overflowing an unsigned is well defined: it wraps around modulo UINT_MAX + 1.
(For what it's worth, what's probably happening in your case is that the int is wrapping around in exactly the same way as it would do if the memory is interpreted as an unsigned).

Related

I've made a program in C that takes two inputs, x and n, and raises x to the power of n. 10^10 doesn't work, what happened?

I've made a program in C that takes two inputs, x and n, and raises x to the power of n. 10^10 doesn't work, what happened?
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
float isEven(int n)
{
return n % 2 == 0;
}
float isOdd(int n)
{
return !isEven(n);
}
float power(int x, int n)
{
// base case
if (n == 0)
{
return 1;
}
// recursive case: n is negative
else if (n < 0)
{
return (1 / power(x, -n));
}
// recursive case: n is odd
else if (isOdd(n))
{
return x * power(x, n-1);
}
// recursive case: n is positive and even
else if (isEven(n))
{
int y = power(x, n/2);
return y * y;
}
return true;
}
int displayPower(int x, int n)
{
printf("%d to the %d is %f", x, n, power(x, n));
return true;
}
int main(void)
{
int x = 0;
printf("What will be the base number?");
scanf("%d", &x);
int n = 0;
printf("What will be the exponent?");
scanf("%d", &n);
displayPower(x, n);
}
For example, here is a pair of inputs that works:
./exponentRecursion
What will be the base number?10
What will be the exponent?9
10 to the 9 is 1000000000.000000
But this is what I get for 10^10:
./exponentRecursion
What will be the base number?10
What will be the exponent?10
10 to the 10 is 1410065408.000000
Why does this write such a weird number?
BTW, 10^11 returns 14100654080.000000, exactly ten times the above.
Perhaps it may be that there is some "Limit" to the data type that I am using? I am not sure.
Your variable x is an int type. The most common internal representation of that is 32 bits. That a signed binary number, so only 31 bits are available for representing a magnitude, with the usual maximum positive int value being 2^31 - 1 = 2,147,483,647. Anything larger that that will overflow, giving a smaller magnitude and possibly a negative sign.
For a greater range, you can change the type of x to long long (usually 64 bits--about 18 digits) or double (usually 64 bits, with 51 bits of precision for about 15 digits).
(Warning: Many implementations use the same representation for int and long, so using long might not be an improvement.)
A float only has enough precision for about 7 decimal digits. Any number with more digits than that will only be an approximations.
If you switch to double you'll get about 16 digits of precision.
When you start handling large numbers with the basic data types in C, you can run into trouble.
Integral types have a limited range of values (such as 4x109 for a 32-bit unsigned integer). Floating point type haver a much larger range (though not infinite) but limited precision. For example, IEEE754 double precision can give you about 16 decimal digits of precision in the range +/-10308
To recover both of these aspects, you'll need to use a bignum library of some sort, such as MPIR.
If you are mixing different data types in a C program, there are several implicit casts done by the compiler. As there are strong rules how the compiler works one can exactly figure out, what happens to your program and why.
As I do not know all of this casting rules, I did the following: Estimating the maximum of precision needed for the biggest result. Then casting explicit every variable and funktion in the process to this precision, even if it is not necessary. Normally this will work like a workarount.

How to write absolute value in c

I know the solution is ugly and technically incorrect but I don't understand why the code doesn't work.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main (int argc, char *argv[]) {
int u;
scanf("%d", &u);
printf("absValue = %u\n", u);
return 0;
}
%u specifies an unsigned decimal character but when I input a negative value, it gives
absValue = 4294967293
Alternatively, with the if command, how to convert the negative sign to positive?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main (int argc, char *argv[]) {
int n;
scanf("%d", &n);
if(n < 0) {
printf("absValue = -%d\n", n);
} else {
printf("absValue = %d\n", n);
}
return 0;
}
The shortest solution in your first piece of code is to change the printf statement as follows:
printf("absValue = %u\n", (unsigned)((u<0)?-u:u));
This will print the absolute value of u. The type conversion (unsigned) ensures that the data type is as expected by printf. The statement (u<0)?-u:u uses the conditional operator to select the value -u if the condition (u<0) is true and u if the condition is false (i.e. u>=0).
The problem in your code is that u is a signed integer which means its value is stored using the Two's complement representation in 4 bytes(*) and printf is not intelligent. When you tell printf to display an unsigned integer, then printf will take the 4 bytes holding u and interpret them as an unsigned integer. Since negative numbers in Two's complement are stored as large positive integers, that is the result you see.
(*) The use of Two's complement and the int size of 4 is machine-dependent, but common.
As an alternative, you can also use the standard C function abs() (or one of its related functions):
7.22.6.1 The abs, labs and llabs functions
Synopsis
#include <stdlib.h>
int abs(int j);
long int labs(long int j);
long long int llabs(long long int j);
Description
The abs, labs, and llabs functions compute the absolute value of
an integer j. If the result cannot be represented, the behavior is
undefined.
Returns
The abs, labs, and llabs, functions return the absolute value.
Footnotes
The absolute value of the most negative number cannot be represented
in two's complement.
Note the footnote "The absolute value of the most negative number cannot be represented in two's complement." and "If the result cannot be represented, the behavior is undefined." Strictly speaking, you'd likely need to use long long int and llabs() to avoid undefined behavior in converting INT_MIN to a positive value, assuming a 32-bit int value, and long is often 32-bits, even on 64-bit Windows.
However, since double values are likely implemented in IEEE format with 53 bits of precision, a 32-bit int value can be converted to double with no loss of precision, so you can use the fabs() function to get the absolute value of a 32-bit int value in one call:
7.12.7.2 The fabs functions
Synopsis
#include <math.h>
double fabs(double x);
float fabsf(float x);
long double fabsl(long double x);
The fabs functions compute the absolute value of a floating-point
number x.
So your code would be:
#include <stdio.h>
#include <math.h>
int main (int argc, char *argv[]) {
int u;
scanf("%d", &u);
printf("absValue = %u\n", (unsigned) fabs((double) u));
return 0;
}
Note that in (unsigned) fabs((double) u), casting u to double is not strictly necessary, as the int value will be implicitly converted to a double because of the double fabs(double) function prototype from stdlib.h. But the cast back to unsigned is exremely necessary to pass the unsigned int value you want to pass to printf().
You could also do this:
#include <stdio.h>
#include <math.h>
int main (int argc, char *argv[]) {
int u;
scanf("%d", &u);
unsigned int absValue = fabs(u);
printf("absValue = %u\n", absValue);
return 0;
}
That works because unsigned int absValue is explicitly an unsigned int.
Also, on modern CPUs, conversion between int and double is usually done by a single relatively fast instruction.
How to write absolute value in c?
The shortest solution :
#include <stdlib.h>
printf("absValue = %d\n", abs(u)); // clear and concise - yet see below
Both printf("%d\n", abs(u)); and printf("%u\n", (unsigned)((u<0)?-u:u)); suffer the same problem: undefined behavior (UB) when n == INT_MIN1. The signed negation of INT_MIN is the UB.
At least abs(u) is clear, unlike (unsigned)((u<0)?-u:u).
To print the absolute value of an int, code could negate negative values with:
(-1 - n) + 1u or
-(unsigned)n or
0u - n
... and end up with an unsigned.2
I'd go for the simplest when a full range |int| is sought.
printf("absValue = %u\n", n < 0 ? 0u - n : (unsigned) n);
Using long, long long or double poses their own troubles and portability. None warranted here.
1 when int is 2's complement encoded - very common.
2 C specified UINT_MAX >= INT_MAX. In the very rare implementations today, INT_MAX == INT_MAX is possible and code needs to resort to a wider type when int is non 2's complement.
printf doesn't convert the strings, but rather expects them converted. I would generally prefer to use the standard abs function which is declared in stdlib.h. This uses strtol to convert an argument to a long then convert that to an int. Nota bene, that, for example, if your machine uses two's-complements, calling abs(INT_MIN) produces undefined behaviour and should be dealt with. (Edited: error detection now complies with non-POSIX systems; see comments.)
#include <stdio.h> /* perror, printf */
#include <stdlib.h> /* strtol, abs */
#include <limits.h> /* INT_MIN, INT_MAX */
#include <errno.h> /* errno, ERANGE */
int main(int argc, char *argv[]) {
int u;
long input;
char *end;
/* Require one argument. */
if(argc != 2) return printf("Usage <number>\n"), EXIT_SUCCESS;
/* `input` is converted from `argv[1]`, if it's 0, check that it actually
read 0; check to see garbage characters at the end; check to see if the
`input` is a) less then `INT_MIN`; b) also if `-INT_MAX < 0`, check that
it is not lower than this value, because that will lead to undefined
`abs`; c) more then `INT_MAX` -> if so, set `ERRNO` and enter the if. */
if( ((input = strtol(argv[1], &end, 0)) == 0 && end == argv[1])
|| (*end != '\0' && (errno = EILSEQ, 1))
|| ((input < INT_MIN || (-INT_MAX < 0 && input < -INT_MAX)
|| input > INT_MAX) && (errno = ERANGE, 1)) )
return perror("Input"), EXIT_FAILURE;
/* We are pretty sure this cast is safe, now: `int abs(int)`. */
u = abs((int)input);
printf("absValue(%ld) = %d\n", input, u);
return EXIT_SUCCESS;
}
Checking edge cases,
bin/abs 2147483647
absValue(2147483647) = 2147483647
bin/abs 2147483648
Input: Result too large
bin/abs -2147483648
Input: Result too large
bin/abs -2147483647
absValue(-2147483647) = 2147483647
bin/abs
Usage <number>
bin/abs 0x10
absValue(16) = 16
bin/abs asdf
Input: Invalid argument
bin/abs 1a
Input: Illegal byte sequence
this is a function to get the absolute value of a number without using abs() function.
int abs_value(int *a){
return *a < 0 ? -*a: *a;
}
If you want to get the absolute difference between two numbers, here's how:
int abs_diff (int *a, int*b) {
return *a > *b ? *a - *b : *b - *a;
}

why the value of sum is coming out to be negative? [duplicate]

This question already has answers here:
Sum of positive values in an array gives negative result in a c program
(4 answers)
Closed 4 years ago.
I have written the following c code to find the sum of first 49 numbers of a given array, but the sum is coming out to be negative.
#include<stdio.h>
int main()
{
int i;
long int sum=0;
long int a[50]={846930887,1681692778,1714636916, 1957747794, 424238336, 719885387, 1649760493, 596516650, 1189641422, 1025202363, 1350490028, 783368691, 1102520060, 2044897764, 1967513927, 1365180541, 1540383427, 304089173, 1303455737, 35005212, 521595369, 294702568, 1726956430, 336465783, 861021531, 278722863, 233665124, 2145174068, 468703136, 1101513930, 1801979803, 1315634023, 635723059, 1369133070, 1125898168, 1059961394, 2089018457, 628175012, 1656478043, 1131176230, 1653377374, 859484422, 1914544920, 608413785, 756898538, 1734575199, 1973594325, 149798316, 2038664371, 1129566414};
for(i=0;i<49;i++)
{
sum=sum+a[i];
printf("sum is : %ld\n",sum);
}
printf("\nthe total sum is %ld",sum);
}
i don't know why it is coming so?please help.
Using long long instead of long, the program works:
Ouput: 56074206897
Reason
Range of long: -2^31+1 to +2^31-1
Range of long long: -2^63+1 to +2^63-1
As you can see 2^31-1 = 2147483647 <
56074206897; but 2^63-1 = 9,223,372,036,854,775,807 > 56074206897
This leads to overflow. According to the C standard, the result of signed integer overflow is undefined behavior. What that means is that if this condition ever happens at runtime, the compiler is allowed to make your code do anything. Your program could crash, or produce the wrong answer, or have unpredictable effects on other parts of your code, or it might silently do what you intended.
In your case it is overflowing the maximum value of long int on your system. Because long int is signed, when the most significant bit gets set, it becomes a negative number.
I didn't actually add them up, but just looking at them, I'd say its a pretty safe guess that you are running into an integer overflow error.
A long int has a maximum size of about 2 billion (2^31). If you add more than that, it'll look back around and go to -2^31.
You'll need to use a data type that can hold more than that if you want to sum up those numbers. Probably a long long int should work. If you're sure it'll always be positive, even better to use an unsigned long long int.
As long int has maximum range upto 2,147,483,647, and the value of sum is more than the range.So, it is coming as negative value. You can use the following code...
#include<stdio.h>
int main()
{
int i;
long long int sum=0; //Taking long long int instead of long int
int a[50]={846930887,1681692778,1714636916, 1957747794, 424238336,
719885387, 1649760493, 596516650, 1189641422, 1025202363, 1350490028,
783368691, 1102520060, 2044897764, 1967513927, 1365180541, 1540383427,
304089173, 1303455737, 35005212, 521595369, 294702568, 1726956430,
336465783, 861021531, 278722863, 233665124, 2145174068, 468703136,
1101513930, 1801979803, 1315634023, 635723059, 1369133070, 1125898168,
1059961394, 2089018457, 628175012, 1656478043, 1131176230, 1653377374,
859484422, 1914544920, 608413785, 756898538, 1734575199, 1973594325,
149798316, 2038664371, 1129566414};
for(i=0;i<49;i++)
{
sum=sum+a[i];
printf("sum is : %lld\n",sum);
}
printf("\nTotal sum is %lld",sum);
}
As Vlad from Moscow said this is a overflow issue, which made an undefined behavior. In you system (long int sum) sum does not have capacity to hold the total value. Not sure but you can use long long int sum =0;(after C99). If it still cannot work properly, search for "BigInteger" implement.

C - erroneous output after multiplication of large numbers

I'm implementing my own decrease-and-conquer method for an.
Here's the program:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
double dncpow(int a, int n)
{
double p = 1.0;
if(n != 0)
{
p = dncpow(a, n / 2);
p = p * p;
if(n % 2)
{
p = p * (double)a;
}
}
return p;
}
int main()
{
int a;
int n;
int a_upper = 10;
int n_upper = 50;
int times = 5;
time_t t;
srand(time(&t));
for(int i = 0; i < times; ++i)
{
a = rand() % a_upper;
n = rand() % n_upper;
printf("a = %d, n = %d\n", a, n);
printf("pow = %.0f\ndnc = %.0f\n\n", pow(a, n), dncpow(a, n));
}
return 0;
}
My code works for small values of a and n, but a mismatch in the output of pow() and dncpow() is observed for inputs such as:
a = 7, n = 39
pow = 909543680129861204865300750663680
dnc = 909543680129861348980488826519552
I'm pretty sure that the algorithm is correct, but dncpow() is giving me wrong answers.
Can someone please help me rectify this? Thanks in advance!
Simple as that, these numbers are too large for what your computer can represent exactly in a single variable. With a floating point type, there's an exponent stored separately and therefore it's still possible to represent a number near the real number, dropping the lowest bits of the mantissa.
Regarding this comment:
I'm getting similar outputs upon replacing 'double' with 'long long'. The latter is supposed to be stored exactly, isn't it?
If you call a function taking double, it won't magically operate on long long instead. Your value is simply converted to double and you'll just get the same result.
Even with a function handling long long (which has 64 bits on nowadays' typical platforms), you can't deal with such large numbers. 64 bits aren't enough to store them. With an unsigned integer type, they will just "wrap around" to 0 on overflow. With a signed integer type, the behavior of overflow is undefined (but still somewhat likely a wrap around). So you'll get some number that has absolutely nothing to do with your expected result. That's arguably worse than the result with a floating point type, that's just not precise.
For exact calculations on large numbers, the only way is to store them in an array (typically of unsigned integers like uintmax_t) and implement all the arithmetics yourself. That's a nice exercise, and a lot of work, especially when performance is of interest (the "naive" arithmetic algorithms are typically very inefficient).
For some real-life program, you won't reinvent the wheel here, as there are libraries for handling large numbers. The arguably best known is libgmp. Read the manuals there and use it.

C recursive function to calculate Factorial

Im just beginning to learn C programming and figured i would start out at a pretty basic problem of calculating the factorial of a number. My code outputs the correct value up until the factorial of 13 and then gives me the wrong answer for when the input is >13. My code is:
#include<stdio.h>
long int factorial(int);
int main()
{
int num;
long int fact;
printf("Please type the number you want factoralized: ");
scanf("%d",&num);
fact = factorial(num);
printf("%d",fact);
return 0;
}
long int factorial(int dig)
{
long int facto;
if (dig>1)
facto = dig * factorial(dig-1);
else if (dig=1)
facto = 1;
return facto;
}
When i input 13 it returns 1932053504 instead of the expected 6227020800
You are probably overflowing the LONG_MAX value on your platform which leads to undefined behaviour. You can use unsigned long (or unsigned long long) but they wouldn't hold for much longer either.
Your options are limited here. You could use libraries, such as GNU GMP that support arbitrarily large integers. Otherwise, you'll have to implement it yourself similar to GMP.
On another note,
else if (dig=1)
is not what you want. It should be
else if ( dig == 1 )
Or you can simply use else {...} here unless you intend to check against negative numbers.

Resources