using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using static System.Console;
using static System.Math;
using static MyIO;
using static MyUtil;

using static Geometory;
using Vector = Geometory.Point;
using Line = Geometory.Segment;

public class D
{
	public static void Main() => (new Solver()).Solve();
}

public class Solver
{
	public void Solve()
	{
		int Q = GetInt();
		var ans = new string[Q];
		for(int i = 0; i < Q; i++)
			ans[i] = solve();

		WriteLine(string.Join("\n", ans));
	}

	private string solve()
	{
		var p1 = new Point(GetDouble(), GetDouble());
		var p2 = new Point(GetDouble(), GetDouble());
		var p3 = new Point(GetDouble(), GetDouble());
		var p4 = new Point(GetDouble(), GetDouble());
		var s1 = new Segment(p1, p2);
		var s2 = new Segment(p3, p4);
		return $"{GetDistance(s1, s2):F12}";
	}
}

public static class Geometory
{
	private const double EPS = 1e-10;
	public static bool Equals(double a, double b) => Math.Abs(a - b) < EPS;

	public class Point
	{
		public double X;
		public double Y;		
		public Point(double x, double y)
		{
			X = x;
			Y = y;
		}
	
		public static Point operator+(Point p, Point q) => new Point(p.X + q.X, p.Y + q.Y);
		public static Point operator-(Point p, Point q) => new Point(p.X - q.X, p.Y - q.Y);
		public static Point operator*(Point p, double a) => new Point(a * p.X, a * p.Y);
		public static Point operator*(double a, Point p) => new Point(a * p.X, a * p.Y);
		public static Point operator/(Point p, double a) => new Point(p.X / a, p.Y / a);
	}

	public class Segment
	{
		public Point P1;
		public Point P2;
		public Segment(Point p1, Point p2)
		{
			P1 = p1;
			P2 = p2;
		}
	}

	public static double Abs(Vector a) => Math.Sqrt(Norm(a));
	public static double Norm(Vector a) => a.X * a.X + a.Y * a.Y;
	public static double Dot(Vector a, Vector b) => a.X * b.X + a.Y * b.Y;
	public static double Cross(Vector a, Vector b) => a.X * b.Y - a.Y * b.X;

	public static bool IsOrthogonal(Vector a, Vector b) => Equals(Dot(a, b), 0.0);
	public static bool IsOrthogonal(Point a1, Point a2, Point b1, Point b2) => IsOrthogonal(a1 - a2, b1 - b2);
	public static bool IsOrthogonal(Segment s1, Segment s2) => Equals(Dot(s1.P2 - s1.P1, s2.P2 - s2.P1), 0.0);
	public static bool IsParallel(Vector a, Vector b) => Equals(Cross(a, b), 0.0);
	public static bool IsParallel(Point a1, Point a2, Point b1, Point b2) => IsParallel(a1 - a2, b1 - b2);
	public static bool IsParallel(Segment s1, Segment s2) => Equals(Cross(s1.P2 - s1.P1, s2.P2 - s2.P1), 0.0);

	public static Point Project(Segment s, Point p)
	{
		Vector b = s.P2 - s.P1;
		double r = Dot(p - s.P1, b) / Norm(b);
		return s.P1 + b * r;
	}
	public static Point Reflect(Segment s, Point p) => p + (Project(s, p) - p) * 2.0;

	public static double GetDistance(Point a, Point b) => Abs(a - b);
	public static double GetDistanceLP(Line l, Point p) => Math.Abs(Cross(l.P2 - l.P1, p - l.P1) / Abs(l.P2 - l.P1));
	public static double GetDistanceSP(Segment s, Point p)
	{
		if(Dot(s.P2 - s.P1, p - s.P1) < 0.0) return Abs(p - s.P1);
		if(Dot(s.P1 - s.P2, p - s.P2) < 0.0) return Abs(p - s.P2);
		return GetDistanceLP(s, p);
	}
	public static double GetDistance(Segment s1, Segment s2)
	{
		if(Intersect(s1, s2)) return 0.0;
		return Math.Min(Math.Min(GetDistanceSP(s1, s2.P1), GetDistanceSP(s1, s2.P2)),
		                Math.Min(GetDistanceSP(s2, s1.P1), GetDistanceSP(s2, s1.P2)));
	}

	public const int COUNTER_CLOCKWISE = 1;
	public const int CLOCKWISE = -1;
	public const int ONLINE_BACK = 2;
	public const int ONLINE_FRONT = -2;
	public const int ON_SEGMENT = 0;
	public static int Ccw(Point p0, Point p1, Point p2)
	{
		Vector a = p1 - p0;
		Vector b = p2 - p0;
		if(Cross(a, b) > EPS) return COUNTER_CLOCKWISE;
		if(Cross(a, b) < -EPS) return CLOCKWISE;
		if(Dot(a, b) < -EPS) return ONLINE_BACK;
		if(Norm(a) < Norm(b)) return ONLINE_FRONT;
		return ON_SEGMENT;
	}
	public static bool Intersect(Point p1, Point p2, Point p3, Point p4)
	{
		return (Ccw(p1, p2, p3) * Ccw(p1, p2, p4) <= 0 && 
		        Ccw(p3, p4, p1) * Ccw(p3, p4, p2) <= 0);
	}
	public static bool Intersect(Segment s1, Segment s2) => Intersect(s1.P1, s1.P2, s2.P1, s2.P2);
}

public static class MyIO
{
	private static string[] args = null;
	private static int num = -1;
	private static int used = -1;

	private static string getArg()
	{
		if(used == num)
		{
			args = Console.ReadLine().Split(' ');
			num = args.Length;
			used = 0;
		}
		return args[used++];
	}

	public static int GetInt() => int.Parse(getArg());
	public static long GetLong() => long.Parse(getArg());
	public static double GetDouble() => double.Parse(getArg());
	public static decimal GetDecimal() => decimal.Parse(getArg());
	public static string GetString() => getArg();
	public static char GetChar() => getArg()[0];
	public static int[] GetInts(long N) => Enumerable.Range(0, (int)N).Select(_ => GetInt()).ToArray();
	public static long[] GetLongs(long N) => Enumerable.Range(0, (int)N).Select(_ => GetLong()).ToArray();
	public static double[] GetDoubles(long N) => Enumerable.Range(0, (int)N).Select(_ => GetDouble()).ToArray();
	public static decimal[] GetDecimals(long N) => Enumerable.Range(0, (int)N).Select(_ => GetDecimal()).ToArray();
	public static string[] GetStrings(long N) => Enumerable.Range(0, (int)N).Select(_ => GetString()).ToArray();
}

public static class MyUtil
{
	public static void chmax<T>(ref T x, T y) where T : IComparable<T>
	{
		if(x.CompareTo(y) < 0)
			x = y;
	}

	public static void chmin<T>(ref T x, T y) where T : IComparable<T>
	{
		if(x.CompareTo(y) > 0)
			x = y;
	}

	public static void swap<T>(ref T x, ref T y)
	{
		T tmp = x;
		x = y;
		y = tmp;
	}
}


Measured memory_bytes: 18080