#include <algorithm>
#include <array>
#include <assert.h>
#include <bitset>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstring>
#include <functional>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <istream>

#include <map>
#include <math.h>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

namespace asl
{
    
    template <typename numeric_type>
    class point
    {
    public:
        numeric_type x, y;

        point(numeric_type x = 0, numeric_type y = 0) : x(x), y(y) {}

        point<numeric_type> &operator+=(const point<numeric_type> &ri)
        {
            x += ri.x;
            y += ri.y;
            return *this;
        }

        point<numeric_type> &operator-=(const point<numeric_type> &ri)
        {
            x -= ri.x;
            y -= ri.y;
            return *this;
        }

        point<numeric_type> &operator*=(const point<numeric_type> &ri)
        {
            auto _x = x * ri.x - y * ri.y;
            auto _y = x * ri.y + y * ri.x;
            x = _x;
            y = _y;
            return *this;
        }

        friend point<numeric_type> operator+(const point<numeric_type> &a, const point<numeric_type> &b)
        {
            return point<numeric_type>(a) += b;
        }

        friend point<numeric_type> operator-(const point<numeric_type> &a, const point<numeric_type> &b)
        {
            return point<numeric_type>(a) -= b;
        }

        friend point<numeric_type> operator*(const point<numeric_type> &a, const point<numeric_type> &b)
        {
            return point<numeric_type>(a) *= b;
        }

    };

    template <typename numeric_type>
    std::istream &operator>>(std::istream &is, point<numeric_type> &p)
    {
        return is >> p.x >> p.y;
    }

    template <typename numeric_type>
    numeric_type norm(point<numeric_type> a)
    {
        return a.x * a.x + a.y * a.y;
    }

    template <typename numeric_type, typename float_type = double>
    float_type abs(point<numeric_type> a)
    {
        return sqrtl(norm(a));
    }

    template <typename numeric_type>
    class line
    {
    public:
        point<numeric_type> p, q;

    };

    template <typename numeric_type>
    std::istream &operator>>(std::istream &is, line<numeric_type> &l)
    {
        return is >> l.p >> l.q;
    }

    template <typename numeric_type>
    using segment = line<numeric_type>;

    template <typename numeric_type>
    numeric_type cross(point<numeric_type> a, point<numeric_type> b)
    {
        return a.x * b.y - a.y * b.x;
    }

    template <typename numeric_type>
    numeric_type dot(point<numeric_type> a, point<numeric_type> b)
    {
        return a.x * b.x + a.y * b.y;
    }

    enum PointOrder
    {
        CounterClockwise = +1,
        Clockwise = -1,
        AlignedFirst = +2,
        AlignedLast = -2,
        AlignedIn = 0,
    };

    template <typename numeric_type>
    PointOrder ccw(point<numeric_type> a, point<numeric_type> b, point<numeric_type> c)
    {
        b -= a;
        c -= a;
        if (cross(b, c) > 0)
            return PointOrder::CounterClockwise;
        else if (cross(b, c) < 0)
            return PointOrder::Clockwise;
        else if (dot(b, c) < 0)
            return PointOrder::AlignedFirst; 
        else if (dot(b, b) < dot(c, c))
            return PointOrder::AlignedLast; 
        else
            return PointOrder::AlignedIn; 
    }

    template <const int eps_exp = 9>
    int sign(double v)
    {
        const double eps = std::pow(10, -eps_exp);

        if (v < -eps)
            return -1;
        else if (v > eps)
            return +1;
        else
            return 0;
    }

} 

#include <stdint.h>

#include <experimental/optional>

namespace asl
{
    
    template <typename numeric_type>
    bool intersect_segment_segment(const segment<numeric_type> &s, const segment<numeric_type> &t)
    {
        return ccw(s.p, s.q, t.p) * ccw(s.p, s.q, t.q) <= 0 && ccw(t.p, t.q, s.p) * ccw(t.p, t.q, s.q) <= 0;
    }

    template <typename numeric_type>
    bool intersect_segment_point(const segment<numeric_type> &s, const point<numeric_type> &p)
    {
        return sign(abs(s.p - p) + abs(s.q - p) - abs(s.q - s.p)) <= 0;
    }

    template <typename numeric_type>
    point<numeric_type> projection(const line<numeric_type> &l, const point<numeric_type> &p)
    {
        double t = dot(p - l.p, l.p - l.q) / norm(l.p - l.q);
        return l.p + t * (l.p - l.q);
    }

    template <typename numeric_type, typename float_type = double>
    float_type distance_segment_point(const segment<numeric_type> &s, const point<numeric_type> &p)
    {
        const point<numeric_type> r = projection(s, p);
        if (intersect_segment_point(s, r))
            return abs(r - p);
        return std::min(abs(s.p - p), abs(s.q - p));
    }

    template <typename numeric_type, typename float_type = double>
    float_type distance_segment_segment(const segment<numeric_type> &s, const segment<numeric_type> &t)
    {
        if (intersect_segment_segment(s, t))
            return 0;

        return std::min(std::min(distance_segment_point(s, t.p), distance_segment_point(s, t.q)),
                        std::min(distance_segment_point(t, s.p), distance_segment_point(t, s.q)));
    }

} 
 
#include <random>

#define endl '\n'

using namespace asl;
using namespace std;

void solve()
{
    segment<double> a, b;
    cin >> a >> b;

    auto r = distance_segment_segment(a, b);
    cout << fixed << r << endl;
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.precision(10);

    int t;
    cin >> t;

    for (int i = 0; i < t; ++i)
    {
        solve();
    }

    return 0;
}





Measured memory_bytes: 3304