// Задача "Большие скачки"
// Шестая Интернет-олимпиада сезона 2009-2010, усложненный уровень
// Автор задачи: Федор Царев, tsarev@rain.ifmo.ru
// Автор решения: Нияз Нигматуллин, niyaz.nigmatullin@gmail.com

import java.io.*;
import java.util.*;

public class horseraces_nn implements Runnable {
	public static void main(String[] args) {
		new horseraces_nn().run();
	}

	class FastScanner {
		BufferedReader br;
		StringTokenizer st;
		boolean eof;
		String buf;

		public FastScanner(String fileName) throws FileNotFoundException {
			br = new BufferedReader(new FileReader(fileName));
			nextToken();
		}

		public FastScanner(InputStream stream) {
			br = new BufferedReader(new InputStreamReader(stream));
			nextToken();
		}

		String nextToken() {
			while (st == null || !st.hasMoreTokens()) {
				try {
					st = new StringTokenizer(br.readLine());
				} catch (Exception e) {
					eof = true;
					break;
				}
			}
			String ret = buf;
			buf = eof ? "-1" : st.nextToken();
			return ret;
		}

		int nextInt() {
			return Integer.parseInt(nextToken());
		}

		long nextLong() {
			return Long.parseLong(nextToken());
		}

		double nextDouble() {
			return Double.parseDouble(nextToken());
		}

		void close() {
			try {
				br.close();
			} catch (Exception e) {

			}
		}

		boolean isEOF() {
			return eof;
		}
	}

	FastScanner sc;
	PrintWriter out;

	private static final String FN = "horseraces";

	public void run() {
		Locale.setDefault(Locale.US);
		try {
			sc = new FastScanner(FN + ".in");
			out = new PrintWriter(FN + ".out");
			solve();
			sc.close();
			out.close();
		} catch (Throwable e) {
			e.printStackTrace();
			System.exit(1);
		}
	}

	void doAssert(boolean isRight, String s) {
		if (!isRight)
			throw new AssertionError(s);
	}

	private final static double EPS = 1e-6;

	static int compare(double a, double b, double eps) {
		if (Double.isNaN(a) || Double.isNaN(b)) {
			throw new Error("can not compare");
		}
		return a < b - eps ? -1 : a > b + eps ? 1 : 0;
	}

	static class Point {
		double x, y;

		public Point(double x, double y) {
			this.x = x;
			this.y = y;
		}

		Point subtract(Point p) {
			return new Point(x - p.x, y - p.y);
		}

		Point norm() {
			double z = len();
			if (compare(z, 0, EPS) == 0) {
				throw new Error("division by zero");
			}
			return new Point(x / z, y / z);
		}

		Point add(Point p) {
			return new Point(x + p.x, y + p.y);
		}

		double len() {
			return Math.sqrt(x * x + y * y);
		}

		public Point multiply(double d) {
			return new Point(x * d, y * d);
		}

		@Override
		public String toString() {
			return "Point [x=" + x + ", y=" + y + "]";
		}

	}

	static class Line {
		double a, b, c;

		Line(Point p1, Point p2) {
			a = p2.y - p1.y;
			b = p1.x - p2.x;
			c = -p1.x * a - p1.y * b;
		}

		double get(Point p) {
			return a * p.x + b * p.y + c;
		}

		double dist(Point p) {
			return Math.abs(get(p)) / Math.sqrt(a * a + b * b);
		}
	}

	static class Circle {
		Point c;
		double r;

		public Circle(Point c, int r) {
			this.c = c;
			this.r = r;
		}

		public Circle(double x, double y, int r) {
			c = new Point(x, y);
			this.r = r;
		}

		@Override
		public String toString() {
			return "Circle [c=" + c + ", r=" + r + "]";
		}

	}

	static class Event implements Comparable<Event> {
		boolean begin;
		double x;

		public Event(boolean begin, double x) {
			this.begin = begin;
			this.x = x;
		}

		@Override
		public int compareTo(Event o) {
			return compare(x, o.x, 0);
		}
	}

	final int MAX = (int) 1e5;

	private void solve() {
		Point p1 = new Point(sc.nextInt(), sc.nextInt());
		Point p2 = new Point(sc.nextInt(), sc.nextInt());
		doAssert(-MAX <= p1.x && -MAX <= p1.y && p1.x <= MAX && p1.y <= MAX
				&& -MAX <= p2.x && -MAX <= p2.y && p2.x <= MAX && p2.y <= MAX,
				"points on line are out of bounds");
		Line l = new Line(p1, p2);
		Point v = p2.subtract(p1).norm();
		int n = sc.nextInt();
		Circle[] circles = new Circle[n];
		for (int i = 0; i < n; i++) {
			circles[i] = new Circle(sc.nextInt(), sc.nextInt(), sc.nextInt());
			doAssert(-MAX <= circles[i].c.x && -MAX <= circles[i].c.y
					&& 1 <= circles[i].r && circles[i].c.x <= MAX
					&& circles[i].c.y <= MAX && circles[i].r <= MAX, "circle["
					+ (i + 1) + "] coordinates and/or radius are out of bounds");
		}
		Point initPoint;
		if (compare(l.b, 0, EPS) == 0) {
			initPoint = new Point(-l.c / l.a, 0);
		} else {
			initPoint = new Point(0, -l.c / l.b);
		}
		ArrayList<Event> events = new ArrayList<Event>();
		for (int i = 0; i < n; i++) {
			double d = l.dist(circles[i].c);
			if (compare(circles[i].r, d, EPS) <= 0) {
				continue;
			}
			Point v1 = new Point(-v.y, v.x).norm().multiply(d);
			{
				double dist1 = l.dist(circles[i].c.add(v1));
				v1 = v1.multiply(-1);
				double dist2 = l.dist(circles[i].c.add(v1));
				if (dist1 < dist2) {
					v1 = v1.multiply(-1);
				}
			}
			Point v2 = v.norm().multiply(
					Math.sqrt(circles[i].r * circles[i].r - d * d));
			Point g1 = circles[i].c.add(v1).add(v2);
			Point g2 = circles[i].c.add(v1).subtract(v2);
			if (compare(l.dist(g1), 0, EPS) != 0) {
				throw new AssertionError("first intersection is not right");
			}
			if (compare(l.dist(g2), 0, EPS) != 0) {
				throw new AssertionError("second intersection is not right");
			}
			double t1, t2;
			if (compare(v.x, 0, EPS) == 0) {
				t1 = g1.subtract(initPoint).y / v.y;
				t2 = g2.subtract(initPoint).y / v.y;
			} else {
				t1 = g1.subtract(initPoint).x / v.x;
				t2 = g2.subtract(initPoint).x / v.x;
			}
			if (t1 > t2) {
				double temp = t1;
				t1 = t2;
				t2 = temp;
			}
			events.add(new Event(true, t1));
			events.add(new Event(false, t2));
		}
		Collections.sort(events);
		double last = Double.NEGATIVE_INFINITY;
		int cur = 0;
		double ans = 0;
		for (Event e : events) {
			if (cur > 0) {
				ans += e.x - last;
			}
			if (e.begin) {
				++cur;
			} else {
				--cur;
			}
			last = e.x;
		}
		out.printf("%.10f\n", ans);
	}
}
