#include <cstdio>
#include <cmath>
#include <cfloat>
#include <cstring>
#include <cassert>
#include <vector>
#include <algorithm>
using namespace std;
 
/* double extention Library. */
 
const double EPS = 1e-8;
 
bool eq(double a, double b)
{
    return (fabs(a - b) <= EPS);
}
 
bool lt(double a, double b)
{
    return (a - b < -EPS);
}
 
bool leq(double a, double b)
{
    return (lt(a, b) || eq(a, b));
}
 
bool gt(double a, double b)
{
    return (a - b > +EPS);
}
 
bool geq(double a, double b)
{
    return (gt(a, b) || eq(a, b));
}
 
/* 2-D Geometry Library. */
 
class Point{
public:
    double x, y;
    Point (double x = 0, double y = 0): x(x), y(y){}
    Point operator + (Point p){
        return (Point(x + p.x, y + p.y));
    }
    Point operator - (Point p){
        return (Point(x - p.x, y - p.y));
    }
    Point operator * (double a){
        return (Point(x * a, y * a));
    }
    double abs(){
        return (sqrt(norm()));
    }
    double norm(){
        return (x * x + y * y);
    }
    bool operator < (const Point &p) const {
        return (x != p.x ? x < p.x : y < p.y);
    }
    bool operator == (const Point &p) const {
        return (fabs(x - p.x) < EPS && fabs(y - p.y) < EPS);
    }
    bool operator != (const Point &p) const {
        return (!(*this == p));
    }
};
 
typedef Point Vector;
typedef vector<Point> Polygon;
 
double norm(Vector a)
{
    return (a.x * a.x + a.y * a.y);
}
 
double abs(Vector a)
{
    return (sqrt(norm(a)));
}
 
double dot(Vector a, Vector b)
{
    return (a.x * b.x + a.y * b.y);
}
 
double cross(Vector a, Vector b)
{
    return (a.x * b.y - a.y * b.x);
}
 
static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;
 
int ccw(Point p0, Point p1, Point p2){
    Vector a = p1 - p0;
    Vector b = p2 - p0;
    if (cross(a, b) > EPS)  return (COUNTER_CLOCKWISE);
    if (cross(a, b) < -EPS) return (CLOCKWISE);
    if (dot(a, b) < -EPS)   return (ONLINE_BACK);
    if (norm(a) < norm(b))  return (ONLINE_FRONT);
    return (ON_SEGMENT);
}
 
bool isIntersect(Point p1, Point p2, Point p3, Point p4){
    return (ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0 &&
             ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0 );
}
 
 
 
bool isInside(Polygon gon, Point p)
{
    for (int i = 0; i < gon.size(); i++){
        if (ccw(gon[i], gon[(i + 1) % gon.size()], p) == CLOCKWISE) return (false);
    }
    return (true);
}
 
Point unitVector(Vector t)
{
    double u = abs(t);
    return (Point(t.x / u , t.y / u));
}
 
double getCos(Vector a, Vector b)
{
    return (dot(a, b) / (abs(a) * abs(b)));
}
 
double getSin(Point a , Point b)
{
    double t = getCos(a, b);
    return (sqrt(1.0 - t * t));
}
 
double getArg(Vector v)
{
    return (atan2(v.y, v.x));
}
 
double getDistPL(Point p, Point a, Point b)
{
    return (fabs(cross(b - a, p - a)) / abs(b - a));
}
 
double getDistPS(Point p, Point a, Point b)
{
    if(dot(b - a, p - a) < EPS) return (abs(p - a));
    if(dot(a - b, p - b) < EPS) return (abs(p - b));
    return (getDistPL(p, a, b));
}
 
Point interPointS(Point a1 , Point a2 , Point b1 , Point b2)
{
    Point b = b2 - b1;
    double d1 = fabs(cross(b, a1 - b1));
    double d2 = fabs(cross(b, a2 - b1));
    double t = d1 / (d1 + d2);
    Point a = a2 - a1;
    Point v = a * t;
    return (a1 + v);
}
 
Point interPointL(Point a1 , Point a2 , Point b1 , Point b2)
{
    Point a = a2 - a1;
    Point b = b2 - b1;
    double t = cross(b, b1 - a1) / cross(b, a);
    Point v = a * t;
    return (a1 + v);
}
 
void interPointLC(Point a, Point b, Point c, double r, Point ans[])
{
    if (getDistPL(c, a, b) > r + EPS) return;
    Point v = unitVector(b - a);
    double delta = dot(v, a - c) * dot(v, a - c) - abs(a - c) * abs(a - c) + r * r;
    double t = -dot(v, a - c);
    double s = sqrt(delta);
    ans[0] = a + v * (t + s);
    ans[1] = a + v * (t - s);
}
 
Point xTranslate(Point t, double k)
{
    return (Point(t.x, 2 * k - t.y));
}
 
Point yTranslate(Point t, double k)
{
    return (Point(2 * k - t.x, t.y));
}
 
Point oTranslate(Point t, Point k)
{
    return (k + (k - t));
}
 
Point rotate(Point t , Point p , double r)
{
    double ta=cos(r)*(t.x-p.x)-sin(r)*(t.y-p.y)+p.x;
    double tb=sin(r)*(t.x-p.x)+cos(r)*(t.y-p.y)+p.y;
    return Point(ta , tb);
}
 
void interPointCC(Point a , double ra , Point b , double rb , Point ans[])
{
    double di=fabs(abs(a-b));
    if(di > ra+rb || di < fabs(ra-rb)) return;
    double t=(ra*ra-rb*rb+di*di)/(di+di);
    double rd=acos(t/ra);
 
    Point dv=unitVector(b-a);
    Point g1=rotate(dv , Point(0,0) , rd);
    Point g2=rotate(dv , Point(0,0) , -rd);
    ans[0]=a+g1*ra;
    ans[1]=a+g2*ra;
}
 
Point normalVector(Point p,Point a,Point b)
{
    Point v=unitVector(b-a);
    v = cross(v , p-a) > 0 ?  Point(v.y,(-1)*v.x) : Point((-1)*v.y , v.x);
    return v*getDistPL(p,a,b);
}
 
Point fTranslate(Point t , Point a , Point b)
{
    return t+normalVector(t,a,b)*2;
}
 
double area(Point a, Point b, Point c){
    return fabs(cross(c-a , b-a)*0.5);
}
 
double polygonArea(Polygon t){
    double ans = 0.0;
    for (unsigned int i = 0; i < t.size(); i++)
        ans += cross(t[i] , t[(i + 1) % t.size()]);
    return (ans / 2);
}
 
Polygon conhel(Polygon& ps)
{
    sort(ps.begin(), ps.end());
    int k = 0, n = static_cast<int>(ps.size());
    Polygon qs(n * 2);
     
    for (int i = 0; i < n; i++){
      while (k > 1 && cross(qs[k - 1] - qs[k - 2], ps[i] - qs[k - 1]) < EPS) k--;
      qs[k++] = ps[i];
    }
 
    for (int i = n - 2, t = k; i >= 0; i--){
      while (k > t && cross(qs[k - 1] - qs[k - 2], ps[i] - qs[k - 1]) < EPS) k--;
      qs[k++] = ps[i];
    }
 
    qs.resize(k - 1);
    return (qs);
}

int n;
Point p[10];
double l[10];

bool check(double z)
{
	for (int i = 0; i < n; i++)
		if (lt(l[i] * l[i] - z * z, 0)) return (false);
	
	vector<Point> check;
	for (int i = 0; i < n; i++)
		check.push_back(p[i]);
	
	for (int i = 0; i < n; i++){
		for (int j = i + 1; j < n; j++){
			Point ans[2];
			ans[0] = ans[1] = Point(-999, -999);
			interPointCC(p[i], sqrt(max(0.0, l[i] * l[i] - z * z)), p[j], sqrt(max(0.0, l[j] * l[j] - z * z)), ans);
			for (int k = 0; k < 2; k++){
				if (!eq(ans[k].x, -999)) check.push_back(ans[k]);
			}
		}
	}
	for (int i = 0; i < check.size(); i++){
		bool ok = true;
		for (int j = 0; j < n; j++){
			if (gt(norm(check[i] - p[j]), l[j] * l[j] - z * z))
				ok = false;
		}
		if (ok){
			return (true);
		}
	}
	
	return (false);
}

int main()
{
	while (scanf("%d", &n) && n){
		
		for (int i = 0; i < n; i++){
			scanf("%lf %lf %lf", &p[i].x, &p[i].y, &l[i]);
		}
		
		double lo = 0.0, hi = 300.0;
		for (int i = 0; i < 100; i++){
			double mid = (lo + hi) / 2.0;
			if (check(mid)) lo = mid;
			else hi = mid;
		}
		printf("%lf\n", (lo + hi) / 2);
	}
}

Measured memory_bytes: 1220