#include <algorithm>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <limits>
#include <vector>
namespace lc {
static const double EPS = 1e-9;
inline double abs(double x){ return std::abs(x); }
inline bool tolerant_eq(double a, double b){ return abs(a - b) < EPS; }
}
namespace lc {
struct Point {
	double x;
	double y;
	explicit Point(const double &x = 0.0, const double &y = 0.0) :
		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*(const Point &p) const {
		return Point(x * p.x - y * p.y, x * p.y + y * p.x);
	}
	Point operator/(double s) const { return Point(x / s, y / s); }
	double abs() const { return sqrt(x * x + y * y); }
	double norm() const { return x * x + y * y; }
};
inline bool tolerant_eq(const Point &a, const Point &b){
	return tolerant_eq(a.x, b.x) && tolerant_eq(a.y, b.y);
}
}
namespace lc {
struct Circle {
	Point c;
	double r;
	explicit Circle(const Point &c = Point(), double r = 0.0) :
		c(c), r(r)
	{ }
	int contains(const Point &p) const {
		const double d2 = (p - c).norm(), r2 = r * r;
		if(d2 > r2){ return 0; }
		if(d2 < r2){ return 1; }
		return -1;
	}
};
inline bool tolerant_eq(const Circle &a, const Circle &b){
	return tolerant_eq(a.c, b.c) && tolerant_eq(a.r, b.r);
}
}
namespace lc {
inline bool intersect(const Circle &a, const Circle &b){
	const double d = (a.c - b.c).abs();
	return d <= a.r + b.r && a.r + d >= b.r && b.r + d >= a.r;
}
}
namespace lc {
inline std::vector<Point> crossing_points(const Circle &a, const Circle &b){
	std::vector<Point> ret;
	if(!intersect(a, b)){ return ret; }
	if(tolerant_eq(a, b)){
		ret.push_back(a.c + Point(a.r, 0.0));
		ret.push_back(a.c + Point(-a.r, 0.0));
		ret.push_back(a.c + Point(0.0, a.r));
	}else{
		const double d = (a.c - b.c).abs();
		const double rc = (d * d + a.r * a.r - b.r * b.r) / (2.0 * d);
		const double rs = sqrt(a.r * a.r - rc * rc);
		const Point diff = (b.c - a.c) / d;
		const Point x = a.c + diff * Point(rc, rs);
		const Point y = a.c + diff * Point(rc, -rs);
		ret.push_back(x);
		if(!tolerant_eq(x, y)){ ret.push_back(y); }
	}
	return ret;
}
}
using namespace std;
inline double pow2(double x){ return x * x; }
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<lc::Point> pegs(n);
		vector<double> ropes(n);
		for(int i = 0; i < n; ++i){
			cin >> pegs[i].x >> pegs[i].y >> ropes[i];
		}
		double left = 0.0, right = *min_element(ropes.begin(), ropes.end());
		for(int iter = 0; iter < 100; ++iter){
			const double center = (left + right) * 0.5;
			vector<lc::Circle> areas(n);
			for(int i = 0; i < n; ++i){
				areas[i] = lc::Circle(
					pegs[i], sqrt(max(0.0, pow2(ropes[i]) - pow2(center))));
			}
			vector<lc::Point> candidates(pegs);
			for(int i = 0; i < n; ++i){
				for(int j = i + 1; j < n; ++j){
					const auto cps = lc::crossing_points(areas[i], areas[j]);
					copy(cps.begin(), cps.end(), back_inserter(candidates));
				}
			}
			bool accept = false;
			for(const auto &p : candidates){
				bool flag = true;
				for(int i = 0; flag && i < n; ++i){
					lc::Circle c(areas[i].c, areas[i].r + lc::EPS);
					if(!c.contains(p)){ flag = false; }
				}
				if(flag){
					accept = true;
					break;
				}
			}
			if(accept){
				left = center;
			}else{
				right = center;
			}
		}
		cout << left << endl;
	}
	return 0;
}

Measured memory_bytes: 1324