code: public static BloomSpecification computeBucketsAndK(double maxFalsePosProb) {
          // Handle the trivial cases
          if (maxFalsePosProb >= probs[minBuckets][minK]) {
              return new BloomSpecification(2, optKPerBuckets[2]);
          }
          if (maxFalsePosProb < probs[maxBuckets][maxK]) {
              return new BloomSpecification(maxK, maxBuckets);
          }
  
          // First find the minimal required number of buckets:
          int bucketsPerElement = 2;
          int K = optKPerBuckets[2];
          while (probs[bucketsPerElement][K] > maxFalsePosProb) {
              bucketsPerElement++;
              K = optKPerBuckets[bucketsPerElement];
          }
          // Now that the number of buckets is sufficient, see if we can relax K
          // without losing too much precision.
          while (probs[bucketsPerElement][K - 1] <= maxFalsePosProb) {
              K--;
          }
  
          return new BloomSpecification(K, bucketsPerElement);
      }
docs: Given a maximum tolerable false positive probability, compute a Bloom
  specification which will give less than the specified false positive rate,
  but minimize the number of buckets per element and the number of hash
  functions used.  Because bandwidth (and therefore total bitvector size)
  is considered more expensive than computing power, preference is given
  to minimizing buckets per element rather than number of hash functions.
  
  @param maxFalsePosProb The maximum tolerable false positive rate.
  @return A Bloom Specification which would result in a false positive rate
  less than specified by the function call.