#include <vector>
#include <iostream>
#include <utility>
#include <algorithm>
#include <string>
#include <deque>
#include <tuple>
#include <queue>
#include <functional>
#include <cmath>
#include <iomanip>
#include <map>
#include <numeric>
#include <unordered_map>
#include <unordered_set>
#include <complex>
#include <iterator>
#include <array>
#include <chrono>
//cin.sync_with_stdio(false);
//streambuf
using namespace std;
typedef long long ll;
typedef double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<double, double> pdd;
using vi = vector<int>;
using vll = vector<ll>;
using vpii = vector<pii>;
template<class T, int s>using va = vector<array<T, s>>;
template<class T, class T2> using umap = unordered_map<T, T2>;
template<class T> using uset = unordered_set<T>;
template<class T, class S> void cmin(T &a, const S&b) { if (a > b)a = b; }
template<class T, class S> void cmax(T &a, const S&b) { if (a < b)a = b; }
#define ALL(a) a.begin(),a.end()
#define rep(i,a) for(int i=0;i<a;i++)
#define rep1(i,a) for(int i=1;i<=a;i++)
#define rrep(i,a) for(int i=a-1;i>=0;i--)
#define rrep1(i,a) for(int i=a;i;i--)
const ll mod = 1000000007;
#ifndef INT_MAX
const int INT_MAX = numeric_limits<signed>().max();
#endif
template<class T>using heap = priority_queue<T, vector<T>, greater<T>>;
template<class T>using pque = priority_queue<T, vector<T>, function<T(T, T)>>;
template <class T>
inline void hash_combine(size_t & seed, const T & v) {
    hash<T> hasher;
    seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
  
const ld eps = 1e-11, pi = acos(-1.0);
typedef complex<ld> P;
typedef vector<P> VP;
ld dot(P a, P b) { return real(conj(a) * b); }
ld cross(P a, P b) { return imag(conj(a) * b); }
   
namespace std {
    bool operator<(const P &a, const P &b) {
        return abs(a.real() - b.real()) < eps ? a.imag() < b.imag() : a.real() < b.real();
    }
}
   
struct L { P a, b; };//line->l,segment->s
struct C { P p; ld r; };
   
int ccw(P a, P b, P c) {
    b -= a; c -= a;
    if (cross(b, c) > 0) return 1;   // counter clockwise
else return -1;
}
int main() {
    int n;
    _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
    _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
    cin.sync_with_stdio(0);
    while (cin >> n, n) {
        va<float, 3> bl(n);
        rep(i, n)rep(j, 3)cin >> bl[i][j];
        //va<double, 3> h;
        double ans = 1e9;
        int mina = 0;
        rep(i, n)if (ans > bl[i][2])ans = bl[i][2], mina = i;
        ans *= ans;
        rep(i, n) {
            rep(j, i) {
                double l = sqrt(double(bl[i][0] - bl[j][0])*(bl[i][0] - bl[j][0]) + (bl[i][1] - bl[j][1])*(bl[i][1] - bl[j][1]));
                double a = ((bl[j][2] * bl[j][2] - bl[i][2] * bl[i][2]) / l + l)*0.5;
                double x = (bl[i][0] * a + bl[j][0] * (l - a)) / l, y = (bl[i][1] * a + bl[j][1] * (l - a)) / l, z = bl[j][2] * bl[j][2] - a*a;
                if (z < 0)continue;
                if (z<ans&&a > 0 && a < l)ans = z;
                double x00 = bl[i][0] - bl[j][0], x01 = bl[i][1] - bl[j][1], x02 = -bl[i][2] * bl[i][2] + bl[j][2] * bl[j][2] + bl[i][0] * bl[i][0] + bl[i][1] * bl[i][1] - bl[j][0] * bl[j][0] - bl[j][1] * bl[j][1];
                if (x01 != 0) {
                    double rv = 1 / x01;
                    rep(k, j) {
                        double x10 = bl[i][0] - bl[k][0], x11 = bl[i][1] - bl[k][1], x12 = -bl[i][2] * bl[i][2] + bl[k][2] * bl[k][2] + bl[i][0] * bl[i][0] + bl[i][1] * bl[i][1] - bl[k][0] * bl[k][0] - bl[k][1] * bl[k][1];
                        double a, b, c;
                        double rv2 = x10 * x01 - x11*x00;
                        if (rv2 == 0)continue;
                        rv2 = 1 / rv2;
                        a = rv2*(x12 * x01 - x11 * x02)*0.5;
                        b = (x02 * 0.5 - a*x00)*rv;
                        c = bl[i][2] * bl[i][2] - (a - bl[i][0])*(a - bl[i][0]) - (b - bl[i][1])*(b - bl[i][1]);
                        if (c < 0)continue;
                        if (c >= ans)continue;
                        int cc = ccw(P(a, b), P(bl[i][0], bl[i][1]), P(bl[j][0], bl[j][1]));
                        if (cc == ccw(P(a, b), P(bl[j][0], bl[j][1]), P(bl[k][0], bl[k][1])) && cc == ccw(P(a, b), P(bl[k][0], bl[k][1]), P(bl[i][0], bl[i][1])))ans = c;
                    }
                }
                else {
                    double a = x02*0.5 / x00;
                    double c_ = bl[i][2] * bl[i][2] - (a - bl[i][0])*(a - bl[i][0]);
                    rep(k, j) {
                        double x11 = bl[i][1] - bl[k][1];
                        if (x11 == 0)continue;
                        double x10 = bl[i][0] - bl[k][0],x12 = -bl[i][2] * bl[i][2] + bl[k][2] * bl[k][2] + bl[i][0] * bl[i][0] + bl[i][1] * bl[i][1] - bl[k][0] * bl[k][0] - bl[k][1] * bl[k][1];
                        double b = (x12*0.5 - a*x10) / x11, c;
                        c = c_ - (b - bl[i][1])*(b - bl[i][1]);
                        if (c < 0)continue;
                        if (c >= ans)continue;
                        int cc = ccw(P(a, b), P(bl[i][0], bl[i][1]), P(bl[j][0], bl[j][1]));
                        if (cc == ccw(P(a, b), P(bl[j][0], bl[j][1]), P(bl[k][0], bl[k][1])) && cc == ccw(P(a, b), P(bl[k][0], bl[k][1]), P(bl[i][0], bl[i][1])))ans = c;
                    }
                }
            }
        }
        cout << fixed << setprecision(7) << sqrt(ans) << endl;
    }
}

Measured memory_bytes: 3244