I was solving a problem wherein the task was to output the result of a pascal triangle at a given row mentioned by a user.
https://leetcode.com/problems/pascals-triangle-ii/
I wrote my solution which had issues storing huge factorial results.
vector<int> getRow(int rowIndex) {
vector<int> v;
int C = 1;
v.push_back(1);
for (int i = 1; i <= rowIndex; i++)
{
printf("%d ", C);
C = C * (rowIndex +1 - i) / i;
v.push_back(C);
}
return v;
}
On going through these questions,
What range of values can integer types store in C++
How many bytes is unsigned long long?
and going through some other sources, i made the following change which gave me the required result.
C = (unsigned long long)C * (rowIndex +1 - i) / i;
Since "C" is of type int and my vector v stores int, i wanted to know why would a cast unsigned long long still give me valid results.
The sub-expression C * (rowIndex +1 - i) can overflow before your division. By casting C to a larger data-type then the whole expression becomes that type, so the multiplication will not overflow. Then after the division with i the result is converted to an int again, but because of the division it is within range of an int.
Note that this is only for the values you currently have. If you continue with even higher values then sooner or later you will have overflows that can't be fixed by such a cast.
When you say
(unsigned long long)C
you are not making actual variable C a unsigned long long. You are just saying when doing this
C * (rowIndex +1 - i) / i;
treat C (at the right side) as unsigned long long. That is, only the temporary space to hold C, then hold its multiplication with (rowIndex +1 - i), and then its division with i is done at a space that big. If the whole result was bigger than a value that integer can have, this would not work either.
Related
I would like to multiple 2 positive signed 32-bit integers i and j. The worst case scenario is when i and j are both INT_MAX where their product is within the limit of a 64-bit integer, but when I perform the operation
int i = INT_MAX;
int j = INT_MAX;
long long int res = i * j;
I get garbage due to integer overflow. So I've typically solved that problem by casting i or j to a long long int
int i = INT_MAX;
int j = INT_MAX;
long long int res = (long long int)i * j;
Is this the typical workaround for this issue? Are there other ways that may be better?
Your solution is correct, and standard enough that quality compilers will recognize it. Some CPU's have dedicated 32x32->64 multiplication instructions, and you can reasonably expect a compiler to use such an instruction despite the cast.
I created a BigInt class which allows for huge numbers (from any bases 2-36) far beyond the integer max by storing each digit in a vector. I need to be able to convert this back to an integer but return the int max/min instead if the max is reached, otherwise there will ofc be an integer overflow.
My question is how can I check if I have exceeded the max without overflowing the integer I am building. I have tried moving the if statements at the bottom into the for loop but my integer still overflows. I feel like the solution is simple but I just can't grasp it.
// Convert BigInt to integer base 10 and return that int
// If BigInt > INT_MAX, return INT_MAX.
// If BigInt < INT_MIN, return INT_MIN.
int BigInt::to_int() const{
int number = 0;
for(size_t i = 0; i < vec.size(); i++) {
number += vec[i] * pow(base, i);
}
if (!isPositive) { number *= -1; }
if (number > INT_MAX) { return INT_MAX; }
if (number < INT_MIN) { return INT_MIN; }
return number;
}
Comparing an int value to INT_MAX is pointless except for equality because all values are less than or equal.
Performing overflow check after the overflowing signed operations is pointless because either they show that there was no overflow or the behaviour of the program is undefined. Always do the check before attempting operations that would overflow the result.
In this case, convert INT_MAX to your BigInt type and compare that with *this.
Preliminary info: you need to check for overflow before calculating something that overflows. If the overflow already happened, it's too late.
Adding an overflow check to your version of to_int() is tricky because you build up your value starting from the one's place. Because of this approach, you try to add pow(base, i), which could overflow an int by itself and that is not easy to detect in advance. Possible, but let's consider something else.
If you were to build up your value ending at the one's place (i.e. repeatedly calculate number*base + digit), you could check for overflow before multiplying. Here is some math, using shorter names for an easier read. Let x and M be integers, base a positive integer, and d some non-negative integer less than base. (M short for "max" and d short for "digit".) Division will mean real-valued division, as I can trunc() the result to get integer division. We want to know how x*base + d compares to M.
If x*base + d <= M then dividing by base gives x + d/base <= M/base, hence x <= trunc(M/base).
By the contrapositive, if x > trunc(M/base) then x*base + d > M.
If x*base + d >= M then dividing by base gives x + d/base >= M/base, hence x >= trunc(M/base).
By the contrapositive, if x < trunc(M/base) then x*base + d < M.
If x == trunc(M/base) then x*base == trunc(M/base)*base. Add M%base to both sides to get x*base + M%base == M. Well, I hope you'll accept the observation that trunc(M/base)*base + M%base == M. If you can accept that much, then the comparison between x*base + d and M is the same as the comparison between d and M%base.
Done with the math. Let's put this into code. You might note a performance increase as well, depending on how your compiler optimizes.
// Tests if number * base + next_digit will overflow an int.
bool will_overflow(int number, int base, int next_digit )
{
if ( number > INT_MAX/base )
return true;
if ( number < INT_MAX/base )
return false;
// It's close enough that the next digit decides it.
return next_digit > INT_MAX % base;
}
// Convert BigInt to integer base 10 and return that int
// If BigInt > INT_MAX, return INT_MAX.
// If BigInt < INT_MIN, return INT_MIN.
int BigInt::to_int() const {
int number = 0;
// Loop in the reverse direction. Be careful with unsigned values!
for(size_t i = vec.size(); i > 0; --i) {
if ( will_overflow(number, base, vec[i-1]) )
return isPositive ? INT_MAX : INT_MIN;
number = number * base + vec[i-1];
}
return number;
}
I will point out one small cheat in this. There is a single negative value that fits in an int, but whose absolute value is greater than INT_MAX. If that singular value comes up, this function will incorrectly detect it as an overflow and return INT_MIN. Fortunately, that works out fine since the singular value is INT_MIN. :)
I've written a C++ function to calculate factorial and used it to calculate 22C11 (Combination). I have declared a variable ans and set it to 0. I tried to calculate
22C11 = fact(2*n)/(fact(n)*fact(n))
where i sent n as 11. For some reason, i'm getting a negative value stored in answer. How can i fix this?
long int fact(long int n) {
if(n==1||n==0)
return 1;
long int x=1;
if(n>1)
x=n*fact(n-1);
return x;
}
The following lines are included in the main function:
long int ans=0;
ans=ans+(fact(2*n)/(fact(n)*fact(n)));
cout<<ans;
The answer i'm getting is -784
The correct answer should be 705432
NOTE: This function is working perfectly fine for n<=10. I have tried long long int instead of long int but it still isn't working.
It is unwise to actually calculate factorials - they grow extremely fast. Generally, with combinatorial formulae it's a good idea to look for a way to re-order operations to keep intermediate results somewhat constrained.
For example, let's look at (2*n)!/(n!*n!). It can be rewritten as ((n+1)*(n+2)*...*(2*n)) / (1*2*...*n) == (n+1)/1 * (n+2)/2 * (n+3)/3 ... * (2*n)/n. By interleaving multiplication and division, the rate of growth of intermediate result is reduced.
So, something like this:
int f(int n) {
int ret = 1;
for (int i = 1; i <= n; ++i) {
ret *= (n + i);
ret /= i;
}
return ret;
}
Demo
22! = 1,124,000,727,777,607,680,000
264 = 18,446,744,073,709,551,615
So unless you have 128-bit integers for unsigned long long you have integer overflow.
You are triggering integer overflow, which causes undefined behaviour. You could in fact use long long int, or unsigned long long int to get a little bit more precision, e.g:
unsigned long long fact(int n)
{
if(n < 2)
return 1;
return fact(n-1) * n;
}
You say you tried this and it didn't work but I'm guessing you forgot to also update the type of x or something. (In my version I removed x as it is redundant). And/or your calculation still was so big that it overflowed unsigned long long int.
You may be interested in this thread which shows an algorithm for working out nCr that doesn't require so much intermediate storage.
You increasing your chances of success by avoiding the brute force method.
COMB(N1, N2) = FACT(N1)/(FACT(N1-N2)*FACT(N2))
You can take advantage of the fact that both the nominator and the denominator have a lot of common terms.
COMB(N1, N2) = (N1-N2+1)*(N1-N2+2)*...*N1/FACT(N1)
Here's an implementation that makes use of that knowledge and computes COMB(22,11) with much less risk of integer overflow.
unsigned long long comb(int n1, int n2)
{
unsigned long long res = 1;
for (int i = (n1-n2)+1; i<= n1; ++i )
{
res *= i;
}
for (int i = 2; i<= n2; ++i )
{
res /= i;
}
return res;
}
I have written an attempt at my own RSA algorithm, but the encryption portion isn't quite working when I use fairly large numbers (nothing like the size which should be used for RSA) and I'm not sure why.
It works in the following way:
The input is a list of characters, for this example "abc"
This is converted to an array: [10,11,12]. (I have chosen 10 - 35 for lower case letters so that they are all 2 digit numbers just to make it easier)
The numbers are combined to form 121110 (using 12*100^2 + 11*100^1 + 10*100^0)
Apply the algorithm: m^e (mod n)
This is simplified using a^b (mod n) = a^c (mod n) * a^d (mod n)
This works for small values in that it can be deciphered using the decryption program which I have written.
When using larger values the output is always 1844674407188030241, with a little bit of research I found that this is roughly 2^64 (to 10 significant figures, it has been pointed out that odd numbers can't be powers of two, oops). I am sure that there is something that I have overlooked and I apologise for what (I really hope) will be a trivial question with an easy answer. Why is the output value always 2^64 and what can I change to fix it? Thank you very much for any help, here is my code:
#include <iostream>
#include <string>
#include <math.h>
int returnVal (char x)
{
return (int) x;
}
unsigned long long modExp(unsigned long long b, unsigned long long e, unsigned long long m)
{
unsigned long long remainder;
int x = 1;
while (e != 0)
{
remainder = e % 2;
e= e/2;
if (remainder == 1)
x = (x * b) % m;
b= (b * b) % m;
}
return x;
}
unsigned mysteryFunction(const std::string& input)
{
unsigned result = 0;
unsigned factor = 1;
for (size_t i = 0; i < input.size(); ++i)
{
result += factor * (input[i] - 87);
factor *= 100;
}
return result;
}
int main()
{
unsigned long long p = 70021;
unsigned long long q = 80001;
int e = 7;
unsigned long long n = p * q;
std::string foo = "ab";
for (int i = 0; i < foo.length(); i++);
{
std::cout << modExp (mysteryFunction(foo), e, n);
}
}
Your code has several problems.
Problem 1: Inconsistent use of unsigned long long.
int x = 1;
Changing this declaration in modExp to unsigned long long causes the program to give a more reasonable-looking result. I don't whether it's the correct result, but it's less than n, at least. I'm still not sure what the exact mechanism of the error was. I can see ways it would have screwed things up, but none that could have caused an output of 1844674407188030241.
Problem 2: Composite "primes".
For RSA, p and q both need to be prime. Neither p nor q is prime in your code.
70021 = 7^2 * 1429
80001 = 3^2 * 2963
In mysteryFunction, you subtract 89, which corresponds to 'W', from the input characters. You probably want to subtract '97' instead, which corresponds to 'a'.
Couldn't you initialize an unsigned int and then increment it until it doesn't increment anymore? That's what I tried to do and I got a runtime error "Timeout." Any idea why this doesn't work? Any idea how to do it correctly?
#include
int main() {
unsigned int i(0), j(1);
while (i != j) {
++i;
++j;
}
std::cout << i;
return 0;
}
Unsigned arithmetic is defined as modulo 2^n in C++ (where n is
the number of bits). So when you increment the maximum value,
you get 0.
Because of this, the simplest way to get the maximum value is to
use -1:
unsigned int i = -1;
std::cout << i;
(If the compiler gives you a warning, and this bothers you, you
can use 0U - 1, or initialize with 0, and then decrement.)
Since i will never be equal to j, you have an infinite loop.
Additionally, this is a very inefficient method for determining the maximum value of an unsigned int. numeric_limits gives you the result without looping for 2^(16, 32, 64, or however many bits are in your unsigned int) iterations. If you didn't want to do that, you could write a much smaller loop:
unsigned int shifts = sizeof(unsigned int) * 8; // or CHAR_BITS
unsigned int maximum_value = 1;
for (int i = 1; i < shifts; ++i)
{
maximum_value <<= 1;
++maximum_value;
}
Or simply do
unsigned int maximum = (unsigned int)-1;
i will always be different than j, so you have entered an endless loop. If you want to take this approach, your code should look like this:
unsigned int i(0), j(1);
while (i < j) {
++i;
++j;
}
std::cout << i;
return 0;
Notice I changed it to while (i<j). Once j overflows i will be greater than j.
When an overflow happens, the value doesn't just stay at the highest, it wraps back abound to the lowest possible number.
i and j will be never equal to each other. When an unsigned integral value achieves its maximum adding to it 1 will result in that the next value will be the minimum that is 0.
For example if to consider unsigned char then its maximum is 255. After adding 1 you will get 0.
So your loop is infinite.
I assume you're trying to find the maximum limit that an unsigned integer can store (which is 65,535 in decimal). The reason that the program will time out is because when the int hits the maximum value it can store, it "Goes off the end." The next time j increments, it will be 65,535; i will be 0.
This means that the way you're going about it, i would NEVER equal j, and the loop would run indefinitely. If you changed it to what Damien has, you'd have i == 65,535; j equal to 0.
Couldn't you initialize an unsigned int and then increment it until it doesn't increment anymore?
No. Unsigned arithmetic is modular, so it wraps around to zero after the maximum value. You can carry on incrementing it forever, as your loop does.
Any idea how to do it correctly?
unsigned int max = -1; // or
unsigned int max = std::numeric_limits<unsigned int>::max();
or, if you want to use a loop to calculate it, change your condition to (j != 0) or (i < j) to stop when j wraps. Since i is one behind j, that will contain the maximum value. Note that this might not work for signed types - they give undefined behaviour when they overflow.