#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int mod = 1e9 + 7;
const int inf = (1 << 30) - 1;
const ll infll = (1LL << 61) - 1;

using Real = double;
using Point = complex<Real>;
const Real Pi = acos(-1), EPS = 1e-9;
inline bool eq(Real a, Real b) { return fabs(a - b) < EPS; }

//scalar
Point operator*(const Point &p, const Real &c)
{
    return Point(c * real(p), c * imag(p));
}

//add
Point operator+(const Point &p, const Point &q)
{
    return Point(real(p) + real(q), imag(p) + imag(q));
}

Point operator-(const Point &p, const Point &q)
{
    return Point(real(p) - real(q), imag(p) - imag(q));
}

//equal
bool operator==(const Point &p, const Point &q)
{
    return (real(p) == real(q)) && (imag(p) == imag(q));
}

Real radian_to_degree(Real r)
{
    return (r * 180.0 / Pi);
}

Real degree_to_radian(Real d)
{
    return (d * Pi / 180.0);
}

//rotate
Point rot(Real theta, const Point &p)
{
    return Point(cos(theta) * p.real() - sin(theta) * p.imag(), sin(theta) * p.real() + cos(theta) * p.imag());
}

// norm
Real norm(const Point &p)
{
    return (real(p) * real(p) + imag(p) * imag(p));
}

Real abs(const Point &p)
{
    return sqrt(norm(p));
}
//argumant [0, 2 * Pi)
Real arg(const Point &p)
{
    Real a = atan2(imag(p), real(p));
    if (a < 0)
        a = fabs(a) + Pi;
    return a;
}

Real dot(const Point &p, const Point &q)
{
    return (real(p) * real(q) + imag(p) * imag(q));
}

// regard z - component is zero
Real cross(const Point &p, const Point &q)
{
    return real(p) * imag(q) - imag(p) * real(q);
}

//input
istream &operator>>(istream &is, Point &p)
{
    Real a, b;
    is >> a >> b;
    p = Point(a, b);
    return is;
}

//output
ostream &operator<<(ostream &os, Point &p)
{
    os << fixed << setprecision(10) << p.real() << " " << p.imag();
}

// a line given two points
struct Line
{
    Point a, b;
    Line() = default;

    Line(Point a, Point b) : a(a), b(b) {}

    // Ax + By = C
    Line(Real A, Real B, Real C)
    {
        if (eq(A, 0))
            a = Point(0, C / B), b = Point(1, C / B);
        else if (eq(B, 0))
            b = Point(C / A, 0), b = Point(C / A, 1);
        else
            a = Point(0, C / B), b = Point(C / A, 0);
    }

    friend istream &operator>>(istream &is, Line &a)
    {
        return is >> a.a >> a.b;
    }

    friend ostream &operator<<(ostream &os, Line &p)
    {
        return os << p.a << " to " << p.b;
    }
};

using Points = vector<Point>;
using Polygon = vector<Point>;
using Lines = vector<Line>;

//For given three points p1,p2,p, find the projection point x of p onto p1p2.
Point projection(const Line &l, const Point &p)
{
    double t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b); // direction vector
    return l.a + (l.a - l.b) * t;
}

//For given three points p1,p2,p, find the reflection point x of p onto p1p2.
Point reflection(const Line &l, const Point &p)
{
    return p + (projection(l, p) - p) * 2.0;
}

// Counter_Clockwise, a is standard point
int ccw(const Point &a, Point b, Point c)
{
    b = b - a, c = c - a;
    if (cross(b, c) > EPS)
        return +1; // counter clockwise
    if (cross(b, c) < -EPS)
        return -1; // clockwise
    if (dot(b, c) < 0)
        return +2; // c--a--b on line
    if (norm(b) < norm(c))
        return -2; // a--b--c on line
    return 0;      // c on segment a-b
}

// two lines are parallel
bool Parallel(const Line &L1, const Line &L2)
{
    return eq(cross(L1.b - L1.a, L2.b - L2.a), 0.0);
}

// two lines are orthogonal
bool Orthogonal(const Line &L1, const Line &L2)
{
    return eq(dot(L1.b - L1.a, L2.b - L2.a), 0.0);
}

// check existence of intersection at the lines
bool intersect(const Line &L1, const Line &L2)
{
    // non-parallel || same line
    bool r = (abs(cross(L1.b - L1.a, L2.b - L2.a)) < EPS) || (abs(cross(L1.b - L1.a, L2.a - L1.a)) < EPS);
    return r;
}

// cross point of two lines
Point CrossPoint(const Line &L1, const Line &L2)
{
    Real A = cross(L1.b - L1.a, L2.b - L2.a);
    Real B = cross(L1.b - L1.a, L1.b - L2.a);
    if (abs(A) < EPS && abs(B) < EPS)
        return L1.a; // same line
    if (abs(A) < EPS)
        assert(false); // precondition !!!
    return L2.a + B / A * (L2.b - L2.a);
}

struct Segment : Line
{
    Segment() = default;

    Segment(Point a, Point b) : Line(a, b) {}
};

using segments = vector<Segment>;

// check existence of intersection at the segments
bool intersect(const Segment &s, const Segment &t)
{
    bool r = ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
    return r;
}

bool intersect(const Line &l, const Point &p)
{
    return abs(ccw(l.a, l.b, p)) != 1;
}

bool intersect(const Segment &s, const Point &p)
{
    return ccw(s.a, s.b, p) == 0;
}

bool intersect(const Line &l, const Segment &s)
{
    return cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < EPS;
}

Point CrossPoint(const Segment &s, const Segment &t)
{
    return CrossPoint(Line(s), Line(t));
}

Real distance(const Point &a, const Point &b)
{
    return abs(a - b);
}

Real distance(const Line &L, const Point &p)
{
    return abs(p - projection(L, p));
}

Real distance(const Line &l, const Line &m)
{
    return intersect(l, m) ? 0 : distance(l, m.a);
}

Real distance(const Segment &s, const Point &p)
{
    Point r = projection(s, p);
    if (intersect(s, r))
        return abs(r - p);
    return min(abs(s.a - p), abs(s.b - p));
}

Real distance(const Segment &a, const Segment &b)
{
    if (intersect(a, b))
        return 0;
    return min({distance(a, b.a), distance(a, b.b), distance(b, a.a), distance(b, a.b)});
}



int main()
{
    int Q;
    cin >> Q;
    for (int i = 0; i < Q; i++)
    {
        Segment S, T;
        cin >> S >> T;
        Real ans = distance(S, T);
        cout << fixed << setprecision(10) << ans << endl;
    }
}


Measured memory_bytes: 3304