import java.util.Scanner; // 参考:https://blog.nowcoder.net/n/034e8ed5f3a64b629e16d127fbb52400 class Point { double x, y; Point(double A, double B) { x = A; y = B; } } class Line { Point point_A, point_B; Line(Point A, Point B) { point_A = A; point_B = B; } } class Circle { Point O; int r; Circle(Point A, int B) { O = A; r = B; } } public class Main { // 辅助方法:计算点到直线的距离 public static double distPointToLine(Point p, Line l) { double xp = p.x, yp = p.y; double xA = l.point_A.x, yA = l.point_A.y; double xB = l.point_B.x, yB = l.point_B.y; /** 1. 向量叉积 对于两个向量 AB 和 AP: AB = (xB-xA, yB-yA) 是直线的方向向量 AP = (xp-xA, yp-yA) 是从点A指向点P的向量 |AB × AP| = |(xB-xA)(yp-yA) - (yB-yA)(xp-xA)| */ // 方法用于返回两个参数的平方和的平方根,没有中间溢出或下溢。 double lineBase = Math.hypot(xA - xB, yA - yB); if (lineBase == 0) { // 直线退化为一个点 return Math.hypot(xp - xA, yp - yA); } // 这两个向量的叉积大小等于以它们为邻边构成的平行四边形的面积: double numerator = Math.abs((xp - xA) * (yB - yA) - (yp - yA) * (xB - xA)); // 2.点到直线的距离实际上就是平行四边形的高: // 距离 = 平行四边形面积 / 底边长度 // = |AB × AP| / |AB| return numerator / lineBase; } public static double getDistance(Circle circle, Line l) { double d = distPointToLine(circle.O, l); double r = circle.r; // 根据勾股定理,我们有: r*r = d*d + (l/2)^2 double halfChordSq = r * r - d * d; // 题目保证不相离,但为健壮性处理浮点误差 if (halfChordSq < 0) { halfChordSq = 0; } // 反推出弦长 l = 2√(r^2-d^2) return 2.0 * Math.sqrt(halfChordSq); } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); double ox = scanner.nextDouble(); double oy = scanner.nextDouble(); int r = scanner.nextInt(); double x1 = scanner.nextDouble(); double y1 = scanner.nextDouble(); double x2 = scanner.nextDouble(); double y2 = scanner.nextDouble(); Point center = new Point(ox, oy); Circle circle = new Circle(center, r); Point p1 = new Point(x1, y1); Point p2 = new Point(x2, y2); Line l = new Line(p1, p2); double result = getDistance(circle, l); System.out.printf("%.6f\n", result); scanner.close(); } }