#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#define PI 3.14159265358979323846
static double a = 2.0, b = 1.0;
double f(double t, double x, double y) {
return (a * cos(t) - x) * (a * sin(t)) + (b * sin(t) - y) * b * cos(t);
}
double cos_t = cos(t);
double sin_t = sin(t);
return (a * a + b * b) * (cos_t * cos_t - sin_t * sin_t)
- a * x * cos_t
+ b * y * sin_t;
}
double distance(double t, double x, double y) {
double ellipse_x = a * cos(t);
double ellipse_y = b * sin(t);
return sqrt((ellipse_x - x) * (ellipse_x - x) +
(ellipse_y - y) * (ellipse_y - y));
}
int newton_downhill(double x, double y, double initial_t, double* t_result,
double e1, double e2, int max_iter) {
double t0 = initial_t;
double lambda = 1.0;
double t, ft, dft;
for (int i = 0; i < max_iter; i++) {
ft = f(t0, x, y);
dft = df(t0, x, y);
if (fabs(dft) < e2) {
if (fabs(ft) < e1) {
*t_result = t0;
return 1;
}
return 0;
}
t = t0 - lambda * ft / dft;
while (t >= 2 * PI) t -= 2 * PI;
while (t < 0) t += 2 * PI;
if (fabs(f(t, x, y)) < e1 && fabs(t - t0) < e2) {
*t_result = t;
return 1;
}
if (fabs(f(t, x, y)) < fabs(ft)) {
t0 = t;
lambda = 1.0;
} else {
lambda *= 0.5;
if (lambda < 1e-10) {
return 0;
}
}
}
return 0;
}
double find_nearest_point(double x, double y, double* best_t) {
double initial_angles[] = {0.0, PI/4, PI/2, 3*PI/4, PI, 5*PI/4, 3*PI/2, 7*PI/4};
int num_angles = 8;
double min_distance = 1e10;
double t_result;
int success_count = 0;
for (int i = 0; i < num_angles; i++) {
if (newton_downhill(x, y, initial_angles[i], &t_result, 1e-9, 1e-9, 100)) {
success_count++;
double dist = distance(t_result, x, y);
if (dist < min_distance) {
min_distance = dist;
*best_t = t_result;
}
}
}
printf("成功收敛次数: %d/%d\n", success_count, num_angles);
return min_distance;
}
void test_algorithm() {
srand((unsigned int)time(NULL));
int num_tests = 20;
int success_count = 0;
printf("=== 牛顿下山法求解点到椭圆最近距离验证 (修正版) ===\n");
printf("椭圆方程: x²/%.1f² + y²/%.1f² = 1\n\n", a, b);
for (int i = 0; i < num_tests; i++) {
double test_x = (rand() % 200 - 100) / 10.0;
double test_y = (rand() % 200 - 100) / 10.0;
double best_t;
double min_dist = find_nearest_point(test_x, test_y, &best_t);
if (min_dist < 1e9) {
success_count++;
double nearest_x = a * cos(best_t);
double nearest_y = b * sin(best_t);
printf("测试 %2d: 点(%.2f, %.2f) -> 最近点(%.4f, %.4f), 距离=%.6f\n",
i+1, test_x, test_y, nearest_x, nearest_y, min_dist);
} else {
printf("测试 %2d: 点(%.2f, %.2f) -> 计算失败\n", i+1, test_x, test_y);
}
}
printf("\n=== 统计结果 ===\n");
printf("总测试次数: %d\n", num_tests);
printf("成功次数: %d\n", success_count);
printf("成功率: %.2f%%\n", (success_count * 100.0) / num_tests);
}
int main() {
test_algorithm();
return 0;
}