code: public static int getNumericType(int t1, int t2, boolean canBeNonNumeric) {
          int localt1 = t1;
          int localt2 = t2;
          if (localt1 == localt2)
              return localt1;
  
          if (canBeNonNumeric && (localt1 == NONNUMERIC || localt2 == NONNUMERIC || localt1 == CHAR || localt2 == CHAR))
              return NONNUMERIC;
          // Try to interpret strings as doubles...
          if (localt1 == NONNUMERIC) {
              localt1 = DOUBLE;
          }
          // Try to interpret strings as doubles... 
          if (localt2 == NONNUMERIC) {
              localt2 = DOUBLE;
          }
  
          if (localt1 >= MIN_REAL_TYPE) {
              if (localt2 >= MIN_REAL_TYPE)
                  return Math.max(localt1, localt2);
              if (localt2 < INT)
                  return localt1;
              if (localt2 == BIGINT)
                  return BIGDEC;
              return Math.max(DOUBLE, localt1);
          } else if (localt2 >= MIN_REAL_TYPE) {
              if (localt1 < INT)
                  return localt2;
              if (localt1 == BIGINT)
                  return BIGDEC;
              return Math.max(DOUBLE, localt2);
          } else
              return Math.max(localt1, localt2);
      }
docs: Returns the constant from the NumericTypes interface that best expresses the type
  of an operation, which can be either numeric or not, on the two given types.
  
  @param localt1         type of one argument to an operator
  @param localt2         type of the other argument
  @param canBeNonNumeric whether the operator can be interpreted as non-numeric
  @return the appropriate constant from the NumericTypes interface