#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;

const double eps = 1e-15;

bool IsEq(double d1, double d2)
{
    if (d1 - d2 > -eps && d1 - d2 < eps){
        return true;
    } else {
        return false;
    }
}

class Point2D {
public:
    double x, y;
    Point2D() : x(0), y(0) {}
    Point2D(double _x, double _y) : x(_x), y(_y) {}
    virtual ~Point2D() {}
};

istream& operator >> (istream& input, Point2D& P)
{
    input >> P.x >> P.y;
    return input;
}

class Segment {
public:
    Point2D P, Q;
    Segment() {}
    Segment(const Point2D& _P, const Point2D& _Q) : P(_P), Q(_Q) {}
};

istream& operator >> (istream& input, Segment& Seg)
{
    input >> Seg.P >> Seg.Q;
    return input;
}

class Vector2D : public Point2D {
public:
    Vector2D(double _x, double _y) : Point2D(_x, _y) {}
    Vector2D(const Point2D& P) : Point2D(P) {}
    Vector2D(const Segment& Seg) : Point2D(Seg.Q.x - Seg.P.x, Seg.Q.y - Seg.P.y) {}
    Vector2D(const Point2D& Start, const Point2D& End) : Point2D(End.x - Start.x, End.y - Start.y) {}
    double InnerProd(const Vector2D Vec) const
    {
        return x * Vec.x + y * Vec.y;
    }
    double OuterProd(const Vector2D Vec) const
    {
        return x * Vec.y - y * Vec.x;
    }
    double Length() const
    {
        return sqrt((*this).InnerProd(*this));
    }
};

Vector2D operator * (double d, const Vector2D& V)
{
    return Vector2D(d * V.x, d * V.y);
}

Vector2D operator + (const Vector2D& V1, const Vector2D& V2)
{
    return Vector2D(V1.x + V2.x, V1.y + V2.y);
}

ostream& operator << (ostream& out, const Vector2D& V)
{
    out << V.x << " " << V.y;
    return out;
}

double Dist(const Point2D& P, const Point2D& Q)
{
    Vector2D V(P, Q);
    return V.Length();
}

bool IsPara(const Segment& Seg1, const Segment& Seg2)
{
    Vector2D V1(Seg1), V2(Seg2);
    return IsEq(V1.OuterProd(V2), 0.);
}

bool IsOnSeg(const Point2D& P, const Segment& Seg)
{
    Vector2D V(Seg);
    return IsEq(V.Length(), Dist(P, Seg.P) + Dist(P, Seg.Q));
}

bool IsIntersect(const Segment& Seg1, const Segment& Seg2) {
    Vector2D P1(Seg1.P), P2(Seg2.P);
    Vector2D V1(Seg1), V2(Seg2);
    if (!IsPara(Seg1, Seg2)) {
        double t = (P2.OuterProd(V2) - P1.OuterProd(V2)) / V1.OuterProd(V2);
        double s = (P2.OuterProd(V1) - P1.OuterProd(V1)) / V1.OuterProd(V2);
        return t > -eps && t < 1 + eps && s > -eps && s < 1 + eps;
    } else {
        if (IsOnSeg(Seg1.P, Seg2) || IsOnSeg(Seg1.Q, Seg2) || IsOnSeg(Seg2.P, Seg1) || IsOnSeg(Seg2.Q, Seg1)) return true;
        return false;
    }
}

Vector2D CrossPoint(const Segment& Seg1, const Segment& Seg2) {
    Vector2D P1(Seg1.P), P2(Seg2.P);
    Vector2D V1(Seg1), V2(Seg2);
    if (!IsPara(Seg1, Seg2)) {
        double t = (P2.OuterProd(V2) - P1.OuterProd(V2)) / V1.OuterProd(V2);
        return P1 + t * V1;
    } else {
        return Point2D();
    }
}

double Dist(const Point2D& P, const Segment& Seg) {
    Vector2D V1(Seg);
    Vector2D V2(Seg.P, P);
    double IP = V1.InnerProd(V2);
    if (IP < 0.) {
        return Dist(P, Seg.P);
    } else if (IP > V1.InnerProd(V1)) {
        return Dist(P, Seg.Q);
    } else {
        return fabs(V1.OuterProd(V2)) / V1.Length();
    }
}

double Dist(const Segment& Seg1, const Segment& Seg2) {
    if (IsIntersect(Seg1, Seg2)) return 0.;
    double Ret = Dist(Seg1.P, Seg2);
    Ret = min(Ret, Dist(Seg1.Q, Seg2));
    Ret = min(Ret, Dist(Seg2.P, Seg1));
    Ret = min(Ret, Dist(Seg2.Q, Seg1));
    return Ret;
}

int main(int argc, const char * argv[]) {
    int q;
    Segment Seg1, Seg2;
    cin >> q;
    for (int i = 0; i < q; ++i) {
        cin >> Seg1 >> Seg2;
        cout << fixed << setprecision(15) << Dist(Seg1, Seg2) << endl;
    }
    return 0;
}



Measured memory_bytes: 3284