#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;

template<class T> inline void chmax(T& a, const T& b) { if(b > a) a = b; }
template<class T> inline void chmin(T& a, const T& b) { if(b < a) a = b; }

const double EPS = 1e-9;
const int INF = 1000000;

struct point {
	double x, y;
	point(double x = 0.0, double y = 0.0):x(x), y(y) {}
	point(const point& p):x(p.x), y(p.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* (const double s) const {
		return point(x * s, y * s);
	}

	point operator* (const point& p) const {
		return point(x * p.x - y * p.y, x * p.y + y * p.x);
	}

	point operator/ (const double s) const {
		return point(x / s, y / s);
	}

	bool operator< (const point& p) const {
		return x + EPS < p.x || abs(x - p.x) < EPS && y + EPS < p.y;
	}

	bool operator== (const point& p) const {
		return abs(x - p.x) < EPS && abs(y - p.y) < EPS;
	}
};

inline double abs(const point& p) {
	return sqrt(p.x * p.x + p.y * p.y);
}

inline double norm(const point& p) {
	return p.x * p.x + p.y * p.y;
}

inline double dot(const point& l, const point& r) {
	return l.x * r.x + l.y * r.y;
}

inline double cross(const point& l, const point& r) {
	return l.x * r.y - l.y * r.x;
}

struct segment {
	point a, b;
	segment(point a, point b):a(a), b(b){}
};

struct circle {
	point c;
	double r;
	circle(point c, double r):c(c), r(r){}
};

inline int ccw(const point& a, point b, point c) {
	b = b - a;
	c = c - a;
	const double tmp = cross(b, c);
	if(tmp > EPS) return 1; // ccw
	if(tmp < -EPS) return -1; // cw
	if(dot(b, c) < 0) return 2; // c, a, b 順に一直線上
	if(norm(b) < norm(c)) return -2; // a, b, c 順に一直線上
	return 0; //a, c, b 順で一直線上
}

inline bool intersect(const segment& s, const segment& t) {
	return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 &&
		ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

inline bool intersect(const segment& s, const point& p) {
	return ccw(s.a, s.b, p) == 0;
}

inline bool intersect(const circle& c, const circle& d) {
	return abs(c.c - d.c) <= c.r + d.r && abs(c.c - d.c) >= abs(c.r - d.r);
}

inline point crosspoint(const segment& s, const segment& t) {
	if(!intersect(s, t)) // 交点を持たない
		return point(INF, INF); // 用改善

	const double tmp = cross(s.b - s.a, t.b - t.a);
	if(abs(tmp) < EPS) { // 一直線上
		if(intersect(s, t.a)) return t.a;
		if(intersect(s, t.b)) return t.b;
		if(intersect(t, s.a)) return s.a;
		return s.b;
	}

	return t.a + (t.b - t.a) * cross(s.b - s.a, s.b - t.a) * (1.0 / tmp);
}

//先に，intersectを用いて交差判定を行うこと
inline vector<point> crosspoint(const circle &c, const circle& d) {
	vector<point> res;
	if(abs(c.c - d.c) < EPS) // 中心の座標が同じ
		return res;

	const double tmp = abs(c.c - d.c);
	const double rc = (tmp * tmp + c.r * c.r - d.r * d.r) / (tmp + tmp);
	const double rs = sqrt(c.r * c.r - rc * rc);
	const point diff = (d.c - c.c) / tmp;
	res.push_back(point(c.c + diff * point(rc, rs)));
	res.push_back(point(c.c + diff * point(rc, -rs)));
	return res;
}

int main() {
	for(int n; scanf("%d", &n), n;) {
		vector<circle> cs;
		cs.reserve(n);
		vector<point> candidates;
		candidates.reserve(4 * n);

		for(int i = 0; i < n; ++i) {
			int x, y, l;
			scanf("%d %d %d", &x, &y, &l);
			cs.push_back(circle(point(x, y), l));
			candidates.push_back(cs[i].c);
		}

		vector<segment> segs;
		segs.reserve(100000);
		for(int i = 0; i < n; ++i) {
			for(int j = i + 1; j < n; ++j) {
				if(!intersect(cs[i], cs[j]))
					continue;

				vector<point> ps = crosspoint(cs[i], cs[j]);
				if(ps.size() == 0)
					continue;

				candidates.push_back((ps[0] + ps[1]) / 2.0);
				segs.push_back(segment(ps[0], ps[1]));
			}
		}

		const int m = segs.size();
		for(int i = 0; i < m; ++i) {
			for(int j = i + 1; j < m; ++j) {
				point p = crosspoint(segs[i], segs[j]);
				if(p.x >= INF)
					continue;

				candidates.push_back(p);
			}
		}

		double ans = 1.0;
		for(int i = 0; i < (int)candidates.size(); ++i) {
			double mn = INF;
			for(int j = 0; j < n; ++j) {
				const double d = abs(cs[j].c - candidates[i]);
				chmin(mn, cs[j].r * cs[j].r - d * d);
			}
			chmax(ans, mn);
		}

		printf("%.7lf\n", sqrt(ans));
	}

	return EXIT_SUCCESS;
}

Measured memory_bytes: 1152