Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-227

BigDecimal type does not behave as expected with operators (+, -, ...)

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 1.0-beta-3, 1.0-beta-4
    • 1.0-beta-4
    • None
    • None
    • All

    Description

      Mathmatical operators such as +, -, ... do not behave as expected with java.math.BigDecimal. They are coverted to Integer for + and -.
      For example:
      bd = new java.math.BigDecimal("1.3");
      print 1 + bd;

      Shows 3, not 3.3 as expected.

      From post by Steve Goetze:
      > The DefaultGroovyMethods: plus(Number, Number), minus(Number,
      > Number),
      > multiply(Number, Number), and divide(Number, Number) have coercion
      > techniques that don't work very well for BigDecimal objects
      > (results are
      > generally coerced to Integer types except for divide which returns
      > Double). Would it be possible to change these methods to check for
      > a left or right BigDecimal and preserve? For example:
      >
      > /**
      > * Add two Numbers
      > *
      > * @param left a Number
      > * @param right another Number to add
      > * @return the addition of both Numbers
      > */
      > public static Number plus(Number left, Number right) {
      > /** @todo maybe a double dispatch thing to handle new large
      > numbers? */
      > if (isBigDecimal(left) || isBigDecimal(right))

      { > return asBigDecimal(left).add(asBigDecimal(right)); > }

      > else if (isBigInteger(left) || isBigInteger(right))

      { > return new Double(left.doubleValue() + > right.doubleValue()); > }
      > else if (isFloatingPoint(left) || isFloatingPoint(right)) {> return new Double(left.doubleValue() + > right.doubleValue());> }

      > else if (isLong(left) || isLong(right))

      { > return new Long(left.longValue() + right.longValue()); > }

      > else

      { > return new Integer(left.intValue() + right.intValue()); > }

      > }
      >
      > where:
      >
      > public static boolean isBigDecimal(Number number)

      { > return number instanceof BigDecimal; > }

      >
      > and:
      >
      > public static BigDecimal asBigDecimal(Number n)

      { > return (n instanceof BigDecimal ? (BigDecimal)n : new > BigDecimal(n.toString())); > }

      >
      >
      > divide(Number, Number) could use a default rounding mode of
      > BigDecimal.ROUND_UP.
      >
      > Also, I don't see that literal longs and doubles can be specified ala
      > java with an "L" or "D". If this is something you would consider
      > adding, it would also be nice to be able to specify literal
      > BigDecimals
      > and BigIntegers, perhaps with a "B" suffix.

      Attachments

        1. number_math_2.patch
          29 kB
          Steve Goetze
        2. operators.wiki
          5 kB
          Steve Goetze

        Activity

          People

            goetze Steve Goetze
            bl7385 Brian Larson
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: