package main

import (
	"strings"
	"fmt"
	"bufio"
	"strconv"
	"os"
	"math"
)

//
func subVector(p1, p2 []float64) []float64 {
	return []float64{
		p1[0] - p2[0],
		p1[1] - p2[1],
	}
}

//
func dotVector(p1, p2 []float64) float64 {
	return p1[0]*p2[0] + p1[1]*p2[1]
}

//
func crossVector(p1, p2 []float64) float64 {
	return p1[0]*p2[1] - p1[1]*p2[0]
}

//
func absVector(p []float64) float64 {
	return math.Sqrt(p[0]*p[0] + p[1]*p[1])
}

//
func norrmalize(p []float64) float64 {
	return p[0]*p[0] + p[1]*p[1]
}

//
// 1: p1-p2より反時計周り側にp3
// 2: p1-p2より時計周り側にp3
// 3: p1-p2直線上、p2の先にp3
// 4: p1-p2直線上、p1の前にp3
// 5: p1-p2線分上にp3
func checkClockWise(p1, p2, p3 []float64) int {
	p1p2 := subVector(p2, p1)
	p1p3 := subVector(p3, p1)
	if crossVector(p1p2, p1p3) > 0 {
		return 1
	} else if crossVector(p1p2, p1p3) < 0 {
		return 2
	} else if dotVector(p1p2, p1p3) < 0 {
		return 4
	} else if norrmalize(p1p2) < norrmalize(p1p3) {
		return 3
	}
	return 5
}

func strSliceToFloat64(strSlice []string) []float64 {
	n := len(strSlice)
	sliceFloat := make([]float64, n)
	for i := 0; i < n; i++ {
		v, _ := strconv.Atoi(strSlice[i])
		sliceFloat[i] = float64(v)
	}
	return sliceFloat
}

func projection(p1, p2, p []float64) []float64 {
	// p - p1
	v1 := []float64{
		p[0] - p1[0],
		p[1] - p1[1],
	}
	// p2 - p1
	v2 := []float64{
		p2[0] - p1[0],
		p2[1] - p1[1],
	}

	dot := v1[0]*v2[0] + v1[1]*v2[1]
	// cross := v1[0]*v2[1] - v1[1]*v2[0]
	normal := v2[0]*v2[0] + v2[1]*v2[1]

	a := dot / normal

	result := []float64{
		p1[0] + v2[0]*a,
		p1[1] + v2[1]*a,
	}
	return result
}

func reflection(p1, p2, p []float64) []float64 {
	prj := projection(p1, p2, p)

	// p to reflection
	toCrossPoint := []float64{
		2 * (prj[0] - p[0]),
		2 * (prj[1] - p[1]),
	}

	result := []float64{
		p[0] + toCrossPoint[0],
		p[1] + toCrossPoint[1],
	}

	return result
}

//
func distancePoint(p1, p2 []float64) float64 {
	return absVector(subVector(p2, p1))
}

//
func distanceToStraightLine(p1, p2, p []float64) float64 {
	v1 := subVector(p, p1)
	v2 := subVector(p2, p1)
	return math.Abs(crossVector(v1, v2)) / absVector(v2)
}

//
func distanceToLineSegment(p1, p2, p []float64) float64 {
	v1 := subVector(p1, p2)
	v2 := subVector(p2, p1)

	if dotVector(subVector(p, p1), v2) <= 0 {
		return distancePoint(p1, p)
	} else if dotVector(subVector(p, p2), v1) <= 0 {
		return distancePoint(p2, p)
	}
	return distanceToStraightLine(p1, p2, p)
}

//
func distanceLineSegment(a1, a2, b1, b2 []float64) float64 {
	if isInterSect(a1, a2, b1, b2) {
		return 0.0
	}
	result := distanceToLineSegment(a1, a2, b1)
	result = math.Min(result, distanceToLineSegment(a1, a2, b2))
	result = math.Min(result, distanceToLineSegment(b1, b2, a1))
	result = math.Min(result, distanceToLineSegment(b1, b2, a2))
	return result
}

//
func isInterSect(a1, a2, b1, b2 []float64) bool {
	c1 := checkClockWise(a1, a2, b1)
	c2 := checkClockWise(a1, a2, b2)

	c3 := checkClockWise(b1, b2, a1)
	c4 := checkClockWise(b1, b2, a2)

	conv := func(v int) int {
		if v == 2 {
			return -1
		} else if v == 5 {
			return 0
		} else if v == 4 {
			return -1
		}
		return v
	}

	c1 = conv(c1)
	c2 = conv(c2)
	c3 = conv(c3)
	c4 = conv(c4)

	isInterSect := (c1*c2) <= 0 && (c3*c4) <= 0
	return isInterSect
}

// solve
func solve(sc *bufio.Scanner) {
	sc.Scan()
	n, _ := strconv.Atoi(sc.Text())

	for i := 0; i < n; i++ {
		sc.Scan()
		slice := strSliceToFloat64(strings.Split(sc.Text(), " "))

		p1 := []float64{slice[0], slice[1]}
		p2 := []float64{slice[2], slice[3]}
		p3 := []float64{slice[4], slice[5]}
		p4 := []float64{slice[6], slice[7]}

		result := distanceLineSegment(p1, p2, p3, p4)

		fmt.Printf("%.10f\n", result)
	}
}

// main
func main() {
	solve(bufio.NewScanner(os.Stdin))
}



Measured memory_bytes: 1364