#include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>

using namespace std;

#define FOR(i,k,n) for(int i=(k); i<(int)(n); ++i)
#define REP(i,n) FOR(i,0,n)
#define FORIT(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)

template<class T> void debug(T begin, T end){ for(T i = begin; i != end; ++i) cerr<<*i<<" "; cerr<<endl; }
inline bool valid(int x, int y, int W, int H){ return (x >= 0 && y >= 0 && x < W && y < H); }

typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

#include <complex>
typedef complex<double> Point;
int sign(double a){
  if(a > EPS) return +1;
  if(a < -EPS) return -1;
  return 0;
}

struct Circle{
  Point p;
  double r;
  Circle() {}
  Circle(Point p, double r) : p(p), r(r) {}
};
struct Line : public vector<Point> {
  Line(const Point& a, const Point& b) {
    push_back(a); push_back(b);
  }
  Point vector() const {
    return back() - front();
  }
};

double dot(Point a, Point b){
  return real(conj(a) * b);
}
double cross(Point a, Point b){
  return imag(conj(a) * b);
}

Point projection(const Line& l, const Point& p){
  double t = dot(p - l[0], l.vector()) / norm(l.vector());
  return l[0] + t * l.vector();
}

vector<Point> crosspointLC(const Line &l, const Circle &c) {
  vector<Point> ret;
  Point center = projection(l, c.p);
  double d = abs(center - c.p);
  double t = sqrt(c.r * c.r - d * d);
  if (isnan(t)) { return ret; }
  Point vect = l.vector();
  vect /= abs(vect);
  ret.push_back(center - vect * t);
  if (t > EPS) {
    ret.push_back(center + vect * t);
  }
  return ret;
}

vector<Point> crosspointCC(const Circle &c1, const Circle &c2) {
  vector<Point> ret;
  double d = abs(c1.p - c2.p);
  if(sign(abs(c1.r - c2.r) - d) >= 0) return ret;
  double x = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
  Point start = c1.p + (c2.p - c1.p) / d * x;
  Point vect = (c1.p - c2.p) * Point(0.0, 1.0);
  return crosspointLC(Line(start, start + vect), c1);
}
enum{ OUT, ON, IN };
int contains(const Circle& C, const Point& p){
  double d = abs(C.p - p);
  if(sign(d - C.r) > 0) return OUT;
  if(sign(d - C.r) == 0) return ON;
  return IN;
}

int main(){
  int N;
  while(cin >> N && N){
    vector<Point> ps(N);
    vector<double> l(N);
    REP(i, N) cin >> ps[i].real() >> ps[i].imag() >> l[i];
    double min_length = l[0];
    REP(i, N) min_length = min(min_length, l[i]);
    double lb = 1, ub = min_length;
    REP(_, 100){
      double h = (ub + lb) * 0.5;
      vector<Circle> cs(N);
      REP(i, N) cs[i].p = ps[i];
      REP(i, N) cs[i].r = sqrt(l[i] * l[i] - h * h);
      vector<Point> cand = ps;
      REP(i, N) FOR(j, i + 1, N){
        vector<Point> cross = crosspointCC(cs[i], cs[j]);
        FORIT(it, cross) cand.push_back(*it);
      }
      bool ok = false;
      REP(i, cand.size()){
        Point p = cand[i];
        int cnt = 0;
        REP(j, N){
          if(contains(cs[j], p) != OUT) cnt++;
        }
        if(cnt == N) ok = true;
      }
      if(ok) lb = h;
      else ub = h;
    }
    printf("%.12f\n", (ub + lb) * 0.5);
  }
  return 0;
}

Measured memory_bytes: 1284