#include<bits/stdc++.h>
#define mset(a,b) memset(a,b,sizeof(a))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef long long ll;
const ll maxn=1e4+200;
const int inf=0x3f3f3f3f;
const double EPS=1e-10;
//typedef pair<int,int> PA;
double add(double a,double b){//考虑误差的加法运算
    if(abs(a+b)<EPS*(abs(a)+abs(b))) return  0;
    return a+b;
}
int sgn(double x){
    if(abs(x)<EPS)  return 0;
    if(x<0) return -1;
    else return 1;
}
class Point{
public:
    double x,y;
    Point(){}
    Point(double x,double y):x(x),y(y){
    }
    Point operator+ (Point p){
        return Point(add(x,p.x),add(y,p.y));
    }
    Point operator -(Point p){
        return Point(add(x,-p.x),add(y,-p.y));
    }
    Point operator *(double d){
        return Point(x*d,y*d);
    }
    double operator *(Point p){
        return add(x*p.x,y*p.y);//外积
    }
    double operator ^(Point p){//内积
        return add(x*p.y,-y*p.x);
    }
    double det(Point p){
     return add(x*p.y,-y*p.x);
    }
    double len(){
        return sqrt(add(x*x,y*y));
    }
};
class Line{
public:
    Point s,e;
    Line(){}
    Line(Point s,Point e):s(s),e(e){}
};
bool onSge(Line l,Point q){
    return ((l.s-q)^(l.e-q))==0&&((l.s-q)*(l.e-q))<=0;
}
Point operator *(double d,Point p){
    return Point(p.x*d,p.y*d);
}
Point getProject(Point p1,Point p2,Point q){//q 在直线p1,p2上的投影坐标
    double d1=1.0/(p2-p1).len();
    Point ans=(q-p1)*(p2-p1)*(p2-p1)*d1*d1;
    return ans+p1;
}
Point getReflect(Point p1,Point p2,Point q){//q 关于直线p1 p2的 反射坐标
    return 2.0*getProject(p1,p2,q)-q;
}
double getDisPP(Point a,Point b){//两点之间距离
    return (b-a).len();
}
double getDisPL(Line l,Point p){//点到直线距离
    Point x=getProject(l.s,l.e,p);
    return (p-x).len();
}
double getDisPS(Line l,Point p){//点到线段最短距离
    Point x=getProject(l.s,l.e,p);
    if(onSge(l,x))
        return (x-p).len();
    else
        return min((p-l.s).len(),(p-l.e).len());

}
double getDisSS(Line la,Line lb){//保证两线段不相交 isInterSS==false
    return min(min(getDisPS(la,lb.s),getDisPS(la,lb.e)),
			min(getDisPS(lb,la.s),getDisPS(lb,la.e)));
}

int getDirPPP(Point p,Point p1,Point p2){
    return sgn((p1-p)^(p2-p));//1代表 p2在p1的逆时针方向  0共线 ，-1是p2在p1的顺时针方向
}
int getStatePP(Point p,Point p1,Point p2){//返回 p2 关于p 在p1的什么方向
        int a=sgn((p1-p)^(p2-p));
        int b=sgn((p1-p)*(p2-p));
        if(a>0){//
            puts("COUNTER_CLOCKWISE");
        }
        else if(a<0){
            puts("CLOCKWISE");
        }
        else if(b<0){
            puts("ONLINE_BACK");
        }
        else if(b>0&&sgn((p1-p)*(p2-p1))>0){
            puts("ONLINE_FRONT");
        }
        else{
            puts("ON_SEGMENT");
        }
        return 0;
}
bool isInterSS(Line la,Line lb){//线段是否想交
    int d1=getDirPPP(lb.s,lb.e,la.s);
    int d2=getDirPPP(lb.s,lb.e,la.e);
    int d3=getDirPPP(la.s,la.e,lb.s);
    int d4=getDirPPP(la.s,la.e,lb.e);
    if(d1*d2<0&&d3*d4<0)
        return true;
    else if(d1==0&&onSge(lb,la.s))
        return true;
    else if(d2==0&&onSge(lb,la.e))
        return true;
    else if(d3==0&&onSge(la,lb.s))
        return true;
    else if(d4==0&&onSge(la,lb.e))
        return true;
    else
        return false;

}
int getStateLL(Line la,Line lb){//两个直线 垂直，相交或者平行
    if(sgn((la.e-la.s)^(lb.e-lb.s))==0){
        return 2;//平行
    }//两向量平行 内积为0
    else if(sgn((la.e-la.s)*(lb.e-lb.s))==0){
        return 1;//垂直
    }
    else return 0;
}
typedef Point P;
Point getInterLL(Point p1,Point p2,Point q1, Point q2){//得到直线交点
    return p1+(p2-p1)*((q2-q1).det(q1-p1)/(q2-q1).det(p2-p1));
}
int main(){
    int q;
    P p0,p1,p2,p3;
    scanf("%d",&q);
    while(q--){
        scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&p0.x,&p0.y,&p1.x,&p1.y,&p2.x,&p2.y,&p3.x,&p3.y);
        if(isInterSS(Line(p0,p1),Line(p2,p3))){
            printf("%.10f\n",0.0);
            continue;
        }
        printf("%.10f\n",getDisSS(Line(p0,p1),Line(p2,p3)));
    }
    return 0;
}


Measured memory_bytes: 3256