using System;
using System.Linq;

namespace geometry
{
	public class Point{
		public double x, y;
		public Point(){
			this.x = this.y = 0;
		}

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

		public static Point operator+(Point p1, Point p2){
			return new Point (p1.x + p2.x, p1.y + p2.y);
		}

		public static Point operator-(Point p1, Point p2){
			return new Point (p1.x - p2.x, p1.y - p2.y);
		}

		public static Point operator*(Point p1, double a){
			return new Point (p1.x * a, p1.y * a);
		}

		public static Point operator/(Point p1, double a){
			return new Point (p1.x / a, p1.y / a);
		}

		public double norm(){
			return this.x * this.x + this.y * this.y;
		}

		public double abs(){
			return Math.Sqrt(norm()); 
		}

		public Point Clone(){
			Point clone = new Point (this.x, this.y);
			return clone;
		}
	}

	public class Line{
		public Point p1, p2;
		public Line(){
			this.p1 = new Point ();
			this.p2 = new Point ();
		}

		public Line(double p1x, double p1y, double p2x, double p2y){
			this.p1 = new Point(p1x, p1y);
			this.p2 = new Point(p2x, p2y);
		}

		public Line(Point p1, Point p2){
			this.p1 = p1.Clone();
			this.p2 = p2.Clone();
		}

		public Line Clone(){
			Line clone = new Line (this.p1, this.p2);
			return clone;
		}
	}

	public class Circle{
		public Point c;
		public double r;
		public Circle(){
			this.c = new Point ();
			this.r = 0.0;
		}

		public Circle(double cx, double cy, double r){
			this.c.x = cx;
			this.c.y = cy;
			this.r = r;
		}

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

		public Circle Clone(){
			Circle clone = new Circle (this.c, this.r);
			return clone;
		}
	}

	class MainClass{
		static bool is_equal(double a, double b){
			if (Math.Abs (a - b) < 0.000001) {
				return true;
			} else {
				return false;
			}
		}

		static double dot(Point v1, Point v2){
			return v1.x * v2.x + v1.y * v2.y;
		}

		static double cross(Point v1, Point v2){
			return v1.x * v2.y - v1.y * v2.x;
		}

		// ??´?????????
		static bool is_orthogonal(Line s1, Line s2){
			return is_equal(dot(s1.p2 - s1.p1, s2.p2 - s2.p1), 0.0);
		}

		// ????????????
		static bool is_parallel(Line s1, Line s2){
			return is_equal(cross(s1.p2 - s1.p1, s2.p2 - s2.p1), 0.0);
		}

		// ????????????
		static bool is_intersect(Line s1, Line s2){
			return ccw(s1.p1, s1.p2, s2.p1) * ccw(s1.p1, s1.p2, s2.p2) <= 0 && ccw(s2.p1, s2.p2, s1.p1) * ccw(s2.p1, s2.p2, s1.p2) <= 0;
		}

		// ?°???±??¢??°
		static Point project(Line s, Point p){
			Point base_v = s.p2 - s.p1;
			double r = dot (p - s.p1, base_v) / base_v.norm ();
			return s.p1 + base_v * r;
		}

		// ????°???¢??°
		static Point reflect(Line s, Point p){
			return p + (project(s, p) - p) * 2;
		}

		// ???????¨???????
		static int ccw(Point p0, Point p1, Point p2){
			Point v1 = p1 - p0;
			Point v2 = p2 - p0;
			if (cross (v1, v2) > 0.000001) {
				return 1;
			}
			if (cross (v1, v2) < -0.000001) {
				return -1;
			}
			if (dot (v1, v2) < -0.000001) {
				return 2;
			}
			if (v1.norm() < v2.norm()) {
				return -2;
			}
			return 0;
		}

		// 2??????????????¢????±???????
		static double get_distance_p2p(Point p1, Point p2){
			return (p2 - p1).abs();
		}
		// ??´?????¨???????????¢????±???????
		static double get_distance_l2p(Line l, Point p){
			return Math.Abs (cross (l.p2 - l.p1, p - l.p1)) / (l.p2 - l.p1).abs ();
		}

		// ????????¨???????????¢????±???????
		static double get_distance_s2p(Line s, Point p){
			if (dot (s.p2 - s.p1, p - s.p1) < 0.0) {
				return (p - s.p1).abs ();
			} else if (dot (s.p1 - s.p2, p - s.p2) < 0.0) {
				return (p - s.p2).abs ();
			}
			return get_distance_l2p (s, p);
		}

		// ????????¨??????????????¢????±???????
		static double get_distance_s2s(Line s1, Line s2){
			if (is_intersect(s1, s2)) {
				return 0.0;
			}
			return Math.Min (Math.Min (get_distance_s2p (s1, s2.p1), get_distance_s2p (s1, s2.p2)), Math.Min (get_distance_s2p (s2, s1.p1), get_distance_s2p (s2, s1.p2)));
		}

		static double[] input_line(){
			string[] s = Console.ReadLine().Split(' ');
			double[] d = s.Select(i => double.Parse(i)).ToArray();
			return d;
		}

		// ????????¨???????????????????±???????
		static Point get_cross_point(Line s1, Line s2){
			Point base_v = s2.p2 - s2.p1;
			double d1 = Math.Abs (cross (base_v, s1.p1 - s2.p1));
			double d2 = Math.Abs (cross (base_v, s1.p2 - s2.p1));
			double t = d1 / (d1 + d2);
			return s1.p1 + (s1.p2 - s1.p1) * t;
		}

		// ?°???±
		static void CGL_1_A(){
			double[] d = input_line ();
			Line l = new Line(d[0], d[1], d[2], d[3]);

			int q = int.Parse(Console.ReadLine());
			for (int i = 0; i < q; i++) {
				double[] p_pos = input_line ();
				Point p1 = new Point (p_pos[0], p_pos[1]);
				Point p2 = project (l, p1);
				Console.WriteLine ("{0} {1}", p2.x, p2.y);
			}
		}

		// ????°?
		static void CGL_1_B(){
			double[] d = input_line ();
			Line l = new Line(d[0], d[1], d[2], d[3]);

			int q = int.Parse(Console.ReadLine());
			for (int i = 0; i < q; i++) {
				double[] p_pos = input_line ();
				Point p1 = new Point (p_pos [0], p_pos [1]);
				Point p2 = reflect (l, p1);
				Console.WriteLine ("{0} {1}", p2.x, p2.y);
			}
		}

		// ???????¨???????
		static void CGL_1_C(){
			double[] d = input_line ();
			Point p0 = new Point (d [0], d [1]);
			Point p1 = new Point (d [2], d [3]);

			int q = int.Parse(Console.ReadLine());
			for (int i = 0; i < q; i++) {
				double[] p_pos = input_line ();
				Point p2 = new Point (p_pos [0], p_pos [1]);
				string s;
				int c = ccw (p0, p1, p2);
				if (c == 1) {
					s = "COUNTER_CLOCKWISE";
				} else if (c == -1) {
					s = "CLOCKWISE";
				} else if (c == 2) {
					s = "ONLINE_BACK";
				} else if (c == -2) {
					s = "ONLINE_FRONT";
				} else {
					s = "ON_SEGMENT";
				}
				Console.WriteLine ("{0}", s);
			}
		}

		// ??´????????´???/????????????
		static void CGL_2_A(){
			int q = int.Parse(Console.ReadLine());
			for (int i = 0; i < q; i++) {
				double[] s_pos = input_line ();
				Line s1 = new Line(s_pos[0], s_pos[1], s_pos[2], s_pos[3]);
				Line s2 = new Line(s_pos[4], s_pos[5], s_pos[6], s_pos[7]);
				if (is_parallel (s1, s2)) {
					Console.Write ("2\n");
				} else if (is_orthogonal (s1, s2)) {
					Console.Write ("1\n");
				} else {
					Console.Write ("0\n");
				}
			}
		}

		// ?????????????????????
		static void CGL_2_B(){
			int q = int.Parse(Console.ReadLine());
			for (int i = 0; i < q; i++) {
				double[] s_pos = input_line ();
				Line s1 = new Line(s_pos[0], s_pos[1], s_pos[2], s_pos[3]);
				Line s2 = new Line(s_pos[4], s_pos[5], s_pos[6], s_pos[7]);

				if (is_intersect (s1, s2)) {
					Console.Write ("1\n");
				} else {
					Console.Write ("0\n");
				}
			}
		}

		// ???????????????
		static void CGL_2_C(){
			int q = int.Parse(Console.ReadLine());
			for (int i = 0; i < q; i++) {
				double[] s_pos = input_line ();
				Line s1 = new Line(s_pos[0], s_pos[1], s_pos[2], s_pos[3]);
				Line s2 = new Line(s_pos[4], s_pos[5], s_pos[6], s_pos[7]);

				Point cp = get_cross_point (s1, s2);
				Console.Write ("{0} {1}\n", cp.x, cp.y);
			}
		}

		// ?????¢
		static void CGL_2_D(){
			int q = int.Parse(Console.ReadLine());
			for (int i = 0; i < q; i++) {
				double[] s_pos = input_line ();
				Line s1 = new Line(s_pos[0], s_pos[1], s_pos[2], s_pos[3]);
				Line s2 = new Line(s_pos[4], s_pos[5], s_pos[6], s_pos[7]);

				Console.Write ("{0}\n", get_distance_s2s(s1, s2));
			}
		}

		public static void Main (string[] args){
			// ?°???±
			//CGL_1_A ();
			// ????°?
			//CGL_1_B ();
			// ???????¨???????
			//CGL_1_C ();
			// ??´????????´???/????????????
			//CGL_2_A ();
			// ?????????????????????
			//CGL_2_B ();
			// ???????????????
			CGL_2_C ();
			// ?????¢
			//CGL_2_D ();
		}
	}
}

Measured memory_bytes: 9760