Reputation: 2429
I am using an equation in which we have to find the maximum value that x can take given the value of b. Both x and b can take only nonnegative integer values. The equation is:
x^4+x^3+x^2+x+1≤b
I have written the following code(apparently dumb) to solve it:
#include<iostream>
#include<climits>
using namespace std;
int main()
{
unsigned long long b,x=0;
cout<<"hey bro, value of b:";
cin>>b;
while(x++<b)
if(x*x*x*x+x*x*x+x*x+x+1>b)
break;
if(b==0)
cout<<"Sorry,no value of x satisfies the inequality"<<endl;
else
cout<<"max value of x:"<<x-1<<endl;
return 0;
}
The above code works fine upto b=LONG_MAX
but after for b=LONG_LONG_MAX
or b=ULLONG_MAX
, it starts taking forever. How can I solve this problem so that it works fine for at most b=ULLONG_MAX
?
Upvotes: 2
Views: 458
Reputation: 3319
Here's a slightly more optimized version:
#include<iostream>
int main()
{
std::cout << "Sorry, no value of x satisfies the inequality" << std::endl;
return 0;
}
Why? Because x^4+x^3+x^2+x+1
is unbounded as x approaches positive infinity. There is no b
for which your inequality holds. Computer Science is a subset of math.
Upvotes: -1
Reputation: 100
Quick answer:
First af all you are starting from x=0 and then increasing it which is not the best solution since you are looking for the maximum value and not the first one. So for that I would go from an upperbound that can be
x=abs((b)^(1/4))
than decrease from that value, and as soon you find an element <=b you are done.
You can even think in this way:
for y=b to 1
solve(x^4+x^3+x^2+x+1=y)
if has an integer solution then return solution
See this
This is a super quick answer I hope I didn't write too many stupid things, and sorry I don't know yet how to write math here.
Upvotes: 0
Reputation: 4689
Old answer (real problem here is not big number of iterations, but integer overflow; please read from 'Update' part; I keep this part here for history of false assumptions):
These values are very big. When your program checks each value from 0 to LONG_LONG_MAX
, it shold make about 9*10^12
operations, isn't it? For ULLONG_MAX
we have about 18*10^12
operations. Try to modify this program to see actual speed of processing:
while (x++ < b)
{
if (x % 1000000 == 0)
cout << " current x: " << x << endl;
if (x*x*x*x+x*x*x+x*x+x+1>b)
break;
}
So, you need to optimize this algorithm (i.e. reduce number of iterations): since your function is monotonic, you can use Binary search algorithm (see Bisection method too for clarification).
Also there is a possible problem with integer overflow: function x*x*x*x
for big values x
will be calculated wrong. Just imagine thay your type is unsigned char
(1 byte). For example, when your program calculates 250*250*250*250
you expect 3906250000, but in fact you have 3906250000 % 256
(i.e. 16
). So, if x
is too big, it is possible, that your function will return value < b
(and it will be strange; theoretically it can brake your optimized algorithm). Good news is that you will not see this problem, if do every check correctly. But for more complex functions you would also need to support long math (for example, use GMP or another implementation).
Update: How to avoid overflow risks?
We need to find maximal allowed value of x
(let's call it xmax
). Value x
is allowed if x*x*x*x+x*x*x+x*x+x+1 < ULLONG_MAX
. So, answer on initial question (about x*x*x*x+x*x*x+x*x+x+1 < b
) is not bigger than xmax
. Let's find xmax
(just solve equation x*x*x*x+x*x*x+x*x+x+1=ULLONG_MAX
in any system, for example WolframAlpha: anwer is about 65535.75...
, so xmax==65535
. So, if we check x
from 0
to xmax
we will not have overflow problems. Also it is our initial values for binary search algorithm.
Also it means, that we do not need to use binary search algorithm here, because it is enought to check only 65535 values. If x==65535
is not answer, we have to stop and return answer 65536
.
If we need cross-platform solution without hardcoding of xmax
, we can use any bigint implementation (GMP or any simpler solution) or implement more accurate multiplication and other operations. Example: if we need to multyply x
and y
, we can calculate z=ULLONG_MAX/x
and compare this value and y
. If z<y
, we can't multiply x
and y
without overflow.
Upvotes: 2
Reputation: 5277
A really simple observation solves your problem in O(1) time.
Find k = sqrt(sqrt(b))
If k
satisfies your inequality, k
is your answer. If it does not, k-1
is your answer.
Upvotes: 2
Reputation:
Don't let x
exceed 65535
. If 65535
satisfies the inequality, 65536
will not.
Upvotes: 1
Reputation: 2320
You could try finding an upper limit and working down from there.
// Find the position of the most significant bit.
int topBitPosition = 0;
while(b >> topBitPosition)
topBitPosition++;
// Find a rough estimate of b ^ 1/4
unsigned long long x = b >> (topBitPosition - topBitPosition/4);
// Work down from there
while(x*x*x*x+x*x*x+x*x+x+1 > b)
x--;
cout<<"max value of x:"<<x-1<<endl;
Upvotes: 1
Reputation: 11642
This is not just an optimization issue. (For optimization, see IVlad's answer). It is also a correctness issue. With very large values, the expression causes integer overflow: to put it simply, it wraps around from ULLONG_MAX back to zero, and your loop carries on having not detected this. You need to build overflow detection in your code.
Upvotes: 3