I have the code
unsigned long long f(unsigned long long x, unsigned long long y){
return sqrt( ( (5*x*x + 1) * (5*y*y +1) - 1 ) / 4 );
}
but if x or y is too big, the thing overflows even though the output is supposed to be small. is there a way around this?
Split the argument of the square root up algebraically, maybe?:
return sqrt((3*x*x+1)/2) * sqrt((6*y*y-5)/2);
Or split it up further based on your needs.
If x
is big enough you can ignore the +1
and make the first term:
sqrt((3*x*x)/2) = fabs(x) * sqrt(3.0/2.0)
and similarly with y
for the second term, making it
sqrt((6*y*y)/2) = fabs(y) * sqrt(3.0);
EDIT: After OP edited his question to be:
return sqrt(((3*x*x+1)*(6*y*y-5)-1)/4);
You can in fact split things up. You just have to be a little bit more careful. Bottom line is that if x
is really big, then the +1
can be ignored. If y
is really big then the -5
can be ignored. If both (3*x*x+1)
and (6*y*y-5)
are positive and either is really big, then the -1
can be ignored. You can use these tips and some additional surrounding logic to break this down a bit further. Like this:
if(fabs(x) > BIGNUMBER && fabs(y) > BIGNUMBER)
{
return fabs(x) * fabs(y) * sqrt(18.0/4.0);
}
if(fabs(x) > BIGNUMBER && fabs(y) > 1.0) // x big and y term positive
{
return fabs(x) * sqrt(6*y*y-5) * sqrt(3.0/2.0);
}
if(fabs(y) > BIGNUMBER) // x term positive and y big
{
return sqrt(3*x*x+1) * fabs(y) * sqrt(6.0/2.0);
}
return sqrt(((3*x*x+1)*(6*y*y-5)-1)/4);
You can optimize this, but this is just meant to show the point.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With