#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;
const double EPS = 1e-8;

struct Point {
	double x, y;
	Point() : x(0), y(0) { }
	Point(double x, double y) : x(x), y(y) { }
	Point operator+(const Point &p) const { return Point(x + p.x, y + p.y); }
	Point operator-(const Point &p) const { return Point(x - p.x, y - p.y); }
	Point operator*(double s) const { return Point(x * s, y * s); }
	Point operator/(double s) const { return Point(x / s, y / s); }
	Point &operator+=(const Point &p){ x += p.x; y += p.y; return *this; }
	Point &operator-=(const Point &p){ x -= p.x; y -= p.y; return *this; }
	Point &operator*=(double s){ x *= s; y *= s; return *this; }
	Point &operator/=(double s){ x /= s; y /= s; return *this; }
	bool operator==(const Point &p) const { return x == p.x && y == p.y; }
	bool operator!=(const Point &p) const { return x != p.x || y != p.y; }
	bool operator<(const Point &p) const {
		return (x == p.x) ? (y < p.y) : (x < p.x);
	}
};
inline Point operator*(double s, const Point &p){ return p * s; }

inline double norm(const Point &p){ return p.x * p.x + p.y * p.y; }
inline double abs(const Point &p){ return sqrt(norm(p)); }
inline double arg(const Point &p){ return atan2(p.y, p.x); }
inline Point unit(const Point &p){ return p / abs(p); }
inline Point ortho(const Point &p){ return Point(-p.y, p.x); }
inline double cross(const Point &a, const Point &b){
	return a.x * b.y - a.y * b.x;
}
inline double dot(const Point &a, const Point &b){
	return a.x * b.x + a.y * b.y;
}

struct Circle {
	Point p;
	double r;
	Circle() : p(), r(0) { }
	Circle(Point p, double r) : p(p), r(r) { }
	bool operator==(const Circle &c) const { return p == c.p && r == c.r; }
	bool operator!=(const Circle &c) const { return p != c.p || r != c.r; }
	bool operator<(const Circle &c) const {
		return (p == c.p) ? (r < c.r) : (p < c.p);
	}
};

inline double heron(double a, double b, double c){
	double s = (a + b + c) / 2.0;
	return sqrt(s * (s - a) * (s - b) * (s - c));
}

inline bool intersect(const Circle &a, const Circle &b){
	const double d = abs(a.p - b.p);
	return (d >= abs(a.r - b.r) - EPS) && (d <= a.r + b.r + EPS);
}
inline vector<Point> crossing_points(const Circle &a, const Circle &b){
	const double l = abs(b.p - a.p);
	const double d = 2.0 * heron(l, a.r, b.r) / l;
	const double t = sqrt(a.r * a.r - d * d);
	const Point v = t * unit(b.p - a.p);
	const Point w = d * unit(ortho(v));
	return vector<Point>({ a.p + v + w, a.p + v - w });
}

int main(){
	ios_base::sync_with_stdio(false);
	cout << setiosflags(ios::fixed) << setprecision(10);
	while(true){
		int n;
		cin >> n;
		if(n == 0){ break; }
		vector<Circle> anchors(n);
		double min_length = 1e10;
		for(int i = 0; i < n; ++i){
			Circle &c = anchors[i];
			cin >> c.p.x >> c.p.y >> c.r;
			min_length = min(min_length, c.r);
		}
		double left = 0.0, right = min_length;
		for(int iter = 0; iter < 100; ++iter){
			const double center = (left + right) / 2.0;
			const double h = center;
			vector<Circle> areas(n);
			for(int i = 0; i < n; ++i){
				const Circle &c = anchors[i];
				const double r = sqrt(c.r * c.r - h * h);
				areas[i] = Circle(c.p, r);
			}
			vector<Point> candidates;
			for(int i = 0; i < n; ++i){
				candidates.push_back(areas[i].p);
				for(int j = i + 1; j < n; ++j){
					if(!intersect(areas[i], areas[j])){ continue; }
					const vector<Point> cp =
						crossing_points(areas[i], areas[j]);
					candidates.push_back(cp[0]);
					candidates.push_back(cp[1]);
				}
			}
			const int m = candidates.size();
			bool accept = false;
			for(int i = 0; !accept && i < m; ++i){
				const Point p = candidates[i];
				bool flag = true;
				for(int j = 0; flag && j < n; ++j){
					const Circle c(areas[j].p, areas[j].r + EPS);
					if(norm(c.p - p) > c.r * c.r){ flag = false; }
				}
				if(flag){ accept = true; }
			}
			if(accept){
				left = center;
			}else{
				right = center;
			}
		}
		cout << left << endl;
	}
	return 0;
}

Measured memory_bytes: 1324