The following simple calculation causes an integer overflow:
void main(void) {
int n = 1291;
long cube = n*n*n;
printf("Cube: %ld, n: %d", cube, n);
}
Output:
Cube: -2143282125, n: 1291
My thinking was that since the result of n*n*n is assigned to a long, the result should evaluate to 2151685171. However, it appears that the result is calculated first into an int; because if int n = 1291 is changed to long n = 1291, it works as expected.
Question:
Is the 'intermediary' result of n*n*n stored to int (the declared type) before being assigned to the long declaration? Or, more simply: Why does n*n*n cause an integer overflow when being assigned to a long type?
I have researched to find the answer first, unfortunately must be searching incorrectly.
Your question resembles a lot to the typical division question:
int a = 7;
double b = a / 2;
=> b seems to be equal to 3 instead of 3.5, and in order to avoid this, you need to do:
double b = ((double)a) / 2; // or:
double b = a / 2.0; // which is the same as (double)2
So, I believe that you might benefit from the same reasoning, doing something like this:
int n = 1291;
long cube = ((long)n) * n * n;
Related
Here is a code snippet:
unsigned int m,n,a;
long long int c,p=0,q=0;
scanf("%u%u%u",&m,&n,&a);
while(m>0){
m-=a;
p++;
}
while(n>0){
n-=a;
q++;
}
c=p*q;
printf("%lld",c);
The above code does not work for any input. That is, it seems like it has crashed,though I could not understand where I'm mistaken. I guess the part with %lld in the printf has problems. But Ido not know how to fix it. I'm using code blocks.
Some expected outputs for corresponding inputs are as follows:
Input: 6 6 4
Output: 4
Input: 1000000000 1000000000 1
Output: 1000000000000000000(10^18).
APPEND:
So, I'm giving the link of the main problem below. The logic of my code seemed correct to me.
https://codeforces.com/contest/1/problem/A
As it's been pointed out in comments/answers the problem is that m and n is unsigned so your loops can only stop if m and n are a multiple of a.
If you look at the input 6 6 4 (i.e. m=6 and a=4), you can see that m first will change like m = 6 - 4 which leads to m being 2. So in the next loop m will change like m = 2 - 4 which should be -2 but since m is unsigned it will wrap to a very high positive number (i.e. UINT_MAX-1) and the loop will continue. That's not what you want.
To fix it I'll suggest you drop the while loops and simply do:
unsigned int m,n,a;
long long unsigned int c,p=0,q=0;
scanf("%u%u%u",&m,&n,&a);
p = (m + a - 1)/a; // Replaces first while
q = (n + a - 1)/a; // Replaces second while
c=p*q;
printf("%lld",c);
One problem with this solution is that the sum (m + a - 1) may overflow (i.e. be greater than UINT_MAX) and therefore give wrong results. You can fix that by adding an overflow check before doing the sum.
Another way to protect against overflow could be:
p = 1; // Start with p=1 to handle m <= a
if (m > a)
{
m -= a; // Compensate for the p = 1 and at the same time
// ensure that overflow won't happen in the next line
p += (m + a - 1)/a;
}
This code can then be reduced to:
p = 1;
if (m > a)
{
p += (m - 1)/a;
}
while(m>0){
m-=a;
p++;
}
will run until m is equal to 0, since it cannot be negative because it is unsigned. So if m is 4 and a is 6, then m will underflow and get the maximum value that m can hold minus 2. You should change the input variables to signed.
4386427 shows how you can use math to remove the loops completely, but for the more general case, you can do like this:
while(m > a) {
m-=a;
p++;
}
// The above loop will run one iteration less
m-=a;
p++;
Of course, you need to do the same thing for the second loop.
Another thing, check return value of scanf:
if(scanf("%u%u%u",&m,&n,&a) != 3) {
/* Handle error */
}
Using an unsigned type isn't always the best choice to represent positive values, expecially when its modular behavior is not needed (and maybe forgotten, which leads to "unexpected" bugs). OP's use case requires an integral type capable of store a value of maximum 109, which is inside the range of a 32-bit signed integer (a long int to be sure).
As 4386427's answer shows, the while loops in OP's code may (and should) be avoided anyways, unless a "brute force" solution is somehow required (which is unlikely the case, given the origin of the question).
I'd use a function, though:
#include <stdio.h>
// Given 1 <= x, a <= 10^9
long long int min_n_of_tiles_to_pave_an_edge(long int x, long int a)
{
if ( x > a ) {
// Note that the calculation is performed with 'long' values and only after
// the result is casted to 'long long', when it is returned
return 1L + (x - 1L) / a;
}
else {
return 1LL;
}
}
int main(void)
{
// Given a maximum value of 10^9, a 32-bit int would be enough.
// A 'long int' (or 'long') is guaranteed to be capable of containing at
// least the [−2,147,483,647, +2,147,483,647] range.
long int m, n, a;
while ( scanf("%ld%ld%ld", &m, &n, &a) == 3 )
{
// The product of two long ints may be too big to fit inside a long.
// To be sure, performe the multiplication using a 'long long' type.
// Note that the factors are stored in the bigger type, not only the
// result.
long long int c = min_n_of_tiles_to_pave_an_edge(m, a)
* min_n_of_tiles_to_pave_an_edge(n, a);
printf("%lld\n",c);
}
}
I see some code in c like this
int main()
{
int x = 4, y = 6;
long z = (long) x + y;
}
what is the benefit of casting even though in this case it implicit? Which operation comes first x + y or casting x first?
In this case the cast can serve a purpose. If you wrote
int x = 4, y = 6;
long z = x + y;
the addition would be performed on int values, and then, afterwards, the sum would be converted to long. So the addition might overflow. In this case, casting one operand causes the addition to be performed using long values, lessening the chance of overflow.
(Obviously in the case of 4 and 6 it's not going to overflow anyway.)
In answer to your second question, when you write
long z = (long)x + y;
the cast is definitely applied first, and that's important. If, on the other hand, you wrote
long z = (long)(x + y);
the cast would be applied after the addition (and it would be too late, because the addition would have already been performed on ints).
Similarly, if you write
float f = x / y;
or even
float f = (float)(x / y);
the division will be performed on int values, and will discard the remainder, and f will end up containing 0. But if you write
float f = (float)x / y;
the division will be performed using floating-point, and f will receive 0.666666.
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.
I have an array of integer element range up to 10^5, and I have to find the first element after the total multiplication.
Example:
Array : 2,4,6,7
multiplication result: 336 and the first element is 3.
Obviously I cannot multiply the elements with the range up to 10^5.
How can I track only the first digit during multiplication?
We can also find the first digit with another method.
Suppose p be the final value after multiplying all the elements.
So, we have to find
P = a[0]*a[1]*a[2]*a[3]*.......*a[n-1]
for n sized array then we can take log with base 10 on both the side after that our expression changes to
log(p) = log(a[i])+log(a[1])+log(a[2])+.....+log(a[n-1])
Now, to find the first digit we have to get the fractional part of this variable sum which can be done in this way
frac = sum - (integer)sum
and at the last step calculate the 10^frac and convert it to the integer value which is our required first digit.
This algorithm is better in comparison to time complexity.
int getFirstDigit(long a[], long n) {
double p;
for(int i=0;i<n;i++) {
p = p+log10(a[i]);
}
double frac = p - (long)p;
int firdig = (int)pow(10,frac);
return firdig;
}
In c or c++ make integer data type as long double such that first digit of number is before decimal point and rest are after decimal point.
Above can be done as follows:-
long double GetFraction(int number){
int length = (int) log(number) + 1; // this will give number of digits in given number. And log is log base 10.
long double fraction = (long double) number / (10^(length - 1);
return fraction;
}
Example :-
Let number = 12345
length = log(12345) + 1 = 5;
fraction = (long double) 12345 / (10^4) = 1.2345
Now for all integers in array find fraction as mention above and multiply them as follow:-
int GetFirstDigit(int arr[] , int size){
if(size == 0)
return 0;
long double firstDigit = 1.0;
for(int i = 0 ; i < size ; i++){
firstDigit = firstDigit*GetFraction(arr[i]);
if(firstDigit >= 10.00) // You have to shorten your number otherwise it will same as large multiplication and will overflow.
firstDigit/=10;
}
return (int) firstDigit;
}
Disclaimer:- This is my approach and I don't have any formal proof about accuracy of result. But I have verified result for integer up to 10^9 and array size up to 10^5
Please donot forget to note that this is just an attempt to make you understand the logic and that you need to make changes in the code as per your requirement. I strongly suggest you make this a subroutine in your program and parse the arguments to it from the main thread in your program.
#include <stdio.h>
void main()
{
int num1, num2;
printf("Enter ur lovely number:\n");
scanf("%d",&num1);
num2=num1;
while(num2)
{
num2=num2/10;
if(num2!=0)
num1=num2;
}
printf("The first digit of the lovely number is %d !! :P\n ",num1);
}
Try this approach,
Take integer as input let us say int x1, now copy this in a double let us say double x2, and suppose you have previous product as double y, initially y = 1 . now use this loop,
while(x1!<10){
x1 = x1/10;
x2 = x2/10; //this will make double in standard form x*10^y without 10^y part
}
ex x1 = 52, then x2 will be converted to 5.2.
Now let us assume y = 3 and x is 5.2.
then product now is 15.6, again reduce this to 1.56 and repeat the process. in the end you will have the only digit before the decimal as the first digit of the product of all the numbers.
I have two int values that I want to combine into a decimal number. So for example, I have A = 1234 and B = 323444. Both are int and I do not want to change it if possible.
I want to combine them to get 1234234233.323444.
My initial method was to divide b by 1e6 and add it to A to get my value.
I assigned
int A = 1234234233;
int B = 323444;
double C;
A = 1234;
B = 323444;
C = A + (B/ 1000000);
printf("%.6f\n", C);
I get 1234234233.000000 as a result. It rounds my C and I do not want that as I want 1234234233.323444
how can I solve this?
Try like this:
C = A + (B/ 1000000.0);
ie, make the denominator as double so that when integer by integer division is made it does not return weird results like you are getting.
NOTE:-
Integer/Integer = Integer
Integer/Double = Double
Double/Integer = Double
Double/Double = Double
B is an integer and dividing an integer by another integer (10000 here) will always give an integer and that's why you are getting unexpected result. Changing 10000, which is of type int, to 10000.0 (double type) will solve this problem. It seem that 10000 and 10000.0 are integer by mathematical definition but both are of different type in programming languages, former is of type int while latter is of type double.
C = A + (B/ 1000000.0);
or
C = A + ((double)B/ 1000000);
to get the expected result.