Code: Select all
5 5 5 0
0 0 0 0
Code: Select all
Case 1:
10.000 5.000
10.000 5.000
Code: Select all
Case 1:
10.000 5.000
Moderator: Board moderators
Code: Select all
5 5 5 0
0 0 0 0
Code: Select all
Case 1:
10.000 5.000
10.000 5.000
Code: Select all
Case 1:
10.000 5.000
One ratio may not be enough... but atan2() surely is. (The function is in math.h, in cmath and I believe that even FreePascal has a similar function.)shahriar_manzoor wrote:To determine an angle in the range (0,360) degree only one trigonometric ratio is not enough. Use sin(theta) and cos(theta) together to uniquely determine an angle. As sinthete is positive in quadrant 1 and 2 and costheta is positive in quadrant 4 and 1. So their sign will indicate where the angle actually is (Qudrant 1, 2, 3, or 4). Hope it helps.
Or may be I talk too much and you have already solved this problem.
yes! I never used atan2(), and never knew its utility, now I understand why this function exists.misof wrote:shahriar_manzoor wrote:atan2(y,x) returns the oriented angle from the vector [1,0] to the vector [x,y].
The only mistake Cho made is that he probably assumed this angle to be from the range [0,2pi), whereas the function returns an angle from (-pi,pi].
Shahriar: using atan2() is much easier and less error-prone than handling the 4 cases you mention "by hand".
This is the same as my case. I don't know the existence of such a handy function until very recently somebody mentioned this function in the forum for solving other problem.shahriar_manzoor wrote:I never used atan2(), and never knew its utility, now I understand why this function exists.
Code: Select all
/* 10834 */
#include <stdio.h>
#include <math.h>
#define error (1e-9)
int main() {
int caso, iR, ir;
long double R, r, x, y, cosd, sind, d, cosg, sing, cosa, sina, a, b, aant, x0, y0, x1, y1;
for (caso = 1;; caso++) {
scanf("%i %i %llf %llf", &iR, &ir, &x, &y);
if (iR == 0 && ir == 0) break;
R = iR;
r = ir;
d = sqrtl(x * x + y * y);
printf("Case %u:\n", caso);
if (R >= d - error || d >= R + 2 * r - error) { puts("IMPOSSIBLE"); continue; }
cosd = ((R + r) * (R + r) + d * d - r * r) / (2 * d * (R + r));
sind = sqrtl(1 - cosd * cosd);
cosg = x / d;
sing = y / d;
/* g+d , el otro es g-d*/
cosa = cosg * cosd - sing * sind;
sina = sing * cosd + cosg * sind;
a = atan2l(sina, cosa);
if (a <= -error) a += 4 * acosl(0);
b = a * R / r;
x0 = (R + r) * cosa - r * sinl(b + a);
y0 = (R + r) * sina + r * cosl(b + a);
aant = a;
cosa = cosg * cosd + sing * sind;
sina = sing * cosd - cosg * sind;
a = atan2l(sina, cosa);
if (a <= -error) a += 4 * acosl(0);
b = a * R / r;
x1 = (R + r) * cosa - r * sinl(b + a);
y1 = (R + r) * sina + r * cosl(b + a);
if (aant <= a)
printf("%.3llf %.3llf\n%.3llf %.3llf\n", x0, y0, x1, y1);
else
printf("%.3llf %.3llf\n%.3llf %.3llf\n", x1, y1, x0, y0);
}
return 0;
}
I haven't had any problems so far using %llf (just as %lli for long longs).Krzysztof Duleba wrote:The proper way to read and print long doubles is with %Lf, not with %llf.
But when should I do so? If a number is -0.0002, the logical thing to print is -0.000, because it is negative. Are you suggesting that any number strictly between -0.001 and 0.001 should be shown as 0.000? If so, this seems to me a rather queer requirement.Krzysztof Duleba wrote:Make sure to print 0.000 instead of -0.000.
Well, the manual says nothing about %llf and using %llf on my system results in reading junk and printing zeros. But if it works for you and for OJ than I guess it's fine.david wrote:I haven't had any problems so far using %llf (just as %lli for long longs).
I agree with you, but my code failed until I added a line that looks like (using your variable names)david wrote:But when should I do so? If a number is -0.0002, the logical thing to print is -0.000, because it is negative.
Code: Select all
if(x0 < 0 && x0 > -error)x0 = 0;