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();
}
}