#include <iostream>
#include <math.h>
#include <stdio.h>
#include <vector>

using namespace std;

// 2次元ベクトルクラス
class Vector {
public:
    double x, y;
    
    // コンストラクタ
    Vector() {
        x = 0.0;
        y = 0.0;
    }
    
    // コンストラクタ(引数あり)
    Vector(double nx, double ny) {
        x = nx;
        y = ny;
    }
    
    // x,y成分を設定する
    void set(double nx, double ny) {
        x = nx;
        y = ny;
    }
    
    // 内積を求める
    double dot(const Vector& vec) const {
        return x * vec.x + y * vec.y;
    }
    
    // 外積を求める
    double cross(const Vector& vec) const {
        return x * vec.y - y * vec.x;
    }
    
    // 余弦を求める
    double getCos(const Vector& vec) const {
        double nor = norm() * vec.norm();
        if (nor == 0.0) {
            return 0.0;
        } else {
            return dot(vec) / nor;
        }
    }
    
    // ベクトルの大きさを求める
    double norm() const {
        return sqrt(x * x + y * y);
    }
    
    // 単位ベクトルを返す
    Vector getUnit() const {
        Vector v;
        double n = norm();
        if (n == 0.0) {
            v.set(0.0, 0.0);
        } else {
            v.set(x / n, y / n);
        }
        return v;
    }
    
    void operator = (const Vector& vec) {
        x = vec.x;
        y = vec.y;
    }
    
    Vector operator + (const Vector& vec) const {
        Vector v(x + vec.x, y + vec.y);
        return v;
    }
    
    Vector operator - (const Vector& vec) const {
        Vector v(x - vec.x, y - vec.y);
        return v;
    }
    
    Vector operator * (const Vector& vec) const {
        Vector v(x * vec.x, y * vec.y);
        return v;
    }
    
    Vector operator * (double f) const {
        Vector v(x * f, y * f);
        return v;
    }
    
    Vector operator / (const Vector& vec) const {
        Vector v;
        if (vec.x == 0.0) {
            v.x = 0.0;
        } else {
            v.x = x / vec.x;
        }
        
        if (vec.y == 0.0) {
            v.y = 0.0;
        } else {
            v.y = y / vec.y;
        }
        return v;
    }
    
    Vector operator / (double f) const {
        Vector v;
        if (f == 0.0) {
            v.set(0.0, 0.0);
        } else {
            v.set(x / f, y / f);
        }
        return v;
    }
    
    void operator += (const Vector& vec) {
        x += vec.x;
        y += vec.y;
    }
    
    void operator -= (const Vector& vec) {
        x -= vec.x;
        y -= vec.y;
    }
    
    void operator *= (const Vector& vec) {
        x *= vec.x;
        y *= vec.y;
    }
    
    void operator /= (const Vector& vec) {
        if (vec.x == 0.0) {
            x = 0.0;
        } else {
            x /= vec.x;
        }
        
        if (vec.y == 0.0) {
            y = 0.0;
        } else {
            y /= vec.y;
        }
    }
    
    bool operator == (const Vector& vec) const {
        if (x == vec.x && y == vec.y) {
            return true;
        } else {
            return false;
        }
    }
};

// ベクトル1をベクトル2に正射影したベクトルを求める
static Vector getProjection(const Vector& vec1, const Vector& vec2) {
    Vector vec(vec2.getUnit() * vec1.norm() * vec1.getCos(vec2));
    return vec;
}


class LineSegment {
private:
    Vector start; // 始点
    Vector end; // 終点
    
public:
    //コンストラクタ
    LineSegment () {}
    
    // 始点と終点を設定する
    void setStartEnd(double sx, double sy, double ex, double ey) {
        start.set(sx, sy);
        end.set(ex, ey);
    }
    
    // 始点を取得する
    Vector getStart() const {
        return start;
    }
    
    //　終点を取得する
    Vector getEnd() const {
        return end;
    }
    
    // 指定の線分を含むか
    // このメソッドは線分同士が平行の時しか使用しない
    bool isInLine(const LineSegment& l) const {
        bool b1 = isPointInLine(l.getStart());
        bool b2 = isPointInLine(l.getEnd());
        if (b1 || b2) {
            return true;
        } else {
            return false;
        }
    }
    
    // 指定の点を線分の中に含むか
    bool isPointInLine(const Vector& p) const {
        if (start == p) {
            return true;
        }
        
        Vector l1 = end - start;
        Vector l2 = p - start;
        Vector u1 = l1.getUnit();
        Vector u2 = l2.getUnit();

        if (u1 == u2 && l2.norm() <= l1.norm()) {
            return true;
        } else {
            return false;
        }
    }
    
    // 指定の線分と交差しているか
    // @return 0(交差していない), 1(交差している)
    int isCross(const LineSegment& l) const {
        Vector l1 = end - start;
        double c1 = l1.cross(l.getStart() - start);
        double c2 = l1.cross(l.getEnd() - start);
        
        Vector l2 = l.getEnd() - l.getStart();
        double c3 = l2.cross(start - l.getStart());
        double c4 = l2.cross(end - l.getStart());
        
        if (c1 * c2 == 0.0 && c3 * c4 == 0.0) { // 平行のとき
            LineSegment ls;
            ls.setStartEnd(start.x, start.y, end.x, end.y);
            if (isInLine(l) || l.isInLine(ls)) {
                return 1;
            }
            return 0;
        } else if ((c1 * c2 < 0.0 && c3 * c4 <= 0.0)
                   || (c1 * c2 <= 0.0 && c3 * c4 < 0.0)
                   || (c1 * c2 < 0.0 && c3 * c4 < 0.0)) { // 交差するとき
            return 1;
        } else { // 交差しないとき
            return 0;
        }
    }
    
    // 任意の点が線分の始点より外にあるか
    bool isOutOfStart(const Vector& vec) const {
        Vector p = end - start;
        Vector q = vec - start;
        double d = p.dot(q);
        if (d < 0) { // 内積が負のとき
            return true;
        }
        return false;
    }
    
    // 任意の線分との距離を求める
    double getDistance(const LineSegment& l) const {
        if (isCross(l)) { // 交差しているとき
            return 0.0;
        }
        double dis1 = getDistance(l.getStart());
        double dis2 = getDistance(l.getEnd());
        LineSegment ls;
        ls.setStartEnd(start.x, start.y, end.x, end.y);
        double dis3 = l.getDistance(ls.getStart());
        double dis4 = l.getDistance(ls.getEnd());
        double min1 = min(dis1, dis2);
        double min2 = min(dis3, dis4);
        return min(min1, min2);
    }
    
    // 任意の点との距離を求める
    double getDistance(const Vector& vec) const {
        if (isPointInLine(vec)) { // 線分内に点を含むとき
            return 0.0;
        }
        if (!isOutOfStart(vec)) { // 線分の始点より内側に点があるとき
            Vector p = end - start;
            Vector q = vec - start;
            Vector proj = getProjection(q, p);
            if (p.norm() > proj.norm()) { // 正射影したベクトルが線分より短いとき
                return (q - proj).norm();
            } else { // 正射影したベクトルが線分と等しいか、長いとき
                return (vec - end).norm();
            }
        } else { // 線分の始点より外にあるとき
            return (vec - start).norm();
        }
    }
};

int main() {
    int n;
    cin >> n;
    
    LineSegment l1, l2;
    vector<double> result;
    for (int i = 0; i < n; i++) {
        double sx1, sy1, ex1, ey1, sx2, sy2, ex2, ey2;
        cin >> sx1 >> sy1 >> ex1 >> ey1 >> sx2 >> sy2 >> ex2 >> ey2;
        l1.setStartEnd(sx1, sy1, ex1, ey1);
        l2.setStartEnd(sx2, sy2, ex2, ey2);
        result.push_back(l1.getDistance(l2));
    }
    
    for (int i = 0; i < result.size(); i++) {
        printf("%.10f\n", result[i]);
    }
    return 0;
}


Measured memory_bytes: 3312