예제 #1
0
/** Rounds this Numeric to the given precision, and rounds a half to even */
Numeric::Ptr ATDecimalOrDerivedImpl::roundHalfToEven(const Numeric::Ptr &precision, const DynamicContext* context) const {
  ATDecimalOrDerived::Ptr decimal_precision = (const Numeric::Ptr)precision->castAs(this->getPrimitiveTypeIndex(), context);
  MAPM exp = MAPM(10).pow(((ATDecimalOrDerivedImpl*)(const ATDecimalOrDerived*)decimal_precision)->_decimal);
  MAPM value = _decimal * exp;
  bool halfVal = false;

  // check if we're rounding on a half value 
  if((value-0.5) == (value.floor())) {
    halfVal = true;
  }
  value = _decimal * exp + 0.5;
  value = value.floor();

  // if halfVal make sure what we return has the least significant digit even
  if (halfVal) {
    if(value.is_odd()) {
      value = value - 1;
    }
  }
  value = value / exp;  
  // if integer, return xs:integer, otherwise xs:decimal    
  if(_isInteger) {
    return context->getItemFactory()->createInteger(value, context);
  }
  return context->getItemFactory()->createDecimal(value, context);
}
예제 #2
0
/** Rounds this Numeric to the given precision, and rounds a half to even */
Numeric::Ptr ATFloatOrDerivedImpl::roundHalfToEven(const Numeric::Ptr &precision, const DynamicContext* context) const {
    switch (_state) {
    case NaN:
        return notANumber(context);
    case INF:
        return infinity(context);
    case NEG_INF:
        return negInfinity(context);
    case NEG_NUM:
    case NUM:
        break;
    default: {
        assert(false);
        return 0; // should never get here
    }
    }

    if (isZero() && isNegative())
        return this;

    ATFloatOrDerived::Ptr float_precision = (const Numeric::Ptr)precision->castAs(this->getPrimitiveTypeIndex(), context);
    MAPM exp = MAPM(10).pow(((ATFloatOrDerivedImpl*)(const ATFloatOrDerived*)float_precision)->_float);
    MAPM value = _float * exp;
    bool halfVal = false;

    // check if we're rounding on a half value
    if((value-0.5) == (value.floor())) {
        halfVal = true;
    }
    value = _float * exp + 0.5;
    value = value.floor();

    // if halfVal make sure what we return has the least significant digit even
    if (halfVal) {
        if(value.is_odd()) {
            value = value - 1;
        }
    }
    value = value / exp;

    // the spec doesn't actually say to do this, but djf believes this is the correct way to handle rounding of -ve values which will result in 0.0E0
    // if (value == 0 && isNegative())
    // return negZero(context);
    return newFloat(value, context);
}